Merge "Do not show Provisioning items for IMS if it is not enabled."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 48b1333..7625e78 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1245,6 +1245,10 @@
<action android:name="android.settings.PRIVACY_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.REQUEST_ENABLE_CONTENT_CAPTURE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.privacy.PrivacyDashboardFragment" />
</activity>
@@ -1575,19 +1579,12 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.suggested.category.FINGERPRINT_ENROLL" />
</intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
- </intent-filter>
- <meta-data android:name="com.android.settings.dismiss"
- android:value="5,9,30" />
<meta-data android:name="com.android.settings.require_feature"
android:value="android.hardware.fingerprint" />
<meta-data android:name="com.android.settings.title"
android:resource="@string/suggestion_additional_fingerprints" />
<meta-data android:name="com.android.settings.summary"
android:resource="@string/suggestion_additional_fingerprints_summary" />
- <meta-data android:name="com.android.settings.icon_tintable" android:value="true" />
</activity>
<!-- Note this must not be exported since it returns the password in the intent -->
@@ -1651,8 +1648,7 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
</intent-filter>
- <meta-data android:name="com.android.settings.dismiss"
- android:value="2,6,30" />
+ <meta-data android:name="com.android.settings.dismiss" android:value="2," />
<meta-data android:name="com.android.settings.require_feature"
android:value="android.hardware.fingerprint" />
<meta-data android:name="com.android.settings.title"
@@ -3029,11 +3025,15 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
- <action android:name="android.settings.panel.action.VOLUME" />
+ <action android:name="android.settings.panel.action.NFC" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
- <action android:name="android.settings.panel.action.NFC" />
+ <action android:name="android.settings.panel.action.WIFI" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.settings.panel.action.VOLUME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
diff --git a/res/drawable/ic_face_header.xml b/res/drawable/ic_face_header.xml
index 4493d66..0bf2c07 100644
--- a/res/drawable/ic_face_header.xml
+++ b/res/drawable/ic_face_header.xml
@@ -15,8 +15,9 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
- android:width="24dp"
+ android:height="32dp"
+ android:width="32dp"
+ android:tint="?android:attr/colorPrimary"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M9,11.75A1.25,1.25 0 0,0 7.75,13A1.25,1.25 0 0,0 9,14.25A1.25,1.25 0 0,0 10.25,13A1.25,1.25 0 0,0 9,11.75M15,11.75A1.25,1.25 0 0,0 13.75,13A1.25,1.25 0 0,0 15,14.25A1.25,1.25 0 0,0 16.25,13A1.25,1.25 0 0,0 15,11.75M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,11.71 4,11.42 4.05,11.14C6.41,10.09 8.28,8.16 9.26,5.77C11.07,8.33 14.05,10 17.42,10C18.2,10 18.95,9.91 19.67,9.74C19.88,10.45 20,11.21 20,12C20,16.41 16.41,20 12,20Z" />
diff --git a/res/layout/homepage_condition_footer.xml b/res/layout/homepage_condition_footer.xml
index 56687fe..cc84f52 100644
--- a/res/layout/homepage_condition_footer.xml
+++ b/res/layout/homepage_condition_footer.xml
@@ -29,6 +29,7 @@
android:id="@+id/collapse_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:src="@drawable/ic_expand_less"/>
+ android:src="@drawable/ic_expand_less"
+ android:tint="?android:attr/colorAccent"/>
</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/homepage_condition_header.xml b/res/layout/homepage_condition_header.xml
index a2796ec..5c1b181 100644
--- a/res/layout/homepage_condition_header.xml
+++ b/res/layout/homepage_condition_header.xml
@@ -45,7 +45,8 @@
android:paddingTop="@dimen/homepage_condition_header_indicator_padding_top"
android:paddingStart="@dimen/homepage_condition_header_indicator_padding_start"
android:paddingEnd="@dimen/homepage_condition_header_indicator_padding_end"
- android:src="@*android:drawable/ic_expand_more"/>
+ android:src="@*android:drawable/ic_expand_more"
+ android:tint="?android:attr/colorAccent"/>
</LinearLayout>
diff --git a/res/layout/homepage_slice_tile.xml b/res/layout/homepage_slice_tile.xml
index 807c26b..e95129e 100644
--- a/res/layout/homepage_slice_tile.xml
+++ b/res/layout/homepage_slice_tile.xml
@@ -31,6 +31,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
+ android:animateLayoutChanges="true"
style="@style/SliceViewStyle"/>
<!--dismissal view-->
diff --git a/res/layout/preference_single_target.xml b/res/layout/preference_single_target.xml
new file mode 100644
index 0000000..b4a9de0
--- /dev/null
+++ b/res/layout/preference_single_target.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 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.
+ -->
+
+<!-- Based off preference_two_target.xml with Material ripple moved to parent for full ripple. -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:gravity="center_vertical"
+ android:background="?android:attr/selectableItemBackground"
+ android:clipToPadding="false">
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="start|center_vertical"
+ android:clipToPadding="false"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+ <LinearLayout
+ android:id="@+id/icon_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="start|center_vertical"
+ android:minWidth="56dp"
+ android:orientation="horizontal"
+ android:clipToPadding="false"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp">
+ <androidx.preference.internal.PreferenceImageView
+ android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ settings:maxWidth="48dp"
+ settings:maxHeight="48dp" />
+ </LinearLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp">
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceListItem"
+ android:ellipsize="marquee" />
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/title"
+ android:layout_alignStart="@android:id/title"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary"
+ android:maxLines="10" />
+
+ </RelativeLayout>
+
+ </LinearLayout>
+
+ <include layout="@layout/preference_two_target_divider" />
+
+ <!-- Preference should place its actual preference widget here. -->
+ <LinearLayout
+ android:id="@android:id/widget_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:minWidth="64dp"
+ android:gravity="center"
+ android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/res/layout/vpn_dialog.xml b/res/layout/vpn_dialog.xml
index 71ce0ad..a626205 100644
--- a/res/layout/vpn_dialog.xml
+++ b/res/layout/vpn_dialog.xml
@@ -140,6 +140,46 @@
android:labelFor="@+id/routes"/>
<EditText style="@style/vpn_value" android:id="@+id/routes"
android:hint="@string/vpn_not_used"/>
+
+ <TextView android:id="@+id/vpn_proxy_settings_title"
+ style="@style/vpn_label"
+ android:text="@string/proxy_settings_title"
+ android:labelFor="@+id/vpn_proxy_settings" />
+
+ <Spinner android:id="@+id/vpn_proxy_settings"
+ style="@style/vpn_value"
+ android:prompt="@string/proxy_settings_title"
+ android:entries="@array/vpn_proxy_settings" />
+
+ <LinearLayout
+ android:id="@+id/vpn_proxy_fields"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:visibility="gone" >
+
+ <TextView
+ style="@style/vpn_label"
+ android:text="@string/proxy_hostname_label"
+ android:labelFor="@+id/vpn_proxy_host" />
+
+ <EditText
+ android:id="@+id/vpn_proxy_host"
+ style="@style/vpn_value"
+ android:hint="@string/proxy_hostname_hint"
+ android:inputType="textNoSuggestions" />
+
+ <TextView
+ style="@style/vpn_label"
+ android:text="@string/proxy_port_label"
+ android:labelFor="@+id/vpn_proxy_port" />
+
+ <EditText
+ android:id="@+id/vpn_proxy_port"
+ style="@style/vpn_value"
+ android:hint="@string/proxy_port_hint"
+ android:inputType="number" />
+ </LinearLayout>
</LinearLayout>
<LinearLayout android:id="@+id/login"
diff --git a/res/layout/wifi_button_preference_widget.xml b/res/layout/wifi_button_preference_widget.xml
index 1ecb98c..0999d20 100644
--- a/res/layout/wifi_button_preference_widget.xml
+++ b/res/layout/wifi_button_preference_widget.xml
@@ -23,5 +23,4 @@
android:minHeight="@dimen/min_tap_target_size"
android:layout_gravity="center"
android:background="@null"
- android:visibility="gone"
- android:contentDescription="@string/wifi_add_network" />
+ android:visibility="gone"/>
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index 1ae3bf5..333296c 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -71,7 +71,7 @@
android:layout_centerVertical="true"
android:background="@null"
android:src="@drawable/ic_scan_24dp"
- android:contentDescription="@string/wifi_add_network" />
+ android:contentDescription="@string/wifi_dpp_scan_qr_code"/>
</RelativeLayout>
<LinearLayout android:id="@+id/ssid_too_long_warning"
@@ -307,7 +307,7 @@
android:layout_centerVertical="true"
android:background="@null"
android:src="@drawable/ic_scan_24dp"
- android:contentDescription="@string/wifi_add_network" />
+ android:contentDescription="@string/wifi_dpp_scan_qr_code"/>
</RelativeLayout>
</LinearLayout>
diff --git a/res/layout/wifi_dpp_fragment_header.xml b/res/layout/wifi_dpp_fragment_header.xml
index e8e71d1..364f360 100644
--- a/res/layout/wifi_dpp_fragment_header.xml
+++ b/res/layout/wifi_dpp_fragment_header.xml
@@ -40,27 +40,35 @@
android:src="@drawable/ic_devices_check_circle_green"
android:scaleType="fitCenter"/>
- <TextView
- android:id="@android:id/title"
- style="@style/TextAppearance.EntityHeaderTitle"
- android:layout_width="match_parent"
+ <!-- Add title_summary_container to group content for Talkback -->
+ <LinearLayout
+ android:id="@+id/title_summary_container"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:textAlignment="center"
- android:layout_marginTop="8dp"
- android:paddingStart="32dp"
- android:paddingEnd="32dp"/>
+ android:orientation="vertical"
+ android:focusable="true">
- <TextView
- android:id="@android:id/summary"
- style="@style/TextAppearance.EntityHeaderSummary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="false"
- android:gravity="center_horizontal"
- android:textAlignment="center"
- android:layout_marginTop="2dp"
- android:paddingStart="32dp"
- android:paddingEnd="32dp"/>
+ <TextView
+ android:id="@android:id/title"
+ style="@style/TextAppearance.EntityHeaderTitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textAlignment="center"
+ android:layout_marginTop="8dp"
+ android:paddingStart="32dp"
+ android:paddingEnd="32dp"/>
+ <TextView
+ android:id="@android:id/summary"
+ style="@style/TextAppearance.EntityHeaderSummary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="false"
+ android:gravity="center_horizontal"
+ android:textAlignment="center"
+ android:layout_marginTop="2dp"
+ android:paddingStart="32dp"
+ android:paddingEnd="32dp"/>
+ </LinearLayout>
</LinearLayout>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 6a03582..7e0ba10 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -931,6 +931,14 @@
<item>IPSec VPN with certificates and hybrid authentication</item>
</string-array>
+ <!-- VPN proxy settings. -->
+ <string-array name="vpn_proxy_settings">
+ <!-- No HTTP proxy is used for the current VPN [CHAR LIMIT=25] -->
+ <item>None</item>
+ <!-- Manual HTTP proxy settings are used for the current VPN [CHAR LIMIT=25] -->
+ <item>Manual</item>
+ </string-array>
+
<!-- Match this with the constants in LegacyVpnInfo. --> <skip />
<!-- Status for a VPN network. [CHAR LIMIT=100] -->
<string-array name="vpn_states">
@@ -1357,4 +1365,17 @@
<item>"9"</item>
</string-array>
+ <!-- WiFi calling mode array -->
+ <string-array name="wifi_calling_mode_summaries" translatable="false">
+ <item>@string/wifi_calling_mode_wifi_preferred_summary</item>
+ <item>@string/wifi_calling_mode_cellular_preferred_summary</item>
+ <item>@string/wifi_calling_mode_wifi_only_summary</item>
+ </string-array>
+
+ <!-- WiFi calling mode array without wifi only mode -->
+ <string-array name="wifi_calling_mode_summaries_without_wifi_only" translatable="false">
+ <item>@string/wifi_calling_mode_wifi_preferred_summary</item>
+ <item>@string/wifi_calling_mode_cellular_preferred_summary</item>
+ </string-array>
+
</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index c7bf1c7..e099cf0 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -132,6 +132,11 @@
<attr name="aspectRatio" format="float" />
</declare-styleable>
+ <declare-styleable name="ListWithEntrySummaryPreference">
+ <!-- Summaries of entry -->
+ <attr name="entrySummaries" format="reference" />
+ </declare-styleable>
+
<!-- For UsageView -->
<declare-styleable name="UsageView">
<attr name="android:colorAccent" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index aeeb403..a36d8ab 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -279,6 +279,15 @@
<dimen name="password_requirement_textsize">14sp</dimen>
+ <!-- Visible vertical space we want to show below password edittext field when ime is shown.
+ The unit is sp as it is related to the text size of password requirement item. -->
+ <dimen name="visible_vertical_space_below_password">20sp</dimen>
+
+ <!-- Select dialog -->
+ <dimen name="select_dialog_padding_start">20dp</dimen>
+ <dimen name="select_dialog_item_margin_start">12dp</dimen>
+ <dimen name="select_dialog_summary_padding_bottom">8dp</dimen>
+
<!-- Padding between the donut and the storage summary. -->
<dimen name="storage_summary_padding_end">16dp</dimen>
<!-- Text size of the big number in the donut. -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 93ba354..2f33878 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2157,6 +2157,10 @@
<string name="wifi_dpp_sharing_wifi_with_this_device">Sharing Wi\u2011Fi with this device\u2026</string>
<!-- Hint for Wi-Fi DPP handshake running [CHAR LIMIT=NONE] -->
<string name="wifi_dpp_connecting">Connecting\u2026</string>
+ <!-- Title for the fragment to show that the QR code is for sharing Wi-Fi hotspot network [CHAR LIMIT=50] -->
+ <string name="wifi_dpp_share_hotspot">Share hotspot</string>
+ <!-- Hint for the user to share Wi-Fi hotspot network [CHAR LIMIT=NONE] -->
+ <string name="wifi_dpp_scan_qr_code_to_share_hotspot">Scan this QR code with another device to join hotspot \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
<!-- Label for the try again button [CHAR LIMIT=20]-->
<string name="retry">Retry</string>
<!-- Label for the check box to share a network with other users on the same device -->
@@ -2221,6 +2225,14 @@
<!-- Button label to connect to a Wi-Fi network -->
<string name="wifi_connect">Connect</string>
+ <!-- Turned on notification for Wi-Fi [CHAR LIMIT=40] -->
+ <string name="wifi_turned_on_message">Wi\u2011Fi turned on</string>
+ <!-- Connected to notification for Wi-Fi [CHAR LIMIT=NONE] -->
+ <string name="wifi_connected_to_message">@string/bluetooth_connected_summary</string>
+ <!-- Button label to connecting progress to a Wi-Fi network [CHAR LIMIT=20] -->
+ <string name="wifi_connecting">Connecting\u2026</string>
+ <!-- Button label to disconnect to a Wi-Fi network [CHAR LIMIT=NONE] -->
+ <string name="wifi_disconnect">@string/bluetooth_device_context_disconnect</string>
<!-- Failured notification for connect -->
<string name="wifi_failed_connect_message">Failed to connect to network</string>
<!-- Button label to delete a Wi-Fi network -->
@@ -2266,6 +2278,10 @@
<!-- Wifi saved access points. Used as a label under the shortcut icon that goes to Wifi saved access points. [CHAR LIMIT=20] -->
<string name="wifi_saved_access_points_label">Saved networks</string>
+ <!-- Tab title for showing subscribed WiFi access points. [CHAR LIMIT=20] -->
+ <string name="wifi_subscribed_access_points_tab">Subscriptions</string>
+ <!-- Tab title for showing saved WiFi access points. -->
+ <string name="wifi_saved_access_points_tab">@string/wifi_access_points</string>
<!-- Wifi Advanced settings. Used as a label under the shortcut icon that goes to Wifi advanced settings. [CHAR LIMIT=20] -->
<string name="wifi_advanced_settings_label">IP settings</string>
<!-- Error message for users that aren't allowed to see or modify WiFi advanced settings [CHAR LIMIT=NONE] -->
@@ -2374,8 +2390,6 @@
<string name="wifi_hotspot_configure_ap_text_summary">AndroidAP WPA2 PSK hotspot</string>
<!-- Default access point SSID used for tethering -->
<string name="wifi_tether_configure_ssid_default">AndroidHotspot</string>
- <!-- Summary text when hotspot is disabled because airplane mode is on [CHAR LIMIT=80]-->
- <string name="wifi_tether_disabled_by_airplane">Unavailable because airplane mode is turned on</string>
<!-- Do not translate. Used for diagnostic screens, precise translation is not necessary
Wi-Fi Testing on the diagnostic screen-->
@@ -2472,7 +2486,7 @@
<!-- Title of WFC preference item [CHAR LIMIT=30] -->
<string name="wifi_calling_mode_title">Calling preference</string>
<!-- Title of WFC preference selection dialog [CHAR LIMIT=30] -->
- <string name="wifi_calling_mode_dialog_title">Wi-Fi calling mode</string>
+ <string name="wifi_calling_mode_dialog_title">Calling preference</string>
<!-- Title of WFC roaming preference item [CHAR LIMIT=45] -->
<string name="wifi_calling_roaming_mode_title">Roaming preference</string>
<!-- Summary of WFC roaming preference item [CHAR LIMIT=NONE]-->
@@ -2480,9 +2494,9 @@
<!-- WFC mode dialog [CHAR LIMIT=45] -->
<string name="wifi_calling_roaming_mode_dialog_title">Roaming preference</string>
<string-array name="wifi_calling_mode_choices">
- <item>Wi-Fi preferred</item>
- <item>Mobile preferred</item>
- <item>Wi-Fi only</item>
+ <item>@*android:string/wfc_mode_wifi_preferred_summary</item>
+ <item>@*android:string/wfc_mode_cellular_preferred_summary</item>
+ <item>@*android:string/wfc_mode_wifi_only_summary</item>
</string-array>
<string-array name="wifi_calling_mode_choices_v2">
<item>Wi-Fi</item>
@@ -2495,8 +2509,8 @@
<item>"0"</item>
</string-array>
<string-array name="wifi_calling_mode_choices_without_wifi_only">
- <item>Wi-Fi preferred</item>
- <item>Mobile preferred</item>
+ <item>@*android:string/wfc_mode_wifi_preferred_summary</item>
+ <item>@*android:string/wfc_mode_cellular_preferred_summary</item>
</string-array>
<string-array name="wifi_calling_mode_choices_v2_without_wifi_only">
<item>Wi-Fi</item>
@@ -2506,6 +2520,14 @@
<item>"2"</item>
<item>"1"</item>
</string-array>
+
+ <!-- Summary of WFC preference item on the WFC preference selection dialog. [CHAR LIMIT=70]-->
+ <string name="wifi_calling_mode_wifi_preferred_summary">If Wi\u2011Fi is unavailable, use mobile network</string>
+ <!-- Summary of WFC preference item on the WFC preference selection dialog. [CHAR LIMIT=70]-->
+ <string name="wifi_calling_mode_cellular_preferred_summary">If mobile network is unavailable, use Wi\u2011Fi</string>
+ <!-- Summary of WFC preference item on the WFC preference selection dialog. [CHAR LIMIT=70]-->
+ <string name="wifi_calling_mode_wifi_only_summary">Call over Wi\u2011Fi. If Wi\u2011Fi is lost, call will end.</string>
+
<!-- Wi-Fi Calling settings. Text displayed when Wi-Fi Calling is off -->
<string name="wifi_calling_off_explanation">When Wi-Fi calling is on, your phone can route calls via Wi-Fi networks or your carrier\u2019s network, depending on your preference and which signal is stronger. Before turning on this feature, check with your carrier regarding fees and other details.<xliff:g id="additional_text" example="Learn More">%1$s</xliff:g></string>
<!-- Wi-Fi Calling settings. Additional text displayed when Wi-Fi Calling is off. Default empty. [CHAR LIMIT=NONE] -->
@@ -5218,8 +5240,8 @@
<string name="battery_tip_high_usage_title" product="tablet">Tablet used more than usual</string>
<!-- Title for the battery high usage tip [CHAR LIMIT=NONE] -->
<string name="battery_tip_high_usage_title" product="device">Device used more than usual</string>
- <!-- Summary for the battery high usage tip, which presents battery may run out soon [CHAR LIMIT=NONE] -->
- <string name="battery_tip_high_usage_summary">Battery may run out soon</string>
+ <!-- Summary for the battery high usage tip, which presents battery may run out earlier [CHAR LIMIT=NONE] -->
+ <string name="battery_tip_high_usage_summary">Battery may run out earlier than usual</string>
<!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
<string name="battery_tip_dialog_message" product="default">Your phone has been used more than usual. Your battery may run out sooner than expected.\n\nTop <xliff:g id="number">%1$d</xliff:g> apps you used since full charge:</string>
<!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
@@ -5583,6 +5605,12 @@
<!-- Battery saver: Title for battery saver schedule screen [CHAR_LIMIT=40] -->
<string name="battery_saver_schedule_settings_title">Set a schedule</string>
+ <!-- Battery Saver: Title for sticky battery saver preference [CHAR_LIMIT=60] -->
+ <string name="battery_saver_sticky_title">Keep battery saver on</string>
+
+ <!-- Battery Saver: Description for sticky battery saver preference [CHAR_LIMIT=NONE] -->
+ <string name="battery_saver_sticky_description">Battery saver will stay on even after device is fully charged</string>
+
<!-- Battery saver: Label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
<string name="battery_saver_seekbar_title"><xliff:g id="percent">%1$s</xliff:g></string>
@@ -5602,9 +5630,9 @@
<string name="battery_saver_turn_on_automatically_pct">at <xliff:g id="percent">%1$s</xliff:g> battery</string>
<!-- [CHAR_LIMIT=40] Battery percentage: Title -->
- <string name="battery_info">Battery Information</string>
+ <string name="battery_percentage">Battery percentage</string>
<!-- [CHAR_LIMIT=NONE] Battery percentage: Description for preference -->
- <string name="battery_info_description">Show percentage and time left before charge is needed</string>
+ <string name="battery_percentage_description">Show battery percentage in status bar</string>
<!-- Process Stats strings -->
<skip />
@@ -7147,6 +7175,9 @@
<string name="keywords_ring_vibration">haptics, vibrate, phone, call, sensitivity, ring</string>
<!-- List of synonyms for notification vibration setting (changes whether your phone vibrates when it shows a notification), used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_notification_vibration">haptics, vibrate, sensitivity</string>
+ <!-- Battery Saver: Search terms for sticky battery saver preference [CHAR_LIMIT=NONE] -->
+ <string name="keywords_battery_saver_sticky">battery saver, sticky, persist, power saver, battery</string>
+
<!-- NFC Wi-Fi pairing/setup strings-->
@@ -9795,8 +9826,11 @@
<!-- Title for settings suggestion for double twist for camera [CHAR LIMIT=60] -->
<string name="double_twist_for_camera_suggestion_title">Take selfies faster</string>
- <!-- Title text for swipe up to switch apps [CHAR LIMIT=60] -->
- <string name="swipe_up_to_switch_apps_title">Swipe up on Home button</string>
+ <!-- Title text for system navigation [CHAR LIMIT=60] [DO NOT TRANSLATE] -->
+ <string name="system_navigation_title" translatable="false">System navigation</string>
+
+ <!-- Title text for swipe up to switch apps [CHAR LIMIT=60] [DO NOT TRANSLATE] -->
+ <string name="swipe_up_to_switch_apps_title" translatable="false">2-button navigation</string>
<!-- Summary text for swipe up to switch apps [CHAR LIMIT=250] -->
<string name="swipe_up_to_switch_apps_summary">To switch apps, swipe up on the Home button. Swipe up again to see all apps. Works from any screen. You’ll no longer have an Overview button on the bottom right of your screen.</string>
<!-- Title for settings suggestion for swipe up to switch apps [CHAR LIMIT=60] -->
@@ -9804,6 +9838,16 @@
<!-- Summary for settings suggestion for swipe up to switch apps [CHAR LIMIT=60] -->
<string name="swipe_up_to_switch_apps_suggestion_summary">Turn on the new gesture to switch apps</string>
+ <!-- Title text for edge to edge navigation [CHAR LIMIT=60] [DO NOT TRANSLATE] -->
+ <string name="edge_to_edge_navigation_title" translatable="false">Fully gestural navigation</string>
+ <!-- Summary text for edge to edge navigation [CHAR LIMIT=None] [DO NOT TRANSLATE] -->
+ <string name="edge_to_edge_navigation_summary" translatable="false">To go Home, swipe up from the bottom of the screen. To go Back, swipe from either the left or right edge of the screen. To switch apps, start swiping up from the bottom of the screen and hold before releasing.</string>
+
+ <!-- Title text for 3-button navigation [CHAR LIMIT=60] [DO NOT TRANSLATE] -->
+ <string name="legacy_navigation_title" translatable="false">3-button navigation</string>
+ <!-- Summary text for 3-button navigation [CHAR LIMIT=250] [DO NOT TRANSLATE] -->
+ <string name="legacy_navigation_summary" translatable="false">Classic Android navigation mode where going Home, switching apps, and going Back are accessible via buttons.</string>
+
<!-- Preference and settings suggestion title text for ambient display double tap (phone) [CHAR LIMIT=60]-->
<string name="ambient_display_title" product="default">Double-tap to check phone</string>
<!-- Preference and settings suggestion title text for ambient display double tap (tablet) [CHAR LIMIT=60]-->
@@ -10640,6 +10684,9 @@
<!-- Title for the Volume dialog (settings panel) with all volume streams[CHAR LIMIT=50] -->
<string name="volume_connectivity_panel_title">Volume</string>
+ <!-- Subtitle explaining that mobile data cannot be used while airplane mode is on [CHAR LIMIT=50] -->
+ <string name="mobile_data_ap_mode_disabled">Unavailable during airplane mode</string>
+
<!-- UI debug setting: force desktop mode [CHAR LIMIT=50] -->
<string name="force_desktop_mode">Force desktop mode</string>
<!-- UI debug setting: force desktop mode summary [CHAR LIMIT=NONE] -->
@@ -10690,8 +10737,8 @@
<!-- Summary for the accessibility usage preference in the Privacy page. [CHAR LIMIT=NONE] -->
<plurals name="accessibility_usage_summary">
- <item quantity="one">1 service has full access to your device</item>
- <item quantity="other"><xliff:g id="service_count">%1$d</xliff:g> services have full access to your device</item>
+ <item quantity="one">1 app has full access to your device</item>
+ <item quantity="other"><xliff:g id="service_count">%1$d</xliff:g> apps have full access to your device</item>
</plurals>
<!-- Title for notification channel slice. [CHAR LIMIT=NONE] -->
@@ -10712,5 +10759,12 @@
<string name="media_output_panel_summary_of_playing_device">Currently playing on <xliff:g id="device_name" example="Bose headphone">%1$s</xliff:g></string>
<!-- Message for forget passpoint dialog [CHAR LIMIT=none] -->
- <string name="forget_passpoint_dialog_message">Your subscription with this provider may be cancelled. Recurring subscriptions will not be cancelled. For more information, check with your provider.</string>
+ <string name="forget_passpoint_dialog_message">You may lose access to any remaining time or data. Check with your provider before removing.</string>
+
+ <!-- Keywords for Content Capture feature [CHAR_LIMIT=32] -->
+ <string name="keywords_content_capture">content capture</string>
+ <!-- Title of the 'Content Capture' feature toggle in the Settings -> Privacy screen [CHAR LIMIT=none]-->
+ <string name="content_capture">Content Capture</string>
+ <!-- Description of the 'Content Capture' feature toggle in the Settings -> Privacy screen [CHAR LIMIT=NONE]-->
+ <string name="content_capture_summary">Allow Android to save information seen on your screen or heard in video or audio content. Android makes helpful suggestions based on your device activity.</string>
</resources>
diff --git a/res/xml/battery_saver_settings.xml b/res/xml/battery_saver_settings.xml
index 89f7eab..ae9d14d 100644
--- a/res/xml/battery_saver_settings.xml
+++ b/res/xml/battery_saver_settings.xml
@@ -26,6 +26,13 @@
android:title="@string/battery_saver_schedule_settings_title"
settings:controller="com.android.settings.fuelgauge.batterysaver.BatterySaverSchedulePreferenceController"/>
+ <SwitchPreference
+ android:key="battery_saver_sticky"
+ android:title="@string/battery_saver_sticky_title"
+ android:summary="@string/battery_saver_sticky_description"
+ settings:keywords="@string/keywords_battery_saver_sticky"
+ settings:controller="com.android.settings.fuelgauge.batterysaver.BatterySaverStickyPreferenceController"/>
+
<com.android.settings.widget.TwoStateButtonPreference
android:key="battery_saver"
android:title="@string/battery_saver"
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 0f4c1d3..91fe656 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -20,7 +20,7 @@
android:key="display_settings_screen"
android:title="@string/display_settings"
settings:keywords="@string/keywords_display"
- settings:initialExpandedChildrenCount="4">
+ settings:initialExpandedChildrenCount="5">
<com.android.settingslib.RestrictedPreference
android:key="brightness"
@@ -57,6 +57,15 @@
android:targetClass="@string/config_wallpaper_picker_class" />
</com.android.settingslib.RestrictedPreference>
+ <ListPreference
+ android:key="dark_ui_mode"
+ android:title="@string/dark_ui_mode"
+ android:dialogTitle="@string/dark_ui_mode_title"
+ android:entries="@array/dark_ui_mode_entries"
+ android:entryValues="@array/dark_ui_mode_values"
+ settings:keywords="@string/keywords_dark_ui_mode"
+ settings:controller="com.android.settings.display.DarkUIPreferenceController" />
+
<!-- Cross-listed item, if you change this, also change it in power_usage_summary.xml -->
<com.android.settings.display.TimeoutListPreference
android:key="screen_timeout"
@@ -136,15 +145,6 @@
android:summary="@string/tap_to_wake_summary" />
<ListPreference
- android:key="dark_ui_mode"
- android:title="@string/dark_ui_mode"
- android:dialogTitle="@string/dark_ui_mode_title"
- android:entries="@array/dark_ui_mode_entries"
- android:entryValues="@array/dark_ui_mode_values"
- settings:keywords="@string/keywords_dark_ui_mode"
- settings:controller="com.android.settings.display.DarkUIPreferenceController" />
-
- <ListPreference
android:key="theme"
android:title="@string/device_theme"
android:summary="@string/summary_placeholder" />
diff --git a/res/xml/firmware_version.xml b/res/xml/firmware_version.xml
index 2914ef1..75336ce 100644
--- a/res/xml/firmware_version.xml
+++ b/res/xml/firmware_version.xml
@@ -68,6 +68,7 @@
android:title="@string/build_number"
android:summary="@string/summary_placeholder"
settings:enableCopying="true"
+ settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.deviceinfo.firmwareversion.SimpleBuildNumberPreferenceController"/>
</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index b1250ec..f705630 100644
--- a/res/xml/gestures.xml
+++ b/res/xml/gestures.xml
@@ -52,10 +52,10 @@
settings:controller="com.android.settings.gestures.DoubleTwistPreferenceController" />
<Preference
- android:key="gesture_swipe_up_input_summary"
- android:title="@string/swipe_up_to_switch_apps_title"
- android:fragment="com.android.settings.gestures.SwipeUpGestureSettings"
- settings:controller="com.android.settings.gestures.SwipeUpPreferenceController" />
+ android:key="gesture_system_navigation_input_summary"
+ android:title="@string/system_navigation_title"
+ android:fragment="com.android.settings.gestures.SystemNavigationGestureSettings"
+ settings:controller="com.android.settings.gestures.SystemNavigationLegacyPreferenceController" />
<Preference
android:key="gesture_tap_screen_input_summary"
diff --git a/res/xml/language_and_input.xml b/res/xml/language_and_input.xml
index b04bdf8..e3690a9 100644
--- a/res/xml/language_and_input.xml
+++ b/res/xml/language_and_input.xml
@@ -94,7 +94,8 @@
<com.android.settings.widget.WorkOnlyCategory
android:key="language_and_input_for_work_category"
- android:title="@string/language_and_input_for_work_category_title">
+ android:title="@string/language_and_input_for_work_category_title"
+ settings:searchable="false">
<Preference
android:key="virtual_keyboards_for_work_pref"
diff --git a/res/xml/mobile_network_list.xml b/res/xml/mobile_network_list.xml
index 5bffa2f..b72540f 100644
--- a/res/xml/mobile_network_list.xml
+++ b/res/xml/mobile_network_list.xml
@@ -24,7 +24,10 @@
android:title="@string/mobile_network_list_add_more"
android:icon="@drawable/ic_menu_add"
android:order="100" >
- <intent android:action="android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION" />
+ <intent android:action="android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION">
+ <extra android:name="android.telephony.euicc.extra.FORCE_PROVISION"
+ android:value="true"/>
+ </intent>
</Preference>
</PreferenceScreen>
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index 83bf5c4..bc498d2 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -115,6 +115,7 @@
android:title="@string/status_imei"
settings:keywords="@string/keywords_imei_info"
android:summary="@string/summary_placeholder"
+ settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.deviceinfo.imei.ImeiInfoPreferenceController"/>
<!-- Android version -->
diff --git a/res/xml/network_and_internet_v2.xml b/res/xml/network_and_internet_v2.xml
index fd29c41..44c3121 100644
--- a/res/xml/network_and_internet_v2.xml
+++ b/res/xml/network_and_internet_v2.xml
@@ -22,6 +22,7 @@
<PreferenceCategory
android:key="multi_network_header"
+ android:title="@string/summary_placeholder"
settings:allowDividerBelow="true"
android:order="-40"
settings:controller="com.android.settings.network.MultiNetworkHeaderController"/>
@@ -79,7 +80,7 @@
settings:useAdminDisabledSummary="true" />
<com.android.settings.datausage.DataSaverPreference
- android:key="restrict_background"
+ android:key="restrict_background_parent_entry"
android:title="@string/data_saver_title"
android:icon="@drawable/ic_settings_data_usage"
android:order="10"
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index 9be0b7d..94ead86 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -50,8 +50,8 @@
<SwitchPreference
android:key="battery_percentage"
- android:title="@string/battery_info"
- android:summary="@string/battery_info_description"
+ android:title="@string/battery_percentage"
+ android:summary="@string/battery_percentage_description"
settings:controller="com.android.settings.display.BatteryPercentagePreferenceController" />
diff --git a/res/xml/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml
index 48034a84..d2d9e35 100644
--- a/res/xml/privacy_dashboard_settings.xml
+++ b/res/xml/privacy_dashboard_settings.xml
@@ -62,6 +62,13 @@
android:summary="@string/summary_placeholder"
settings:searchable="false"/>
+ <!-- Content Capture -->
+ <SwitchPreference
+ android:key="content_capture"
+ android:title="@string/content_capture"
+ android:summary="@string/content_capture_summary"
+ settings:controller="com.android.settings.privacy.EnableContentCapturePreferenceController"/>
+
<!-- Privacy Service -->
<PreferenceCategory
android:key="privacy_services"/>
diff --git a/res/xml/single_choice_list_item_2.xml b/res/xml/single_choice_list_item_2.xml
new file mode 100644
index 0000000..ca80f44
--- /dev/null
+++ b/res/xml/single_choice_list_item_2.xml
@@ -0,0 +1,58 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/select_dialog_padding_start"
+ android:paddingEnd="?android:attr/dialogPreferredPadding"
+ android:orientation="horizontal"
+ android:descendantFocusability="blocksDescendants">
+
+ <RadioButton
+ android:id="@+id/radio"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:clickable="false" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:layout_marginStart="@dimen/select_dialog_item_margin_start"
+ android:layout_gravity="center_vertical">
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorAlertDialogListItem"
+ android:ellipsize="marquee" />
+
+ <TextView
+ android:id="@+id/summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/select_dialog_summary_padding_bottom"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary"
+ android:maxLines="10" />
+
+ </LinearLayout>
+</LinearLayout>
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 81a0453..57bee1f 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -41,7 +41,7 @@
settings:controller="com.android.settings.notification.MediaVolumePreferenceController"/>
<!-- Media output switcher -->
- <ListPreference
+ <Preference
android:key="media_output"
android:title="@string/media_output_title"
android:dialogTitle="@string/media_output_title"
diff --git a/res/xml/swipe_up_gesture_settings.xml b/res/xml/swipe_up_gesture_settings.xml
deleted file mode 100644
index cc1db16..0000000
--- a/res/xml/swipe_up_gesture_settings.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:key="gesture_swipe_up_screen"
- android:title="@string/swipe_up_to_switch_apps_title">
-
- <com.android.settings.widget.VideoPreference
- android:key="gesture_swipe_up_video"
- app:animation="@raw/gesture_swipe_up"
- app:preview="@drawable/gesture_swipe_up" />
-
- <SwitchPreference
- android:key="gesture_swipe_up"
- android:title="@string/swipe_up_to_switch_apps_title"
- android:summary="@string/swipe_up_to_switch_apps_summary"
- app:keywords="@string/keywords_gesture"
- app:controller="com.android.settings.gestures.SwipeUpPreferenceController"
- app:allowDividerAbove="true" />
-
-</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/system_navigation_gesture_settings.xml b/res/xml/system_navigation_gesture_settings.xml
new file mode 100644
index 0000000..97aacb8
--- /dev/null
+++ b/res/xml/system_navigation_gesture_settings.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:key="gesture_system_navigation_screen"
+ android:title="@string/system_navigation_title">
+
+ <com.android.settings.widget.VideoPreference
+ android:key="gesture_swipe_up_video"
+ app:animation="@raw/gesture_swipe_up"
+ app:preview="@drawable/gesture_swipe_up" />
+
+ <com.android.settings.widget.RadioButtonPreference
+ android:key="gesture_edge_to_edge"
+ android:title="@string/edge_to_edge_navigation_title"
+ android:summary="@string/edge_to_edge_navigation_summary"
+ app:keywords="@string/keywords_gesture"
+ app:controller="com.android.settings.gestures.SystemNavigationEdgeToEdgePreferenceController"
+ app:allowDividerAbove="true" />
+
+ <com.android.settings.widget.RadioButtonPreference
+ android:key="gesture_swipe_up"
+ android:title="@string/swipe_up_to_switch_apps_title"
+ android:summary="@string/swipe_up_to_switch_apps_summary"
+ app:keywords="@string/keywords_gesture"
+ app:controller="com.android.settings.gestures.SystemNavigationSwipeUpPreferenceController" />
+
+ <com.android.settings.widget.RadioButtonPreference
+ android:key="gesture_legacy"
+ android:title="@string/legacy_navigation_title"
+ android:summary="@string/legacy_navigation_summary"
+ app:keywords="@string/keywords_gesture"
+ app:controller="com.android.settings.gestures.SystemNavigationLegacyPreferenceController" />
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml
index 64b620a..367f426 100644
--- a/res/xml/top_level_settings.xml
+++ b/res/xml/top_level_settings.xml
@@ -18,8 +18,7 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
- android:key="top_level_settings"
- android:title="@string/settings_label_launcher">
+ android:key="top_level_settings">
<Preference
android:key="top_level_network"
diff --git a/res/xml/wifi_calling_settings.xml b/res/xml/wifi_calling_settings.xml
index 0adb1e8..0276bdb 100644
--- a/res/xml/wifi_calling_settings.xml
+++ b/res/xml/wifi_calling_settings.xml
@@ -15,24 +15,27 @@
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="wifi_calling_settings"
android:title="@string/wifi_calling_settings_title">
- <ListPreference
+ <com.android.settings.wifi.calling.ListWithEntrySummaryPreference
android:key="wifi_calling_mode"
android:title="@string/wifi_calling_mode_title"
android:summary="@string/wifi_calling_mode_title"
android:entries="@array/wifi_calling_mode_choices"
android:entryValues="@array/wifi_calling_mode_values"
- android:dialogTitle="@string/wifi_calling_mode_dialog_title" />
+ android:dialogTitle="@string/wifi_calling_mode_dialog_title"
+ settings:entrySummaries="@array/wifi_calling_mode_summaries" />
- <ListPreference
+ <com.android.settings.wifi.calling.ListWithEntrySummaryPreference
android:key="wifi_calling_roaming_mode"
android:title="@string/wifi_calling_roaming_mode_title"
android:summary="@string/wifi_calling_roaming_mode_summary"
android:entries="@array/wifi_calling_mode_choices_v2"
android:entryValues="@array/wifi_calling_mode_values"
- android:dialogTitle="@string/wifi_calling_roaming_mode_dialog_title" />
+ android:dialogTitle="@string/wifi_calling_roaming_mode_dialog_title"
+ settings:entrySummaries="@array/wifi_calling_mode_summaries" />
<Preference
android:key="emergency_address_key"
diff --git a/res/xml/wifi_display_saved_access_points.xml b/res/xml/wifi_display_saved_access_points.xml
index 98b4dec..b3a8d55 100644
--- a/res/xml/wifi_display_saved_access_points.xml
+++ b/res/xml/wifi_display_saved_access_points.xml
@@ -21,8 +21,13 @@
android:title="@string/wifi_saved_access_points_label">
<PreferenceCategory
+ android:key="subscribed_access_points_category"
+ android:title="@string/wifi_subscribed_access_points_tab"
+ settings:controller="com.android.settings.wifi.savedaccesspoints.SubscribedAccessPointsPreferenceController"/>
+
+ <PreferenceCategory
android:key="saved_access_points_category"
- android:layout="@layout/preference_category_no_label"
+ android:title="@string/wifi_saved_access_points_tab"
settings:controller="com.android.settings.wifi.savedaccesspoints.SavedAccessPointsPreferenceController"/>
</PreferenceScreen>
diff --git a/res/xml/wifi_network_details_fragment.xml b/res/xml/wifi_network_details_fragment.xml
index 7c542d8..8979efc 100644
--- a/res/xml/wifi_network_details_fragment.xml
+++ b/res/xml/wifi_network_details_fragment.xml
@@ -26,6 +26,11 @@
android:order="-10000"
settings:allowDividerBelow="true"/>
+ <com.android.settings.datausage.DataUsageSummaryPreference
+ android:key="status_header"
+ android:selectable="false"
+ settings:isPreferenceVisible="false"/>
+
<!-- Buttons -->
<com.android.settingslib.widget.ActionButtonsPreference
android:key="buttons"
diff --git a/res/xml/wifi_tether_settings.xml b/res/xml/wifi_tether_settings.xml
index 6c5e3c4..81e60a2 100644
--- a/res/xml/wifi_tether_settings.xml
+++ b/res/xml/wifi_tether_settings.xml
@@ -23,7 +23,7 @@
settings:searchable="false"
settings:initialExpandedChildrenCount="3">
- <com.android.settings.widget.ValidatedEditTextPreference
+ <com.android.settings.wifi.tether.WifiTetherSsidPreference
android:key="wifi_tether_network_name"
android:title="@string/wifi_hotspot_name_title"
android:summary="@string/summary_placeholder"/>
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 541ca3a..001e65b 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -50,6 +50,8 @@
import com.android.internal.util.ArrayUtils;
import com.android.settings.Settings.WifiSettingsActivity;
import com.android.settings.applications.manageapplications.ManageApplications;
+import com.android.settings.backup.BackupSettingsHelper;
+import com.android.settings.backup.UserBackupSettingsActivity;
import com.android.settings.core.OnActivityResultListener;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.core.SubSettingLauncher;
@@ -630,6 +632,12 @@
showDev, isAdmin)
|| somethingChanged;
+ // Enable/disable backup settings depending on whether backup is activated for the user.
+ boolean isBackupActive = new BackupSettingsHelper(this).isBackupServiceActive();
+ somethingChanged = setTileEnabled(changedList, new ComponentName(packageName,
+ UserBackupSettingsActivity.class.getName()), isBackupActive, isAdmin)
+ || somethingChanged;
+
somethingChanged = setTileEnabled(changedList, new ComponentName(packageName,
Settings.WifiDisplaySettingsActivity.class.getName()),
WifiDisplaySettings.isAvailable(this), isAdmin)
diff --git a/src/com/android/settings/accessibility/BalanceSeekBar.java b/src/com/android/settings/accessibility/BalanceSeekBar.java
index e18a593..b108e18 100644
--- a/src/com/android/settings/accessibility/BalanceSeekBar.java
+++ b/src/com/android/settings/accessibility/BalanceSeekBar.java
@@ -28,6 +28,8 @@
import android.util.AttributeSet;
import android.widget.SeekBar;
+import androidx.annotation.VisibleForTesting;
+
import com.android.settings.R;
/**
@@ -37,14 +39,13 @@
* Updates Settings.System for balance on progress changed.
*/
public class BalanceSeekBar extends SeekBar {
- private static final String TAG = "BalanceSeekBar";
private final Context mContext;
private final Object mListenerLock = new Object();
private OnSeekBarChangeListener mOnSeekBarChangeListener;
private final OnSeekBarChangeListener mProxySeekBarListener = new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
- synchronized(mListenerLock) {
+ synchronized (mListenerLock) {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
}
@@ -53,7 +54,7 @@
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
- synchronized(mListenerLock) {
+ synchronized (mListenerLock) {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
}
@@ -79,7 +80,7 @@
// after adjusting the seekbar, notify downstream listener.
// note that progress may have been adjusted in the code above to mCenter.
- synchronized(mListenerLock) {
+ synchronized (mListenerLock) {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
}
@@ -88,7 +89,8 @@
};
// Percentage of max to be used as a snap to threshold
- private static final float SNAP_TO_PERCENTAGE = 0.03f;
+ @VisibleForTesting
+ static final float SNAP_TO_PERCENTAGE = 0.03f;
private final Paint mCenterMarkerPaint;
private final Rect mCenterMarkerRect;
// changed in setMax()
@@ -122,7 +124,7 @@
@Override
public void setOnSeekBarChangeListener(OnSeekBarChangeListener listener) {
- synchronized(mListenerLock) {
+ synchronized (mListenerLock) {
mOnSeekBarChangeListener = listener;
}
}
@@ -148,5 +150,10 @@
canvas.restore();
super.onDraw(canvas);
}
+
+ @VisibleForTesting
+ OnSeekBarChangeListener getProxySeekBarListener() {
+ return mProxySeekBarListener;
+ }
}
diff --git a/src/com/android/settings/accessibility/BalanceSeekBarPreference.java b/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
index a40282c..b03c8ab 100644
--- a/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
+++ b/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
@@ -34,7 +34,9 @@
/** A slider preference that directly controls audio balance **/
public class BalanceSeekBarPreference extends SeekBarPreference {
- private static final String TAG = "BalanceSeekBarPreference";
+ private static final int BALANCE_CENTER_VALUE = 100;
+ private static final int BALANCE_MAX_VALUE = 200;
+
private final Context mContext;
private BalanceSeekBar mSeekBar;
private ImageView mIconView;
@@ -62,9 +64,9 @@
final float balance = Settings.System.getFloatForUser(
mContext.getContentResolver(), Settings.System.MASTER_BALANCE,
0.f /* default */, UserHandle.USER_CURRENT);
- // Rescale balance to range 0-200 centered at 100.
- mSeekBar.setMax(200);
- mSeekBar.setProgress((int)(balance * 100.f) + 100);
+ // Rescale balance to range 0-BALANCE_MAX_VALUE centered at BALANCE_MAX_VALUE / 2.
+ mSeekBar.setMax(BALANCE_MAX_VALUE);
+ mSeekBar.setProgress((int) (balance * 100.f) + BALANCE_CENTER_VALUE);
mSeekBar.setEnabled(isEnabled());
}
}
diff --git a/src/com/android/settings/accounts/AvatarViewMixin.java b/src/com/android/settings/accounts/AvatarViewMixin.java
index 3ce8c0a..9e762c7 100644
--- a/src/com/android/settings/accounts/AvatarViewMixin.java
+++ b/src/com/android/settings/accounts/AvatarViewMixin.java
@@ -17,6 +17,7 @@
package com.android.settings.accounts;
import android.accounts.Account;
+import android.app.ActivityManager;
import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.Context;
@@ -64,11 +65,13 @@
private final Context mContext;
private final ImageView mAvatarView;
private final MutableLiveData<Bitmap> mAvatarImage;
+ private final ActivityManager mActivityManager;
private String mAccountName;
public AvatarViewMixin(SettingsHomepageActivity activity, ImageView avatarView) {
mContext = activity.getApplicationContext();
+ mActivityManager = mContext.getSystemService(ActivityManager.class);
mAvatarView = avatarView;
mAvatarView.setOnClickListener(v -> {
Intent intent;
@@ -114,7 +117,11 @@
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
if (!mContext.getResources().getBoolean(R.bool.config_show_avatar_in_homepage)) {
- Log.d(TAG, "Feature disabled. Skipping");
+ Log.d(TAG, "Feature disabled by config. Skipping");
+ return;
+ }
+ if (mActivityManager.isLowRamDevice()) {
+ Log.d(TAG, "Feature disabled on low ram device. Skipping");
return;
}
if (hasAccount()) {
diff --git a/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java b/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java
index ca8dda3..0663e2a 100644
--- a/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java
+++ b/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java
@@ -14,12 +14,12 @@
package com.android.settings.applications.appinfo;
+import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.os.UserManager;
-import android.permission.PermissionControllerManager;
import android.text.TextUtils;
import androidx.preference.Preference;
@@ -58,14 +58,14 @@
mRoleManager = context.getSystemService(RoleManager.class);
- final PermissionControllerManager permissionControllerManager =
- mContext.getSystemService(PermissionControllerManager.class);
+ final RoleControllerManager roleControllerManager =
+ mContext.getSystemService(RoleControllerManager.class);
final Executor executor = mContext.getMainExecutor();
- permissionControllerManager.isRoleVisible(mRoleName, executor, visible -> {
+ roleControllerManager.isRoleVisible(mRoleName, executor, visible -> {
mRoleVisible = visible;
refreshAvailability();
});
- permissionControllerManager.isApplicationQualifiedForRole(mRoleName, mPackageName, executor,
+ roleControllerManager.isApplicationQualifiedForRole(mRoleName, mPackageName, executor,
qualified -> {
mAppQualified = qualified;
refreshAvailability();
diff --git a/src/com/android/settings/applications/defaultapps/DefaultEmergencyPicker.java b/src/com/android/settings/applications/defaultapps/DefaultEmergencyPicker.java
index f088967..32cc9a8 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultEmergencyPicker.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultEmergencyPicker.java
@@ -17,9 +17,7 @@
package com.android.settings.applications.defaultapps;
import android.app.role.RoleManager;
-import android.app.role.RoleManagerCallback;
import android.app.settings.SettingsEnums;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -27,7 +25,6 @@
import android.content.pm.ResolveInfo;
import android.os.AsyncTask;
import android.os.Process;
-import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -100,18 +97,13 @@
final String previousValue = getDefaultKey();
if (!TextUtils.isEmpty(key) && !TextUtils.equals(key, previousValue)) {
- getContext().getSystemService(RoleManager.class)
- .addRoleHolderAsUser(
- RoleManager.ROLE_EMERGENCY, key, 0, Process.myUserHandle(),
- AsyncTask.THREAD_POOL_EXECUTOR, new RoleManagerCallback() {
- @Override
- public void onSuccess() {}
-
- @Override
- public void onFailure() {
- Log.e(TAG, "Failed to set emergency default app.");
- }
- });
+ getContext().getSystemService(RoleManager.class).addRoleHolderAsUser(
+ RoleManager.ROLE_EMERGENCY, key, 0, Process.myUserHandle(),
+ AsyncTask.THREAD_POOL_EXECUTOR, successful -> {
+ if (!successful) {
+ Log.e(TAG, "Failed to set emergency default app.");
+ }
+ });
return true;
}
return false;
diff --git a/src/com/android/settings/backup/BackupSettingsHelper.java b/src/com/android/settings/backup/BackupSettingsHelper.java
index fa77154..b836e55 100644
--- a/src/com/android/settings/backup/BackupSettingsHelper.java
+++ b/src/com/android/settings/backup/BackupSettingsHelper.java
@@ -209,7 +209,7 @@
}
/** Checks if backup service is enabled for this user. */
- private boolean isBackupServiceActive() {
+ public boolean isBackupServiceActive() {
boolean backupOkay;
try {
backupOkay = mBackupManager.isBackupServiceActive(UserHandle.myUserId());
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index b650c6c..1b41240 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -16,8 +16,6 @@
package com.android.settings.biometrics;
-import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
-
import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -25,8 +23,11 @@
import com.android.settings.biometrics.face.FaceEnrollIntroduction;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction;
+import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollIntroduction;
import com.android.settings.core.InstrumentedActivity;
+import com.google.android.setupcompat.util.WizardManagerHelper;
+
/**
* Trampoline activity launched by the {@code android.settings.BIOMETRIC_ENROLL} action which
* shows the user an appropriate enrollment flow depending on the device's biometric hardware.
@@ -40,20 +41,38 @@
super.onCreate(savedInstanceState);
final PackageManager pm = getApplicationContext().getPackageManager();
- final Intent intent = new Intent();
+ Intent intent = null;
// This logic may have to be modified on devices with multiple biometrics.
if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
- intent.setClassName(SETTINGS_PACKAGE_NAME,
- FingerprintEnrollIntroduction.class.getName());
+ intent = getFingerprintEnrollIntent();
} else if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
- intent.setClassName(SETTINGS_PACKAGE_NAME, FaceEnrollIntroduction.class.getName());
+ intent = getFaceEnrollIntent();
}
- startActivity(intent);
+ if (intent != null) {
+ intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ startActivity(intent);
+ }
finish();
}
+ private Intent getFingerprintEnrollIntent() {
+ if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
+ Intent intent = new Intent(this, SetupFingerprintEnrollIntroduction.class);
+ WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
+ return intent;
+ } else {
+ return new Intent(this, FingerprintEnrollIntroduction.class);
+ }
+ }
+
+ private Intent getFaceEnrollIntent() {
+ Intent intent = new Intent(this, FaceEnrollIntroduction.class);
+ WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
+ return intent;
+ }
+
@Override
public int getMetricsCategory() {
return SettingsEnums.BIOMETRIC_ENROLL_ACTIVITY;
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index e8cf809..097ffe2 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -21,14 +21,19 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.storage.StorageManager;
import android.view.View;
import android.widget.TextView;
+import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.password.ChooseLockGeneric;
+import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.password.SetupChooseLockGeneric;
import com.google.android.setupcompat.template.FooterButton;
+import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.span.LinkSpan;
/**
@@ -199,28 +204,39 @@
}
protected Intent getChooseLockIntent() {
- return new Intent(this, ChooseLockGeneric.class);
+ if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
+ // Default to PIN lock in setup wizard
+ Intent intent = new Intent(this, SetupChooseLockGeneric.class);
+ if (StorageManager.isFileEncryptedNativeOrEmulated()) {
+ intent.putExtra(
+ LockPatternUtils.PASSWORD_TYPE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
+ intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
+ }
+ WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
+ return intent;
+ } else {
+ return new Intent(this, ChooseLockGeneric.class);
+ }
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- final boolean isResultFinished = resultCode == RESULT_FINISHED;
- final int result = isResultFinished ? RESULT_OK : RESULT_SKIP;
if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
- if (isResultFinished || resultCode == RESULT_SKIP) {
- setResult(result, data);
+ if (resultCode == RESULT_FINISHED || resultCode == RESULT_SKIP) {
+ setResult(resultCode, data);
finish();
return;
}
} else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
- if (isResultFinished) {
+ if (resultCode == RESULT_FINISHED) {
updatePasswordQuality();
mToken = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
return;
} else {
- setResult(result, data);
+ setResult(resultCode, data);
finish();
}
} else if (requestCode == CONFIRM_REQUEST) {
@@ -228,7 +244,7 @@
mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
} else {
- setResult(result, data);
+ setResult(resultCode, data);
finish();
}
} else if (requestCode == LEARN_MORE_REQUEST) {
@@ -241,6 +257,11 @@
finish();
}
+ protected void onSkipButtonClick(View view) {
+ setResult(RESULT_SKIP);
+ finish();
+ }
+
@Override
protected void initViews() {
super.initViews();
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index e45817d..5f2b675 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -36,6 +36,7 @@
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
+import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.span.LinkSpan;
public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
@@ -59,14 +60,25 @@
mSwitchDiversity = findViewById(R.id.toggle_diversity);
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
- mFooterBarMixin.setSecondaryButton(
- new FooterButton.Builder(this)
- .setText(R.string.security_settings_face_enroll_introduction_cancel)
- .setListener(this::onCancelButtonClick)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(R.style.SudGlifButton_Secondary)
- .build()
- );
+ if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
+ mFooterBarMixin.setSecondaryButton(
+ new FooterButton.Builder(this)
+ .setText(R.string.skip_label)
+ .setListener(this::onSkipButtonClick)
+ .setButtonType(FooterButton.ButtonType.SKIP)
+ .setTheme(R.style.SudGlifButton_Secondary)
+ .build()
+ );
+ } else {
+ mFooterBarMixin.setSecondaryButton(
+ new FooterButton.Builder(this)
+ .setText(R.string.security_settings_face_enroll_introduction_cancel)
+ .setListener(this::onCancelButtonClick)
+ .setButtonType(FooterButton.ButtonType.CANCEL)
+ .setTheme(R.style.SudGlifButton_Secondary)
+ .build()
+ );
+ }
mFooterBarMixin.setPrimaryButton(
new FooterButton.Builder(this)
@@ -166,6 +178,7 @@
intent.setClass(this, FaceEnrollEnrolling.class);
}
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, mSwitchDiversity.isChecked());
+ WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
return intent;
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index 490580d..ea5a303 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -156,6 +156,9 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ if (!isAvailable(context)) {
+ return null;
+ }
final List<AbstractPreferenceController> controllers =
buildPreferenceControllers(context, getSettingsLifecycle());
// There's no great way of doing this right now :/
@@ -197,7 +200,11 @@
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
- return buildPreferenceControllers(context, null /* lifecycle */);
+ if (isAvailable(context)) {
+ return buildPreferenceControllers(context, null /* lifecycle */);
+ } else {
+ return null;
+ }
}
@Override
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index f2ffe22..fbb2ae3 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -23,8 +23,10 @@
public static final String AUDIO_SWITCHER_SETTINGS = "settings_audio_switcher";
public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
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 SLICE_INJECTION = "settings_slice_injection";
public static final String MAINLINE_MODULE = "settings_mainline_module";
+ public static final String WIFI_DETAILS_SAVED_SCREEN = "settings_wifi_details_saved_screen";
+ public static final String WIFI_DETAILS_DATAUSAGE_HEADER =
+ "settings_wifi_details_datausage_header";
}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 7abd98d..147d0be 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -82,7 +82,7 @@
import com.android.settings.gestures.DoubleTwistGestureSettings;
import com.android.settings.gestures.PickupGestureSettings;
import com.android.settings.gestures.SwipeToNotificationSettings;
-import com.android.settings.gestures.SwipeUpGestureSettings;
+import com.android.settings.gestures.SystemNavigationGestureSettings;
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
@@ -201,7 +201,7 @@
DoubleTapScreenSettings.class.getName(),
PickupGestureSettings.class.getName(),
DoubleTwistGestureSettings.class.getName(),
- SwipeUpGestureSettings.class.getName(),
+ SystemNavigationGestureSettings.class.getName(),
CryptKeeperSettings.class.getName(),
DataUsageSummary.class.getName(),
DreamSettings.class.getName(),
diff --git a/src/com/android/settings/datausage/DataUsageSummaryPreference.java b/src/com/android/settings/datausage/DataUsageSummaryPreference.java
index 481538d..93df2f1 100644
--- a/src/com/android/settings/datausage/DataUsageSummaryPreference.java
+++ b/src/com/android/settings/datausage/DataUsageSummaryPreference.java
@@ -69,6 +69,8 @@
private boolean mDefaultTextColorSet;
private int mDefaultTextColor;
private int mNumPlans;
+ /** The specified un-initialized value for cycle time */
+ private final long CYCLE_TIME_UNINITIAL_VALUE = 0;
/** The ending time of the billing cycle in milliseconds since epoch. */
private long mCycleEndTimeMs;
/** The time of the last update in standard milliseconds since the epoch */
@@ -94,6 +96,7 @@
/** WiFi only mode */
private boolean mWifiMode;
private String mUsagePeriod;
+ private boolean mSingleWifi; // Shows only one specified WiFi network usage
public DataUsageSummaryPreference(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -142,9 +145,10 @@
notifyChanged();
}
- void setWifiMode(boolean isWifiMode, String usagePeriod) {
+ void setWifiMode(boolean isWifiMode, String usagePeriod, boolean isSingleWifi) {
mWifiMode = isWifiMode;
mUsagePeriod = usagePeriod;
+ mSingleWifi = isSingleWifi;
notifyChanged();
}
@@ -171,7 +175,16 @@
Button launchButton = (Button) holder.findViewById(R.id.launch_mdp_app_button);
TextView limitInfo = (TextView) holder.findViewById(R.id.data_limits);
- if (mWifiMode) {
+ if (mWifiMode && mSingleWifi) {
+ updateCycleTimeText(holder);
+
+ usageTitle.setVisibility(View.GONE);
+ launchButton.setVisibility(View.GONE);
+ carrierInfo.setVisibility(View.GONE);
+
+ limitInfo.setVisibility(TextUtils.isEmpty(mLimitInfoText) ? View.GONE : View.VISIBLE);
+ limitInfo.setText(mLimitInfoText);
+ } else if (mWifiMode) {
usageTitle.setText(R.string.data_usage_wifi_title);
usageTitle.setVisibility(View.VISIBLE);
TextView cycleTime = (TextView) holder.findViewById(R.id.cycle_left_time);
@@ -265,6 +278,13 @@
private void updateCycleTimeText(PreferenceViewHolder holder) {
TextView cycleTime = (TextView) holder.findViewById(R.id.cycle_left_time);
+ // Takes zero as a special case which value is never set.
+ if (mCycleEndTimeMs == CYCLE_TIME_UNINITIAL_VALUE) {
+ cycleTime.setVisibility(View.GONE);
+ return;
+ }
+
+ cycleTime.setVisibility(View.VISIBLE);
long millisLeft = mCycleEndTimeMs - System.currentTimeMillis();
if (millisLeft <= 0) {
cycleTime.setText(getContext().getString(R.string.billing_cycle_none_left));
diff --git a/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java b/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java
index 353c5ee..a06bb77 100644
--- a/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java
+++ b/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java
@@ -65,10 +65,10 @@
private final EntityHeaderController mEntityHeaderController;
private final Lifecycle mLifecycle;
private final PreferenceFragmentCompat mFragment;
- private final DataUsageController mDataUsageController;
- private final DataUsageInfoController mDataInfoController;
+ protected final DataUsageController mDataUsageController;
+ protected final DataUsageInfoController mDataInfoController;
private final NetworkTemplate mDefaultTemplate;
- private final NetworkPolicyEditor mPolicyEditor;
+ protected final NetworkPolicyEditor mPolicyEditor;
private final int mDataUsageTemplate;
private final boolean mHasMobileData;
private final SubscriptionManager mSubscriptionManager;
@@ -200,11 +200,13 @@
if (DataUsageUtils.hasSim(mActivity)) {
info = mDataUsageController.getDataUsageInfo(mDefaultTemplate);
mDataInfoController.updateDataLimit(info, mPolicyEditor.getPolicy(mDefaultTemplate));
- summaryPreference.setWifiMode(/* isWifiMode */ false, /* usagePeriod */ null);
+ summaryPreference.setWifiMode(/* isWifiMode */ false,
+ /* usagePeriod */ null, /* isSingleWifi */ false);
} else {
info = mDataUsageController.getDataUsageInfo(
NetworkTemplate.buildTemplateWifiWildcard());
- summaryPreference.setWifiMode(/* isWifiMode */ true, /* usagePeriod */ info.period);
+ summaryPreference.setWifiMode(/* isWifiMode */ true, /* usagePeriod */
+ info.period, /* isSingleWifi */ false);
summaryPreference.setLimitInfo(null);
summaryPreference.setUsageNumbers(info.usageLevel,
/* dataPlanSize */ -1L,
diff --git a/src/com/android/settings/datausage/WifiDataUsageSummaryPreferenceController.java b/src/com/android/settings/datausage/WifiDataUsageSummaryPreferenceController.java
new file mode 100644
index 0000000..8b6d10a
--- /dev/null
+++ b/src/com/android/settings/datausage/WifiDataUsageSummaryPreferenceController.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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.datausage;
+
+import android.app.Activity;
+import android.net.NetworkTemplate;
+import android.telephony.SubscriptionManager;
+import android.text.format.Formatter;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.net.DataUsageController;
+
+/**
+ * The controller displays a data usage chart for the specified Wi-Fi network.
+ */
+public class WifiDataUsageSummaryPreferenceController extends DataUsageSummaryPreferenceController {
+ final String mNetworkId;
+
+ public WifiDataUsageSummaryPreferenceController(Activity activity,
+ Lifecycle lifecycle, PreferenceFragmentCompat fragment, CharSequence networkId) {
+ super(activity, lifecycle, fragment, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+ if (networkId == null) {
+ mNetworkId = null;
+ } else {
+ mNetworkId = String.valueOf(networkId);
+ }
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ if (preference == null) {
+ return;
+ }
+
+ final DataUsageSummaryPreference mPreference = (DataUsageSummaryPreference) preference;
+ // TODO(b/126299427): Currently gets data usage of whole Wi-Fi networks, but should get
+ // specified one.
+ final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(mNetworkId);
+ final DataUsageController.DataUsageInfo info = mDataUsageController.getDataUsageInfo(
+ template);
+ mDataInfoController.updateDataLimit(info, mPolicyEditor.getPolicy(template));
+
+ mPreference.setWifiMode(/* isWifiMode */ true, /* usagePeriod */
+ info.period, /* isSingleWifi */ true);
+ mPreference.setChartEnabled(true);
+ // Treats Wi-Fi network as unlimited network, which has same usage level and limited level.
+ mPreference.setUsageNumbers(info.usageLevel, info.usageLevel, /* hasMobileData */ false);
+
+ // TODO(b/126142293): Passpoint Wi-Fi should have limit of data usage and time remaining
+ mPreference.setProgress(100);
+ mPreference.setLabels(Formatter.formatFileSize(mContext, /* sizeBytes */ 0),
+ DataUsageUtils.formatDataUsage(mContext, info.usageLevel));
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
index f13af94..855a988 100644
--- a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
@@ -16,12 +16,8 @@
package com.android.settings.deviceinfo;
-import static android.content.Context.CLIPBOARD_SERVICE;
-
import android.app.Activity;
import android.app.settings.SettingsEnums;
-import android.content.ClipData;
-import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -79,11 +75,7 @@
@Override
public CharSequence getSummary() {
- try {
- return BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY);
- } catch (Exception e) {
- return mContext.getText(R.string.device_info_default);
- }
+ return BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY);
}
@Override
@@ -99,29 +91,7 @@
@Override
public int getAvailabilityStatus() {
- return AVAILABLE;
- }
-
- @Override
- public boolean isSliceable() {
- return true;
- }
-
- @Override
- public boolean isCopyableSlice() {
- return true;
- }
-
- @Override
- public void copy() {
- final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
- CLIPBOARD_SERVICE);
- final ClipData clip = ClipData.newPlainText("text", getSummary());
- clipboard.setPrimaryClip(clip);
-
- final String toast = mContext.getString(R.string.copyable_slice_toast,
- mContext.getText(R.string.build_number));
- Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
+ return AVAILABLE_UNSEARCHABLE;
}
@Override
diff --git a/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java
index c7d4459..36f1a43 100644
--- a/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java
@@ -16,10 +16,16 @@
package com.android.settings.deviceinfo.firmwareversion;
+import static android.content.Context.CLIPBOARD_SERVICE;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
import android.content.Context;
import android.os.Build;
import android.text.BidiFormatter;
+import android.widget.Toast;
+import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
public class SimpleBuildNumberPreferenceController extends BasePreferenceController {
@@ -38,4 +44,26 @@
public CharSequence getSummary() {
return BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY);
}
+
+ @Override
+ public boolean isSliceable() {
+ return true;
+ }
+
+ @Override
+ public boolean isCopyableSlice() {
+ return true;
+ }
+
+ @Override
+ public void copy() {
+ final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
+ CLIPBOARD_SERVICE);
+ final ClipData clip = ClipData.newPlainText("text", getSummary());
+ clipboard.setPrimaryClip(clip);
+
+ final String toast = mContext.getString(R.string.copyable_slice_toast,
+ mContext.getText(R.string.build_number));
+ Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
+ }
}
diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java
index 1f11f5a..c851a71 100644
--- a/src/com/android/settings/fuelgauge/BatteryInfo.java
+++ b/src/com/android/settings/fuelgauge/BatteryInfo.java
@@ -47,6 +47,7 @@
public long averageTimeToDischarge = Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN;
public String batteryPercentString;
public String statusLabel;
+ public String suggestionLabel;
private boolean mCharging;
private BatteryStats mStats;
private static final String LOG_TAG = "BatteryInfo";
@@ -247,6 +248,7 @@
final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
info.discharging = false;
+ info.suggestionLabel = null;
if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
info.remainingTimeUs = chargeTime;
CharSequence timeString = StringUtil.formatElapsedTime(context,
@@ -282,8 +284,11 @@
info.batteryPercentString,
estimate.isBasedOnUsage && !shortString
);
+ info.suggestionLabel = PowerUtil.getBatteryTipStringFormatted(
+ context, PowerUtil.convertUsToMs(drainTimeUs));
} else {
info.remainingLabel = null;
+ info.suggestionLabel = null;
info.chargeLabel = info.batteryPercentString;
}
}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
new file mode 100644
index 0000000..b14fec9
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
@@ -0,0 +1,41 @@
+package com.android.settings.fuelgauge.batterysaver;
+
+import android.content.Context;
+import android.provider.Settings;
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.PreferenceControllerMixin;
+
+public class BatterySaverStickyPreferenceController extends BasePreferenceController implements
+ PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
+
+ public static final String LOW_POWER_STICKY_AUTO_DISABLE_ENABLED =
+ "low_power_sticky_auto_disable_enabled";
+
+ public BatterySaverStickyPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ int setting = Settings.System.getInt(mContext.getContentResolver(),
+ LOW_POWER_STICKY_AUTO_DISABLE_ENABLED, 1);
+
+ ((SwitchPreference) preference).setChecked(setting == 0);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean keepActive = (Boolean) newValue;
+ Settings.System.putInt(mContext.getContentResolver(),
+ LOW_POWER_STICKY_AUTO_DISABLE_ENABLED,
+ keepActive ? 0 : 1);
+ return true;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/batterytip/AnomalyInfo.java b/src/com/android/settings/fuelgauge/batterytip/AnomalyInfo.java
index 063cfec..fc15706 100644
--- a/src/com/android/settings/fuelgauge/batterytip/AnomalyInfo.java
+++ b/src/com/android/settings/fuelgauge/batterytip/AnomalyInfo.java
@@ -20,7 +20,7 @@
import android.util.Log;
/**
- * Model class to parse and store anomaly info from westworld
+ * Model class to parse and store anomaly info from statsd.
*/
public class AnomalyInfo {
private static final String TAG = "AnomalyInfo";
@@ -38,4 +38,4 @@
autoRestriction = parser.getBoolean(KEY_AUTO_RESTRICTION, false);
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java
index 21cc28a..ca9141d 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java
@@ -62,6 +62,6 @@
}
return new LowBatteryTip(
- state, powerSaveModeOn, mBatteryInfo.remainingLabel);
+ state, powerSaveModeOn, mBatteryInfo.suggestionLabel);
}
}
diff --git a/src/com/android/settings/gestures/SwipeUpPreferenceController.java b/src/com/android/settings/gestures/SwipeUpPreferenceController.java
deleted file mode 100644
index 5e882c4..0000000
--- a/src/com/android/settings/gestures/SwipeUpPreferenceController.java
+++ /dev/null
@@ -1,97 +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.gestures;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-import com.android.internal.R;
-
-public class SwipeUpPreferenceController extends GesturePreferenceController {
-
- private final int ON = 1;
- private final int OFF = 0;
-
- private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
- private static final String PREF_KEY_VIDEO = "gesture_swipe_up_video";
- private final UserManager mUserManager;
-
- public SwipeUpPreferenceController(Context context, String key) {
- super(context, key);
- mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- }
-
- static boolean isGestureAvailable(Context context) {
- if (!context.getResources().getBoolean(R.bool.config_swipe_up_gesture_setting_available)) {
- return false;
- }
-
- final ComponentName recentsComponentName = ComponentName.unflattenFromString(
- context.getString(R.string.config_recentsComponentName));
- if (recentsComponentName == null) {
- return false;
- }
- final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
- .setPackage(recentsComponentName.getPackageName());
- if (context.getPackageManager().resolveService(quickStepIntent,
- PackageManager.MATCH_SYSTEM_ONLY) == null) {
- return false;
- }
- return true;
- }
-
- @Override
- public int getAvailabilityStatus() {
- return isGestureAvailable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
- }
-
- @Override
- public boolean isSliceable() {
- return TextUtils.equals(getPreferenceKey(), "gesture_swipe_up");
- }
-
- @Override
- protected String getVideoPrefKey() {
- return PREF_KEY_VIDEO;
- }
-
- @Override
- public boolean setChecked(boolean isChecked) {
- setSwipeUpPreference(mContext, mUserManager, isChecked ? ON : OFF);
- return true;
- }
-
- public static void setSwipeUpPreference(Context context, UserManager userManager,
- int enabled) {
- Settings.Secure.putInt(context.getContentResolver(),
- Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, enabled);
- }
-
- @Override
- public boolean isChecked() {
- final int defaultValue = mContext.getResources()
- .getBoolean(R.bool.config_swipe_up_gesture_default) ? ON : OFF;
- final int swipeUpEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, defaultValue);
- return swipeUpEnabled != OFF;
- }
-}
diff --git a/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceController.java b/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceController.java
new file mode 100644
index 0000000..129cf90
--- /dev/null
+++ b/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceController.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.android.settings.widget.RadioButtonPreference;
+
+public class SystemNavigationEdgeToEdgePreferenceController extends
+ SystemNavigationPreferenceController {
+ static final String PREF_KEY_EDGE_TO_EDGE = "gesture_edge_to_edge";
+
+ public SystemNavigationEdgeToEdgePreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return TextUtils.equals(PREF_KEY_EDGE_TO_EDGE, getPreferenceKey());
+ }
+
+ @Override
+ public void onRadioButtonClicked(RadioButtonPreference preference) {
+ setSwipeUpEnabled(mContext, true);
+ setEdgeToEdgeGestureEnabled(mContext, true);
+ selectRadioButtonInGroup(PREF_KEY_EDGE_TO_EDGE, mPreferenceScreen);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return isEdgeToEdgeEnabled(mContext);
+ }
+}
diff --git a/src/com/android/settings/gestures/SwipeUpGestureSettings.java b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
similarity index 85%
rename from src/com/android/settings/gestures/SwipeUpGestureSettings.java
rename to src/com/android/settings/gestures/SystemNavigationGestureSettings.java
index a125643..ea5454b 100644
--- a/src/com/android/settings/gestures/SwipeUpGestureSettings.java
+++ b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
@@ -32,12 +32,12 @@
import java.util.List;
@SearchIndexable
-public class SwipeUpGestureSettings extends DashboardFragment {
+public class SystemNavigationGestureSettings extends DashboardFragment {
- private static final String TAG = "SwipeUpGesture";
+ private static final String TAG = "SystemNavigationGesture";
public static final String PREF_KEY_SUGGESTION_COMPLETE =
- "pref_swipe_up_suggestion_complete";
+ "pref_system_navigation_suggestion_complete";
@Override
public void onAttach(Context context) {
@@ -60,7 +60,7 @@
@Override
protected int getPreferenceScreenResId() {
- return R.xml.swipe_up_gesture_settings;
+ return R.xml.system_navigation_gesture_settings;
}
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
@@ -69,13 +69,13 @@
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
- sir.xmlResId = R.xml.swipe_up_gesture_settings;
+ sir.xmlResId = R.xml.system_navigation_gesture_settings;
return Arrays.asList(sir);
}
@Override
protected boolean isPageSearchEnabled(Context context) {
- return SwipeUpPreferenceController.isGestureAvailable(context);
+ return SystemNavigationPreferenceController.isGestureAvailable(context);
}
};
}
diff --git a/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceController.java b/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceController.java
new file mode 100644
index 0000000..f9c95a8
--- /dev/null
+++ b/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceController.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.android.settings.widget.RadioButtonPreference;
+
+public class SystemNavigationLegacyPreferenceController extends
+ SystemNavigationPreferenceController {
+ static final String PREF_KEY_LEGACY = "gesture_legacy";
+
+ public SystemNavigationLegacyPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return TextUtils.equals(PREF_KEY_LEGACY, getPreferenceKey());
+ }
+
+ @Override
+ public void onRadioButtonClicked(RadioButtonPreference preference) {
+ setEdgeToEdgeGestureEnabled(mContext, false);
+ setSwipeUpEnabled(mContext, false);
+ selectRadioButtonInGroup(PREF_KEY_LEGACY, mPreferenceScreen);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return !isEdgeToEdgeEnabled(mContext) && !isSwipeUpEnabled(mContext);
+ }
+}
diff --git a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
new file mode 100644
index 0000000..a11754e
--- /dev/null
+++ b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import static android.os.UserHandle.USER_SYSTEM;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.om.IOverlayManager;
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.View;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.widget.RadioButtonPreference;
+
+public abstract class SystemNavigationPreferenceController extends GesturePreferenceController
+ implements RadioButtonPreference.OnClickListener {
+
+ private static final int OFF = 0;
+ private static final int ON = 1;
+
+ private static final String HIDE_BACK_BUTTON = "quickstepcontroller_hideback";
+ private static final String HIDE_HOME_BUTTON = "quickstepcontroller_hidehome";
+ private static final String HIDE_NAVBAR_DIVIDER = "hide_navigationbar_divider";
+ private static final String SHOW_HANDLE = "quickstepcontroller_showhandle";
+ private static final String ENABLE_CLICK_THROUGH = "quickstepcontroller_clickthrough";
+ private static final String ENABLE_LAUNCHER_SWIPE_TO_HOME = "SWIPE_HOME";
+ private static final String ENABLE_COLOR_ADAPT_FOR_HANDLE = "navbar_color_adapt_enable";
+ private static final String ENABLE_ASSISTANT_GESTURE = "ENABLE_ASSISTANT_GESTURE";
+ private static final String PROTOTYPE_ENABLED = "prototype_enabled";
+
+ private static final int EDGE_SENSITIVITY_WIDTH = 32;
+ private static final String EDGE_SENSITIVITY_KEY = "quickstepcontroller_edge_width_sensitivity";
+
+ private static final String GESTURES_MATCH_MAP_OFF = "000000";
+ private static final String GESTURES_MATCH_MAP_ON = "071133";
+ private static final String GESTURES_MATCH_MAP_KEY = "quickstepcontroller_gesture_match_map";
+
+ private static final String OVERLAY_NAVBAR_TYPE_INSET =
+ "com.android.internal.experiment.navbar.type.inset";
+ private static final String OVERLAY_NAVBAR_TYPE_FLOATING =
+ "com.android.internal.experiment.navbar.type.floating";
+
+ private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
+ private static final String PREF_KEY_VIDEO = "gesture_swipe_up_video";
+
+ private static final String[] RADIO_BUTTONS_IN_GROUP = {
+ SystemNavigationLegacyPreferenceController.PREF_KEY_LEGACY,
+ SystemNavigationSwipeUpPreferenceController.PREF_KEY_SWIPE_UP,
+ SystemNavigationEdgeToEdgePreferenceController.PREF_KEY_EDGE_TO_EDGE,
+ };
+
+ protected PreferenceScreen mPreferenceScreen;
+
+ public SystemNavigationPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return isGestureAvailable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreferenceScreen = screen;
+
+ Preference preference = screen.findPreference(getPreferenceKey());
+ if (preference != null && preference instanceof RadioButtonPreference) {
+ RadioButtonPreference radioPreference = (RadioButtonPreference) preference;
+ radioPreference.setOnClickListener(this);
+ radioPreference.setAppendixVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ if (!isChecked || mPreferenceScreen == null) {
+ return false;
+ }
+ Preference preference = mPreferenceScreen.findPreference(getPreferenceKey());
+ if (preference != null && preference instanceof RadioButtonPreference) {
+ onRadioButtonClicked((RadioButtonPreference) preference);
+ }
+ return true;
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ if (isEdgeToEdgeEnabled(mContext)) {
+ return mContext.getText(R.string.edge_to_edge_navigation_title);
+ } else if (isSwipeUpEnabled(mContext)) {
+ return mContext.getText(R.string.swipe_up_to_switch_apps_title);
+ } else {
+ return mContext.getText(R.string.legacy_navigation_title);
+ }
+ }
+
+ @Override
+ protected String getVideoPrefKey() {
+ return PREF_KEY_VIDEO;
+ }
+
+ static boolean isGestureAvailable(Context context) {
+ if (!context.getResources().getBoolean(
+ com.android.internal.R.bool.config_swipe_up_gesture_setting_available)) {
+ return false;
+ }
+
+ final ComponentName recentsComponentName = ComponentName.unflattenFromString(
+ context.getString(com.android.internal.R.string.config_recentsComponentName));
+ if (recentsComponentName == null) {
+ return false;
+ }
+ final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
+ .setPackage(recentsComponentName.getPackageName());
+ if (context.getPackageManager().resolveService(quickStepIntent,
+ PackageManager.MATCH_SYSTEM_ONLY) == null) {
+ return false;
+ }
+ return true;
+ }
+
+ static void selectRadioButtonInGroup(String preferenceKey, PreferenceScreen screen) {
+ if (screen == null) {
+ return;
+ }
+ for (String key : RADIO_BUTTONS_IN_GROUP) {
+ ((RadioButtonPreference) screen.findPreference(key)).setChecked(
+ TextUtils.equals(key, preferenceKey));
+ }
+ }
+
+ static void setEdgeToEdgeGestureEnabled(Context context, boolean enable) {
+ // TODO(b/127366543): replace all of this with a single switch
+ setBooleanGlobalSetting(context, HIDE_BACK_BUTTON, enable);
+ setBooleanGlobalSetting(context, HIDE_HOME_BUTTON, enable);
+ setBooleanGlobalSetting(context, HIDE_NAVBAR_DIVIDER, enable);
+ setBooleanGlobalSetting(context, SHOW_HANDLE, enable);
+ setBooleanGlobalSetting(context, ENABLE_CLICK_THROUGH, enable);
+ setBooleanGlobalSetting(context, ENABLE_LAUNCHER_SWIPE_TO_HOME, enable);
+ setBooleanGlobalSetting(context, ENABLE_COLOR_ADAPT_FOR_HANDLE, enable);
+ setBooleanGlobalSetting(context, ENABLE_ASSISTANT_GESTURE, enable);
+ setBooleanGlobalSetting(context, PROTOTYPE_ENABLED, enable);
+ Settings.Global.putInt(context.getContentResolver(), EDGE_SENSITIVITY_KEY,
+ EDGE_SENSITIVITY_WIDTH);
+ Settings.Global.putString(context.getContentResolver(), GESTURES_MATCH_MAP_KEY,
+ enable ? GESTURES_MATCH_MAP_ON : GESTURES_MATCH_MAP_OFF);
+
+ IOverlayManager overlayManager = IOverlayManager.Stub
+ .asInterface(ServiceManager.getService(Context.OVERLAY_SERVICE));
+ if (overlayManager != null) {
+ try {
+ overlayManager.setEnabled(OVERLAY_NAVBAR_TYPE_FLOATING, false, USER_SYSTEM);
+ overlayManager.setEnabled(OVERLAY_NAVBAR_TYPE_INSET, enable, USER_SYSTEM);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ static void setBooleanGlobalSetting(Context context, String name, boolean flag) {
+ Settings.Global.putInt(context.getContentResolver(), name, flag ? ON : OFF);
+ }
+
+ static void setSwipeUpEnabled(Context context, boolean enabled) {
+ Settings.Secure.putInt(context.getContentResolver(),
+ Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, enabled ? ON : OFF);
+ }
+
+ static boolean isSwipeUpEnabled(Context context) {
+ if (isEdgeToEdgeEnabled(context)) {
+ return false;
+ }
+ final int defaultSwipeUpValue = context.getResources()
+ .getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_default) ? ON : OFF;
+ return Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, defaultSwipeUpValue) == ON;
+ }
+
+ static boolean isEdgeToEdgeEnabled(Context context) {
+ return Settings.Global.getInt(context.getContentResolver(), PROTOTYPE_ENABLED, OFF) == ON;
+ }
+}
diff --git a/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceController.java b/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceController.java
new file mode 100644
index 0000000..25fafdb
--- /dev/null
+++ b/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceController.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.android.settings.widget.RadioButtonPreference;
+
+public class SystemNavigationSwipeUpPreferenceController extends
+ SystemNavigationPreferenceController {
+ static final String PREF_KEY_SWIPE_UP = "gesture_swipe_up";
+
+ public SystemNavigationSwipeUpPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return TextUtils.equals(PREF_KEY_SWIPE_UP, getPreferenceKey());
+ }
+
+ @Override
+ public void onRadioButtonClicked(RadioButtonPreference preference) {
+ setEdgeToEdgeGestureEnabled(mContext, false);
+ setSwipeUpEnabled(mContext, true);
+ selectRadioButtonInGroup(PREF_KEY_SWIPE_UP, mPreferenceScreen);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return isSwipeUpEnabled(mContext);
+ }
+}
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index 9e869a9..9b83f88 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -17,6 +17,7 @@
package com.android.settings.homepage;
import android.animation.LayoutTransition;
+import android.app.ActivityManager;
import android.app.settings.SettingsEnums;
import android.os.Bundle;
import android.view.View;
@@ -53,7 +54,10 @@
final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);
getLifecycle().addObserver(avatarViewMixin);
- showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
+ if (!getSystemService(ActivityManager.class).isLowRamDevice()) {
+ // Only allow contextual feature on high ram devices.
+ showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
+ }
showFragment(new TopLevelSettings(), R.id.main_content);
((FrameLayout) findViewById(R.id.main_content))
.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
index 12590ff..43e90e8 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
@@ -165,6 +165,7 @@
com.android.settings.intelligence.ContextualCardProto.ContextualCard.newBuilder()
.setSliceUri(card.getSliceUri().toString())
.setCardName(card.getName())
+ .setCardScore(card.getRankingScore())
.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 ea6ac43..13564b5 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -26,7 +26,6 @@
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
-import android.text.format.DateUtils;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -50,7 +49,6 @@
@VisibleForTesting
static final int DEFAULT_CARD_COUNT = 4;
static final int CARD_CONTENT_LOADER_ID = 1;
- static final long CARD_CONTENT_LOADER_TIMEOUT_MS = DateUtils.SECOND_IN_MILLIS;
private static final String TAG = "ContextualCardLoader";
private static final long ELIGIBILITY_CHECKER_TIMEOUT_MS = 250;
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 3b8aacd..c829015 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -24,6 +24,8 @@
import android.content.Context;
import android.os.Bundle;
+import android.provider.Settings;
+import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.widget.BaseAdapter;
@@ -62,8 +64,12 @@
public class ContextualCardManager implements ContextualCardLoader.CardContentLoaderListener,
ContextualCardUpdateListener, LifecycleObserver, OnSaveInstanceState {
- private static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards";
+ @VisibleForTesting
+ static final long CARD_CONTENT_LOADER_TIMEOUT_MS = DateUtils.SECOND_IN_MILLIS;
+ @VisibleForTesting
+ static final String KEY_GLOBAL_CARD_LOADER_TIMEOUT = "global_card_loader_timeout_key";
+ private static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards";
private static final String TAG = "ContextualCardManager";
//The list for Settings Custom Card
@@ -201,7 +207,8 @@
}
//only log homepage display upon a fresh launch
- if (loadTime <= ContextualCardLoader.CARD_CONTENT_LOADER_TIMEOUT_MS) {
+ final long timeoutLimit = getCardLoaderTimeout(mContext);
+ if (loadTime <= timeoutLimit) {
onContextualCardUpdated(cards.stream()
.collect(groupingBy(ContextualCard::getCardType)));
}
@@ -239,6 +246,14 @@
return getCardsWithSuggestionViewType(result);
}
+ @VisibleForTesting
+ long getCardLoaderTimeout(Context context) {
+ // Return the timeout limit if Settings.Global has the KEY_GLOBAL_CARD_LOADER_TIMEOUT key,
+ // else return default timeout.
+ return Settings.Global.getLong(mContext.getContentResolver(),
+ KEY_GLOBAL_CARD_LOADER_TIMEOUT, CARD_CONTENT_LOADER_TIMEOUT_MS);
+ }
+
private List<ContextualCard> getCardsWithSuggestionViewType(List<ContextualCard> cards) {
// Shows as half cards if 2 suggestion type of cards are next to each other.
// Shows as full card if 1 suggestion type of card lives alone.
diff --git a/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java b/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
index 5423ce3..fe68d02 100644
--- a/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
+++ b/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
@@ -51,6 +51,9 @@
@VisibleForTesting
boolean isCardEligibleToDisplay(ContextualCard card) {
+ if (card.getRankingScore() < 0) {
+ return false;
+ }
if (card.isCustomCard()) {
return true;
}
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSlice.java
deleted file mode 100644
index 6c7f930..0000000
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSlice.java
+++ /dev/null
@@ -1,139 +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.deviceinfo;
-
-import android.app.PendingIntent;
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.Uri;
-import android.os.PowerManager;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.core.graphics.drawable.IconCompat;
-import androidx.slice.Slice;
-import androidx.slice.builders.ListBuilder;
-import androidx.slice.builders.SliceAction;
-
-import com.android.settings.R;
-import com.android.settings.SubSettings;
-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;
-
-/**
- * Utility class to build a Battery Slice, and handle all associated actions.
- */
-public class BatteryInfoSlice implements CustomSliceable {
- private static final String TAG = "BatteryInfoSlice";
-
- private final Context mContext;
-
- private BatteryInfo mBatteryInfo;
- private boolean mIsBatteryInfoLoading;
-
- public BatteryInfoSlice(Context context) {
- mContext = context;
- }
-
- @Override
- public Slice getSlice() {
- if (mBatteryInfo == null) {
- mIsBatteryInfoLoading = true;
- loadBatteryInfo();
- }
- final IconCompat icon = IconCompat.createWithResource(mContext,
- R.drawable.ic_settings_battery);
- 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, CustomSliceRegistry.BATTERY_INFO_SLICE_URI,
- ListBuilder.INFINITY)
- .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
- .setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
- .addRow(new ListBuilder.RowBuilder()
- .setTitle(getBatteryPercentString(), mIsBatteryInfoLoading)
- .setSubtitle(getSummary(), mIsBatteryInfoLoading)
- .setPrimaryAction(primarySliceAction))
- .build();
- mBatteryInfo = null;
- mIsBatteryInfoLoading = false;
- return slice;
- }
-
- @Override
- public Uri getUri() {
- return CustomSliceRegistry.BATTERY_INFO_SLICE_URI;
- }
-
- @Override
- public void onNotifyChange(Intent intent) {
-
- }
-
- @Override
- public Intent getIntent() {
- final String screenTitle = mContext.getText(R.string.power_usage_summary_title).toString();
- return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
- PowerUsageSummary.class.getName(), "" /* key */, screenTitle,
- SettingsEnums.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName())
- .setData(CustomSliceRegistry.BATTERY_INFO_SLICE_URI);
- }
-
- @Override
- public IntentFilter getIntentFilter() {
- final IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
- intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
- intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
- intentFilter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED);
- return intentFilter;
- }
-
- @VisibleForTesting
- void loadBatteryInfo() {
- BatteryInfo.getBatteryInfo(mContext, info -> {
- mBatteryInfo = info;
- mContext.getContentResolver().notifyChange(getUri(), null);
- }, true);
- }
-
- @VisibleForTesting
- CharSequence getBatteryPercentString() {
- return mBatteryInfo == null ? null : mBatteryInfo.batteryPercentString;
- }
-
- @VisibleForTesting
- CharSequence getSummary() {
- if (mBatteryInfo == null) {
- return null;
- }
- return mBatteryInfo.remainingLabel == null ? mBatteryInfo.statusLabel
- : mBatteryInfo.remainingLabel;
- }
-
- private PendingIntent getPrimaryAction() {
- final Intent intent = getIntent();
- 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/BluetoothDevicesSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
index 95412a8..99fe219 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
@@ -16,11 +16,14 @@
package com.android.settings.homepage.contextualcards.slices;
+import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
@@ -87,6 +90,9 @@
@Override
public Slice getSlice() {
+ // Reload theme for switching dark mode on/off
+ mContext.getTheme().applyStyle(R.style.Theme_Settings_Home, true /* force */);
+
final IconCompat icon = IconCompat.createWithResource(mContext,
com.android.internal.R.drawable.ic_settings_bluetooth);
final CharSequence title = mContext.getText(R.string.bluetooth_devices);
@@ -98,7 +104,7 @@
ListBuilder.ICON_IMAGE, title);
final ListBuilder listBuilder =
new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
- .setAccentColor(Utils.getColorAccentDefaultColor(mContext));
+ .setAccentColor(COLOR_NOT_TINTED);
// Get row builders by Bluetooth devices.
final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilder();
@@ -179,14 +185,9 @@
final Collection<CachedBluetoothDevice> cachedDevices =
bluetoothManager.getCachedDeviceManager().getCachedDevicesCopy();
- /**
- * TODO(b/114807655): Contextual Home Page - Connected Device
- * It's under discussion for including available media devices and currently connected
- * devices from Bluetooth. Will update the devices list or remove TODO later.
- */
- // Get available media device list and sort them.
+ // Get all connected devices and sort them.
return cachedDevices.stream()
- .filter(device -> device.isConnected() && device.isConnectedA2dpDevice())
+ .filter(device -> device.getDevice().isConnected())
.sorted(COMPARATOR).collect(Collectors.toList());
}
@@ -212,13 +213,23 @@
IconCompat getBluetoothDeviceIcon(CachedBluetoothDevice device) {
final Pair<Drawable, String> pair = BluetoothUtils
.getBtClassDrawableWithDescription(mContext, device);
+ final Drawable drawable = pair.first;
- if (pair.first != null) {
- return Utils.createIconWithDrawable(pair.first);
- } else {
+ // Use default bluetooth icon if can't get icon.
+ if (drawable == null) {
return IconCompat.createWithResource(mContext,
- com.android.internal.R.drawable.ic_settings_bluetooth);
+ com.android.internal.R.drawable.ic_settings_bluetooth);
}
+
+ // Tint icon: Accent color for connected state; Disable color for busy state.
+ @ColorInt int color = Utils.getColorAccentDefaultColor(mContext);
+ if (device.isBusy()) {
+ color = Utils.getDisabled(mContext,
+ Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal));
+ }
+ drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
+
+ return Utils.createIconWithDrawable(drawable);
}
private List<ListBuilder.RowBuilder> getBluetoothRowBuilder() {
@@ -226,18 +237,29 @@
final List<ListBuilder.RowBuilder> bluetoothRows = new ArrayList<>();
final List<CachedBluetoothDevice> bluetoothDevices = getConnectedBluetoothDevices();
for (CachedBluetoothDevice bluetoothDevice : bluetoothDevices) {
- bluetoothRows.add(new ListBuilder.RowBuilder()
+ final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
.setTitleItem(getBluetoothDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
.setTitle(bluetoothDevice.getName())
- .setSubtitle(bluetoothDevice.getConnectionSummary())
- .setPrimaryAction(buildBluetoothDeviceAction(bluetoothDevice))
- .addEndItem(buildBluetoothDetailDeepLinkAction(bluetoothDevice)));
+ .setSubtitle(bluetoothDevice.getConnectionSummary());
+
+ if (bluetoothDevice.isConnectedA2dpDevice()) {
+ // For available media devices, the primary action is to activate audio stream and
+ // add setting icon to the end to link detail page.
+ rowBuilder.setPrimaryAction(buildMediaBluetoothAction(bluetoothDevice));
+ rowBuilder.addEndItem(buildBluetoothDetailDeepLinkAction(bluetoothDevice));
+ } else {
+ // For other devices, the primary action is to link detail page.
+ rowBuilder.setPrimaryAction(buildBluetoothDetailDeepLinkAction(bluetoothDevice));
+ }
+
+ bluetoothRows.add(rowBuilder);
}
return bluetoothRows;
}
- private SliceAction buildBluetoothDeviceAction(CachedBluetoothDevice bluetoothDevice) {
+ @VisibleForTesting
+ SliceAction buildMediaBluetoothAction(CachedBluetoothDevice bluetoothDevice) {
// Send broadcast to activate available media device.
final Intent intent = new Intent(getUri().toString())
.setClass(mContext, SliceBroadcastReceiver.class)
@@ -250,10 +272,11 @@
bluetoothDevice.getName());
}
- private SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
+ @VisibleForTesting
+ SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
return SliceAction.createDeeplink(
getBluetoothDetailIntent(bluetoothDevice),
- IconCompat.createWithResource(mContext, R.drawable.ic_settings_24dp),
+ IconCompat.createWithResource(mContext, R.drawable.ic_settings_accent),
ListBuilder.ICON_IMAGE,
bluetoothDevice.getName());
}
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java b/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java
index ef0a67d..ee63536 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java
@@ -16,6 +16,7 @@
package com.android.settings.homepage.contextualcards.slices;
+import android.animation.LayoutTransition;
import android.content.Context;
import android.view.View;
@@ -94,6 +95,7 @@
public SliceViewHolder(View view) {
super(view);
sliceView = view.findViewById(R.id.slice_view);
+ sliceView.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
}
}
}
diff --git a/src/com/android/settings/media/MediaDeviceUpdateWorker.java b/src/com/android/settings/media/MediaDeviceUpdateWorker.java
index 7416018..d1e55e4 100644
--- a/src/com/android/settings/media/MediaDeviceUpdateWorker.java
+++ b/src/com/android/settings/media/MediaDeviceUpdateWorker.java
@@ -70,7 +70,7 @@
@Override
public void close() {
-
+ mLocalMediaManager = null;
}
@Override
diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java
index d52b441..232986c 100644
--- a/src/com/android/settings/media/MediaOutputSlice.java
+++ b/src/com/android/settings/media/MediaOutputSlice.java
@@ -20,13 +20,11 @@
import android.annotation.ColorInt;
import android.app.PendingIntent;
+import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.os.UserHandle;
-import android.util.IconDrawableFactory;
+import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -58,37 +56,48 @@
private MediaDeviceUpdateWorker mWorker;
private String mPackageName;
- private IconDrawableFactory mIconDrawableFactory;
public MediaOutputSlice(Context context) {
mContext = context;
mPackageName = getUri().getQueryParameter(MEDIA_PACKAGE_NAME);
- mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
}
@VisibleForTesting
- void init(String packageName, MediaDeviceUpdateWorker worker, IconDrawableFactory factory) {
+ void init(String packageName, MediaDeviceUpdateWorker worker) {
mPackageName = packageName;
mWorker = worker;
- mIconDrawableFactory = factory;
}
@Override
public Slice getSlice() {
- final PackageManager pm = mContext.getPackageManager();
+ final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (!adapter.isEnabled()) {
+ Log.d(TAG, "getSlice() Bluetooth is off");
+ return null;
+ }
final List<MediaDevice> devices = getMediaDevices();
- final CharSequence title = Utils.getApplicationLabel(mContext, mPackageName);
- final CharSequence summary =
- mContext.getString(R.string.media_output_panel_summary_of_playing_device,
- getConnectedDeviceName());
-
- final Drawable drawable =
- Utils.getBadgedIcon(mIconDrawableFactory, pm, mPackageName, UserHandle.myUserId());
- final IconCompat icon = Utils.createIconWithDrawable(drawable);
-
@ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
- final SliceAction primarySliceAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+
+ final MediaDevice connectedDevice = getWorker().getCurrentConnectedMediaDevice();
+ final ListBuilder listBuilder = buildActiveDeviceHeader(color, connectedDevice);
+
+ for (MediaDevice device : devices) {
+ if (!TextUtils.equals(connectedDevice.getId(), device.getId())) {
+ listBuilder.addRow(getMediaDeviceRow(device));
+ }
+ }
+
+ return listBuilder.build();
+ }
+
+ private ListBuilder buildActiveDeviceHeader(@ColorInt int color, MediaDevice device) {
+ final String title = device.getName();
+ final IconCompat icon = IconCompat.createWithResource(mContext, device.getIcon());
+
+ final PendingIntent broadcastAction =
+ getBroadcastIntent(mContext, device.getId(), device.hashCode());
+ final SliceAction primarySliceAction = SliceAction.createDeeplink(broadcastAction, icon,
ListBuilder.ICON_IMAGE, title);
final ListBuilder listBuilder = new ListBuilder(mContext, MEDIA_OUTPUT_SLICE_URI,
@@ -97,14 +106,10 @@
.addRow(new ListBuilder.RowBuilder()
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setTitle(title)
- .setSubtitle(summary)
+ .setSubtitle(device.getSummary())
.setPrimaryAction(primarySliceAction));
- for (MediaDevice device : devices) {
- listBuilder.addRow(getMediaDeviceRow(device));
- }
-
- return listBuilder.build();
+ return listBuilder;
}
private MediaDeviceUpdateWorker getWorker() {
@@ -120,18 +125,6 @@
return devices;
}
- private String getConnectedDeviceName() {
- final MediaDevice device = getWorker().getCurrentConnectedMediaDevice();
- return device != null ? device.getName() : "";
- }
-
- private PendingIntent getPrimaryAction() {
- final PackageManager pm = mContext.getPackageManager();
- final Intent launchIntent = pm.getLaunchIntentForPackage(mPackageName);
- final Intent intent = launchIntent;
- return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
- }
-
private ListBuilder.RowBuilder getMediaDeviceRow(MediaDevice device) {
final String title = device.getName();
final PendingIntent broadcastAction =
@@ -141,7 +134,8 @@
.setTitleItem(deviceIcon, ListBuilder.ICON_IMAGE)
.setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
ListBuilder.ICON_IMAGE, title))
- .setTitle(title);
+ .setTitle(title)
+ .setSubtitle(device.getSummary());
return rowBuilder;
}
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index dd282c6..a1fef4c 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -29,6 +29,7 @@
import android.telephony.euicc.EuiccManager;
import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settings.widget.AddPreference;
import com.android.settingslib.Utils;
@@ -43,7 +44,8 @@
import androidx.preference.PreferenceScreen;
public class MobileNetworkSummaryController extends AbstractPreferenceController implements
- SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver {
+ SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver,
+ PreferenceControllerMixin {
private static final String TAG = "MobileNetSummaryCtlr";
private static final String KEY = "mobile_network_list";
@@ -74,8 +76,10 @@
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mTelephonyMgr = mContext.getSystemService(TelephonyManager.class);
mEuiccManager = mContext.getSystemService(EuiccManager.class);
- mChangeListener = new SubscriptionsChangeListener(context, this);
- lifecycle.addObserver(this);
+ if (lifecycle != null) {
+ mChangeListener = new SubscriptionsChangeListener(context, this);
+ lifecycle.addObserver(this);
+ }
}
@OnLifecycleEvent(ON_RESUME)
@@ -116,6 +120,7 @@
private void startAddSimFlow() {
final Intent intent = new Intent(EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
+ intent.putExtra(EuiccManager.EXTRA_FORCE_PROVISION, true);
mContext.startActivity(intent);
}
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index 7672c2e..8c686a5 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -168,7 +168,12 @@
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
- sir.xmlResId = R.xml.network_and_internet;
+ if (FeatureFlagPersistent.isEnabled(context,
+ FeatureFlags.NETWORK_INTERNET_V2)) {
+ sir.xmlResId = R.xml.network_and_internet_v2;
+ } else {
+ sir.xmlResId = R.xml.network_and_internet;
+ }
return Arrays.asList(sir);
}
diff --git a/src/com/android/settings/network/TopLevelNetworkEntryPreferenceController.java b/src/com/android/settings/network/TopLevelNetworkEntryPreferenceController.java
index 567e52e..1136736 100644
--- a/src/com/android/settings/network/TopLevelNetworkEntryPreferenceController.java
+++ b/src/com/android/settings/network/TopLevelNetworkEntryPreferenceController.java
@@ -22,6 +22,7 @@
import android.text.TextUtils;
import com.android.settings.R;
+import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.wifi.WifiMasterSwitchPreferenceController;
@@ -45,7 +46,7 @@
@Override
public int getAvailabilityStatus() {
- return AVAILABLE_UNSEARCHABLE;
+ return Utils.isDemoUser(mContext) ? UNSUPPORTED_ON_DEVICE : AVAILABLE_UNSEARCHABLE;
}
@Override
diff --git a/src/com/android/settings/network/telephony/MobileDataSlice.java b/src/com/android/settings/network/telephony/MobileDataSlice.java
index 6efd8c3..5a5d6a2 100644
--- a/src/com/android/settings/network/telephony/MobileDataSlice.java
+++ b/src/com/android/settings/network/telephony/MobileDataSlice.java
@@ -74,8 +74,27 @@
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_network_cell);
final String title = mContext.getText(R.string.mobile_data_settings_title).toString();
- final CharSequence summary = getSummary();
@ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
+
+ // Return a Slice without the mobile data toggle when airplane mode is on.
+ if (isAirplaneModeEnabled()) {
+ final CharSequence summary = mContext.getText(R.string.mobile_data_ap_mode_disabled);
+ // Intent does nothing, but we have to pass an intent to the Row.
+ final PendingIntent intent = PendingIntent.getActivity(mContext, 0 /* requestCode */,
+ new Intent(), 0 /* flags */);
+ final SliceAction deadAction =
+ SliceAction.create(intent, icon, ListBuilder.ICON_IMAGE, title);
+ final ListBuilder listBuilder = new ListBuilder(mContext, getUri(),
+ ListBuilder.INFINITY)
+ .setAccentColor(color)
+ .addRow(new ListBuilder.RowBuilder()
+ .setTitle(title)
+ .setSubtitle(summary)
+ .setPrimaryAction(deadAction));
+ return listBuilder.build();
+ }
+
+ final CharSequence summary = getSummary();
final PendingIntent toggleAction = getBroadcastIntent(mContext);
final PendingIntent primaryAction = getPrimaryAction();
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
@@ -101,11 +120,6 @@
@Override
public void onNotifyChange(Intent intent) {
- // Don't make a change if we are in Airplane Mode.
- if (isAirplaneModeEnabled()) {
- return;
- }
-
final boolean newState = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
isMobileDataEnabled());
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 5553dd7..9f5ece2 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -16,6 +16,8 @@
package com.android.settings.notification;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.settings.SettingsEnums;
@@ -24,6 +26,8 @@
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
+import android.view.Window;
+import android.view.WindowManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
@@ -33,7 +37,6 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
-import com.android.settings.widget.MasterCheckBoxPreference;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -85,6 +88,8 @@
public void onResume() {
super.onResume();
+ getActivity().getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+
if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
Log.w(TAG, "Missing package or uid or packageinfo");
finish();
@@ -119,6 +124,15 @@
}
@Override
+ public void onPause() {
+ super.onPause();
+ final Window window = getActivity().getWindow();
+ final WindowManager.LayoutParams attrs = window.getAttributes();
+ attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+ window.setAttributes(attrs);
+ }
+
+ @Override
protected String getLogTag() {
return TAG;
}
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index b26b921..eec0fb8 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -38,7 +38,6 @@
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.sound.HandsFreeProfileOutputPreferenceController;
-import com.android.settings.sound.MediaOutputPreferenceController;
import com.android.settings.widget.PreferenceCategoryController;
import com.android.settings.widget.UpdatableListPreferenceDialogFragment;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -77,7 +76,6 @@
private RingtonePreference mRequestPreference;
private UpdatableListPreferenceDialogFragment mDialogFragment;
- private String mMediaOutputControllerKey;
private String mHfpOutputControllerKey;
@Override
@@ -132,8 +130,6 @@
final int metricsCategory;
if (mHfpOutputControllerKey.equals(preference.getKey())) {
metricsCategory = SettingsEnums.DIALOG_SWITCH_HFP_DEVICES;
- } else if (mMediaOutputControllerKey.equals(preference.getKey())) {
- metricsCategory = SettingsEnums.DIALOG_SWITCH_A2DP_DEVICES;
} else {
metricsCategory = Instrumentable.METRICS_CATEGORY_UNKNOWN;
}
@@ -186,9 +182,6 @@
volumeControllers.add(use(CallVolumePreferenceController.class));
volumeControllers.add(use(RemoteVolumePreferenceController.class));
- use(MediaOutputPreferenceController.class).setCallback(listPreference ->
- onPreferenceDataChanged(listPreference));
- mMediaOutputControllerKey = use(MediaOutputPreferenceController.class).getPreferenceKey();
use(HandsFreeProfileOutputPreferenceController.class).setCallback(listPreference ->
onPreferenceDataChanged(listPreference));
mHfpOutputControllerKey =
diff --git a/src/com/android/settings/panel/NfcPanel.java b/src/com/android/settings/panel/NfcPanel.java
index 8fa41d9..6a9c74d 100644
--- a/src/com/android/settings/panel/NfcPanel.java
+++ b/src/com/android/settings/panel/NfcPanel.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2019 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.panel;
import android.app.settings.SettingsEnums;
diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
index 6b096a1..67c300f 100644
--- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java
+++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
@@ -28,12 +28,14 @@
switch (panelType) {
case Settings.Panel.ACTION_INTERNET_CONNECTIVITY:
return InternetConnectivityPanel.create(context);
- case Settings.Panel.ACTION_VOLUME:
- return VolumePanel.create(context);
- case Settings.Panel.ACTION_NFC:
- return NfcPanel.create(context);
case ACTION_MEDIA_OUTPUT:
return MediaOutputPanel.create(context, mediaPackageName);
+ case Settings.Panel.ACTION_NFC:
+ return NfcPanel.create(context);
+ case Settings.Panel.ACTION_WIFI:
+ return WifiPanel.create(context);
+ case Settings.Panel.ACTION_VOLUME:
+ return VolumePanel.create(context);
}
throw new IllegalStateException("No matching panel for: " + panelType);
diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java
index 3819c80..8aee382 100644
--- a/src/com/android/settings/panel/SettingsPanelActivity.java
+++ b/src/com/android/settings/panel/SettingsPanelActivity.java
@@ -16,13 +16,11 @@
package com.android.settings.panel;
-import static com.android.settingslib.media.MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT;
import static com.android.settingslib.media.MediaOutputSliceConstants.EXTRA_PACKAGE_NAME;
import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.os.Bundle;
-import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -75,15 +73,8 @@
return;
}
- final String mediaPackageName =
- callingIntent.getStringExtra(EXTRA_PACKAGE_NAME);
-
- if (TextUtils.equals(ACTION_MEDIA_OUTPUT, callingIntent.getAction())
- && TextUtils.isEmpty(mediaPackageName)) {
- Log.e(TAG, "Missing EXTRA_PACKAGE_NAME, closing Panel Activity");
- finish();
- return;
- }
+ // We will use it once media output switch panel support remote device.
+ final String mediaPackageName = callingIntent.getStringExtra(EXTRA_PACKAGE_NAME);
setContentView(R.layout.settings_panel);
diff --git a/src/com/android/settings/panel/WifiPanel.java b/src/com/android/settings/panel/WifiPanel.java
new file mode 100644
index 0000000..6d83742
--- /dev/null
+++ b/src/com/android/settings/panel/WifiPanel.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 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.panel;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.android.settings.R;
+import com.android.settings.SubSettings;
+import com.android.settings.network.NetworkDashboardFragment;
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.SliceBuilderUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Panel data class for Wifi settings.
+ */
+public class WifiPanel implements PanelContent {
+
+ private final Context mContext;
+
+ public static WifiPanel create(Context context) {
+ return new WifiPanel(context);
+ }
+
+ private WifiPanel(Context context) {
+ mContext = context.getApplicationContext();
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mContext.getText(R.string.wifi_settings);
+ }
+
+ @Override
+ public List<Uri> getSlices() {
+ final List<Uri> uris = new ArrayList<>();
+ uris.add(CustomSliceRegistry.WIFI_SLICE_URI);
+ return uris;
+ }
+
+ @Override
+ public Intent getSeeMoreIntent() {
+ final String screenTitle =
+ mContext.getText(R.string.network_dashboard_title).toString();
+ final Intent intent = SliceBuilderUtils.buildSearchResultPageIntent(mContext,
+ NetworkDashboardFragment.class.getName(),
+ null /* key */,
+ screenTitle,
+ SettingsEnums.SETTINGS_NETWORK_CATEGORY);
+ intent.setClassName(mContext.getPackageName(), SubSettings.class.getName());
+ return intent;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.PANEL_WIFI;
+ }
+}
diff --git a/src/com/android/settings/password/SetNewPasswordActivity.java b/src/com/android/settings/password/SetNewPasswordActivity.java
index d7445e6..4722c56 100644
--- a/src/com/android/settings/password/SetNewPasswordActivity.java
+++ b/src/com/android/settings/password/SetNewPasswordActivity.java
@@ -16,7 +16,7 @@
package com.android.settings.password;
-import static android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY;
+import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
import static android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY;
@@ -83,7 +83,7 @@
if (ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction)
&& getIntent().hasExtra(EXTRA_PASSWORD_COMPLEXITY)) {
final boolean hasPermission = PasswordUtils.isCallingAppPermitted(
- this, activityToken, REQUEST_SCREEN_LOCK_COMPLEXITY);
+ this, activityToken, REQUEST_PASSWORD_COMPLEXITY);
if (hasPermission) {
mRequestedMinComplexity =
PasswordMetrics.sanitizeComplexityLevel(getIntent()
@@ -91,7 +91,7 @@
} else {
PasswordUtils.crashCallingApplication(activityToken,
"Must have permission "
- + REQUEST_SCREEN_LOCK_COMPLEXITY + " to use extra "
+ + REQUEST_PASSWORD_COMPLEXITY + " to use extra "
+ EXTRA_PASSWORD_COMPLEXITY);
finish();
return;
diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java
index 7fbb211..346e771 100644
--- a/src/com/android/settings/password/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/password/SetupChooseLockGeneric.java
@@ -16,7 +16,7 @@
package com.android.settings.password;
-import static android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY;
+import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
@@ -82,10 +82,10 @@
if(getIntent().hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)) {
IBinder activityToken = getActivityToken();
boolean hasPermission = PasswordUtils.isCallingAppPermitted(
- this, activityToken, REQUEST_SCREEN_LOCK_COMPLEXITY);
+ this, activityToken, REQUEST_PASSWORD_COMPLEXITY);
if (!hasPermission) {
PasswordUtils.crashCallingApplication(activityToken,
- "Must have permission " + REQUEST_SCREEN_LOCK_COMPLEXITY
+ "Must have permission " + REQUEST_PASSWORD_COMPLEXITY
+ " to use extra " + EXTRA_PASSWORD_COMPLEXITY);
finish();
return;
diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java
index d120062..8d40175 100644
--- a/src/com/android/settings/print/PrintServiceSettingsFragment.java
+++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java
@@ -143,6 +143,8 @@
@Override
public void onStart() {
super.onStart();
+ initComponents();
+ updateUiForArguments();
updateEmptyView();
updateUiForServiceState();
}
@@ -158,20 +160,9 @@
@Override
public void onStop() {
super.onStop();
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- initComponents();
- updateUiForArguments();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
mSwitchBar.removeOnSwitchChangeListener(this);
mSwitchBar.hide();
+ mPrintersAdapter.unregisterAdapterDataObserver(mDataObserver);
}
private void onPreferenceToggled(String preferenceKey, boolean enabled) {
diff --git a/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java b/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java
new file mode 100644
index 0000000..b3ea9a7
--- /dev/null
+++ b/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 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.privacy;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.view.contentcapture.ContentCaptureManager;
+
+import com.android.settings.core.TogglePreferenceController;
+
+public class EnableContentCapturePreferenceController extends TogglePreferenceController {
+
+ private static final String KEY_SHOW_PASSWORD = "content_capture";
+ private static final int MY_USER_ID = UserHandle.myUserId();
+
+ public EnableContentCapturePreferenceController(Context context) {
+ super(context, KEY_SHOW_PASSWORD);
+ }
+
+ @Override
+ public boolean isChecked() {
+ boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.CONTENT_CAPTURE_ENABLED, 1, MY_USER_ID) == 1;
+ return enabled;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.CONTENT_CAPTURE_ENABLED, isChecked ? 1 : 0, MY_USER_ID);
+ return true;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ // We cannot look for ContentCaptureManager, because it's not available if the service
+ // didn't whitelist Settings
+ IBinder service = ServiceManager.checkService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
+ return service != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+}
diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java
index c9e473a..91f55ae 100644
--- a/src/com/android/settings/slices/CustomSliceManager.java
+++ b/src/com/android/settings/slices/CustomSliceManager.java
@@ -18,25 +18,6 @@
import android.content.Context;
import android.net.Uri;
-import android.util.ArrayMap;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.settings.flashlight.FlashlightSlice;
-import com.android.settings.homepage.contextualcards.deviceinfo.BatteryInfoSlice;
-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.BluetoothDevicesSlice;
-import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
-import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
-import com.android.settings.location.LocationSlice;
-import com.android.settings.media.MediaOutputSlice;
-import com.android.settings.network.telephony.MobileDataSlice;
-import com.android.settings.wifi.slice.ContextualWifiSlice;
-import com.android.settings.wifi.slice.WifiSlice;
import java.util.Map;
import java.util.WeakHashMap;
@@ -47,17 +28,12 @@
*/
public class CustomSliceManager {
- @VisibleForTesting
- final Map<Uri, Class<? extends CustomSliceable>> mUriMap;
-
private final Context mContext;
private final Map<Uri, CustomSliceable> mSliceableCache;
public CustomSliceManager(Context context) {
mContext = context.getApplicationContext();
- mUriMap = new ArrayMap<>();
mSliceableCache = new WeakHashMap<>();
- addSlices();
}
/**
@@ -67,12 +43,12 @@
* the only thing that should be needed to create the object.
*/
public CustomSliceable getSliceableFromUri(Uri uri) {
- final Uri newUri = removeParameterFromUri(uri);
+ final Uri newUri = CustomSliceRegistry.removeParameterFromUri(uri);
if (mSliceableCache.containsKey(newUri)) {
return mSliceableCache.get(newUri);
}
- final Class clazz = mUriMap.get(newUri);
+ final Class clazz = CustomSliceRegistry.getSliceClassByUri(newUri);
if (clazz == null) {
throw new IllegalArgumentException("No Slice found for uri: " + uri);
}
@@ -82,9 +58,6 @@
return sliceable;
}
- private Uri removeParameterFromUri(Uri uri) {
- return uri != null ? uri.buildUpon().clearQuery().build() : null;
- }
/**
* Return a {@link CustomSliceable} associated to the Action.
@@ -95,39 +68,4 @@
public CustomSliceable getSliceableFromIntentAction(String action) {
return getSliceableFromUri(Uri.parse(action));
}
-
- /**
- * Returns {@code true} if {@param uri} is a valid Slice Uri handled by
- * {@link CustomSliceManager}.
- */
- public boolean isValidUri(Uri uri) {
- return mUriMap.containsKey(removeParameterFromUri(uri));
- }
-
- /**
- * Returns {@code true} if {@param action} is a valid intent action handled by
- * {@link CustomSliceManager}.
- */
- public boolean isValidAction(String action) {
- return isValidUri(Uri.parse(action));
- }
-
- private void addSlices() {
- mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
- mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatteryInfoSlice.class);
- mUriMap.put(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
- mUriMap.put(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.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.MOBILE_DATA_SLICE_URI, MobileDataSlice.class);
- mUriMap.put(CustomSliceRegistry.NOTIFICATION_CHANNEL_SLICE_URI,
- NotificationChannelSlice.class);
- mUriMap.put(CustomSliceRegistry.STORAGE_SLICE_URI, StorageSlice.class);
- mUriMap.put(CustomSliceRegistry.WIFI_SLICE_URI, WifiSlice.class);
- mUriMap.put(CustomSliceRegistry.MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
- }
}
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index 3a1db69..12e7b48 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -24,11 +24,30 @@
import android.content.ContentResolver;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
+import android.util.ArrayMap;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.flashlight.FlashlightSlice;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
+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.BluetoothDevicesSlice;
+import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
+import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
+import com.android.settings.location.LocationSlice;
+import com.android.settings.media.MediaOutputSlice;
+import com.android.settings.network.telephony.MobileDataSlice;
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
+import com.android.settings.wifi.slice.ContextualWifiSlice;
+import com.android.settings.wifi.slice.WifiSlice;
import com.android.settingslib.media.MediaOutputSliceConstants;
+import java.util.Map;
+
/**
* A registry of custom slice Uris.
*/
@@ -53,15 +72,7 @@
.appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
.appendPath(BatteryTipPreferenceController.PREF_NAME)
.build();
- /**
- * Backing Uri for the Battery info Slice.
- */
- public static final Uri BATTERY_INFO_SLICE_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
- .appendPath("battery_card")
- .build();
+
/**
* Backing Uri for the Bluetooth Slice.
*/
@@ -287,4 +298,51 @@
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(MediaOutputSliceConstants.KEY_MEDIA_OUTPUT)
.build();
+
+ @VisibleForTesting
+ static final Map<Uri, Class<? extends CustomSliceable>> sUriToSlice;
+
+ static {
+ sUriToSlice = new ArrayMap<>();
+
+ sUriToSlice.put(BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
+ sUriToSlice.put(BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
+ sUriToSlice.put(CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.class);
+ sUriToSlice.put(DATA_USAGE_SLICE_URI, DataUsageSlice.class);
+ sUriToSlice.put(DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
+ sUriToSlice.put(EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class);
+ sUriToSlice.put(FLASHLIGHT_SLICE_URI, FlashlightSlice.class);
+ sUriToSlice.put(LOCATION_SLICE_URI, LocationSlice.class);
+ sUriToSlice.put(LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
+ sUriToSlice.put(MOBILE_DATA_SLICE_URI, MobileDataSlice.class);
+ sUriToSlice.put(NOTIFICATION_CHANNEL_SLICE_URI, NotificationChannelSlice.class);
+ sUriToSlice.put(STORAGE_SLICE_URI, StorageSlice.class);
+ sUriToSlice.put(WIFI_SLICE_URI, WifiSlice.class);
+ sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
+ }
+
+ public static Class<? extends CustomSliceable> getSliceClassByUri(Uri uri) {
+ return sUriToSlice.get(uri);
+ }
+
+ public static Uri removeParameterFromUri(Uri uri) {
+ return uri != null ? uri.buildUpon().clearQuery().build() : null;
+ }
+
+ /**
+ * Returns {@code true} if {@param uri} is a valid Slice Uri handled by
+ * {@link CustomSliceManager}.
+ */
+ public static boolean isValidUri(Uri uri) {
+ return sUriToSlice.containsKey(removeParameterFromUri(uri));
+ }
+
+ /**
+ * Returns {@code true} if {@param action} is a valid intent action handled by
+ * {@link CustomSliceManager}.
+ */
+ public static boolean isValidAction(String action) {
+ return isValidUri(Uri.parse(action));
+ }
+
}
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 397b2fc..d019368 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -147,7 +147,7 @@
@Override
public void onSlicePinned(Uri sliceUri) {
- if (mCustomSliceManager.isValidUri(sliceUri)) {
+ if (CustomSliceRegistry.isValidUri(sliceUri)) {
final CustomSliceable sliceable = mCustomSliceManager.getSliceableFromUri(sliceUri);
final IntentFilter filter = sliceable.getIntentFilter();
if (filter != null) {
@@ -194,7 +194,7 @@
// Before adding a slice to {@link CustomSliceManager}, please get approval
// from the Settings team.
- if (mCustomSliceManager.isValidUri(sliceUri)) {
+ if (CustomSliceRegistry.isValidUri(sliceUri)) {
final CustomSliceable sliceable = mCustomSliceManager.getSliceableFromUri(
sliceUri);
return sliceable.getSlice();
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index b2ea583..8b6fc98 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -63,7 +63,7 @@
final CustomSliceManager mCustomSliceManager = FeatureFactory.getFactory(
context).getSlicesFeatureProvider().getCustomSliceManager(context);
- if (mCustomSliceManager.isValidAction(action)) {
+ if (CustomSliceRegistry.isValidAction(action)) {
final CustomSliceable sliceable =
mCustomSliceManager.getSliceableFromIntentAction(action);
sliceable.onNotifyChange(intent);
diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
index f4afa16..d2179d2 100644
--- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
+++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
@@ -47,7 +47,7 @@
// TODO (b/80263568) Avoid duplicating this list of Slice Uris.
final CustomSliceManager customSliceManager = FeatureFactory.getFactory(this)
.getSlicesFeatureProvider().getCustomSliceManager(this);
- if (customSliceManager.isValidUri(sliceUri)) {
+ if (CustomSliceRegistry.isValidUri(sliceUri)) {
final CustomSliceable sliceable =
customSliceManager.getSliceableFromUri(sliceUri);
launchIntent = sliceable.getIntent();
diff --git a/src/com/android/settings/slices/SlicesFeatureProvider.java b/src/com/android/settings/slices/SlicesFeatureProvider.java
index 1a9fd98..16a7424 100644
--- a/src/com/android/settings/slices/SlicesFeatureProvider.java
+++ b/src/com/android/settings/slices/SlicesFeatureProvider.java
@@ -12,8 +12,6 @@
boolean DEBUG = false;
- SlicesIndexer getSliceIndexer(Context context);
-
SliceDataConverter getSliceDataConverter(Context context);
/**
diff --git a/src/com/android/settings/slices/SlicesFeatureProviderImpl.java b/src/com/android/settings/slices/SlicesFeatureProviderImpl.java
index 508eb1c..44863ec 100644
--- a/src/com/android/settings/slices/SlicesFeatureProviderImpl.java
+++ b/src/com/android/settings/slices/SlicesFeatureProviderImpl.java
@@ -32,14 +32,6 @@
private CustomSliceManager mCustomSliceManager;
@Override
- public SlicesIndexer getSliceIndexer(Context context) {
- if (mSlicesIndexer == null) {
- mSlicesIndexer = new SlicesIndexer(context.getApplicationContext());
- }
- return mSlicesIndexer;
- }
-
- @Override
public SliceDataConverter getSliceDataConverter(Context context) {
if (mSliceDataConverter == null) {
mSliceDataConverter = new SliceDataConverter(context.getApplicationContext());
@@ -76,4 +68,11 @@
public Enhanced4gLteSliceHelper getNewEnhanced4gLteSliceHelper(Context context) {
return new Enhanced4gLteSliceHelper(context);
}
+
+ private SlicesIndexer getSliceIndexer(Context context) {
+ if (mSlicesIndexer == null) {
+ mSlicesIndexer = new SlicesIndexer(context.getApplicationContext());
+ }
+ return mSlicesIndexer;
+ }
}
diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
index f77dfca..0da0f21 100644
--- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java
+++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
@@ -32,7 +32,6 @@
import android.media.MediaRouter.Callback;
import android.os.Handler;
import android.os.Looper;
-import android.text.TextUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
@@ -40,7 +39,6 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.FeatureFlags;
@@ -63,15 +61,11 @@
/**
* Abstract class for audio switcher controller to notify subclass
* updating the current status of switcher entry. Subclasses must overwrite
- * {@link #setActiveBluetoothDevice(BluetoothDevice)} to set the
- * active device for corresponding profile.
*/
public abstract class AudioSwitchPreferenceController extends BasePreferenceController
- implements Preference.OnPreferenceChangeListener, BluetoothCallback,
- LifecycleObserver, OnStart, OnStop {
+ implements BluetoothCallback, LifecycleObserver, OnStart, OnStop {
private static final String TAG = "AudioSwitchPrefCtrl";
- private static final int INVALID_INDEX = -1;
protected final List<BluetoothDevice> mConnectedDevices;
protected final AudioManager mAudioManager;
@@ -129,35 +123,6 @@
}
@Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final String address = (String) newValue;
- if (!(preference instanceof ListPreference)) {
- return false;
- }
-
- final ListPreference listPreference = (ListPreference) preference;
- if (TextUtils.equals(address, mContext.getText(R.string.media_output_default_summary))) {
- // Switch to default device which address is device name
- mSelectedIndex = getDefaultDeviceIndex();
- setActiveBluetoothDevice(null);
- listPreference.setSummary(mContext.getText(R.string.media_output_default_summary));
- } else {
- // Switch to BT device which address is hardware address
- final int connectedDeviceIndex = getConnectedDeviceIndex(address);
- if (connectedDeviceIndex == INVALID_INDEX) {
- return false;
- }
- final BluetoothDevice btDevice = mConnectedDevices.get(connectedDeviceIndex);
- mSelectedIndex = connectedDeviceIndex;
- setActiveBluetoothDevice(btDevice);
- listPreference.setSummary(btDevice.getAliasName());
- }
- return true;
- }
-
- public abstract void setActiveBluetoothDevice(BluetoothDevice device);
-
- @Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(mPreferenceKey);
@@ -185,6 +150,12 @@
}
@Override
+ public void onBluetoothStateChanged(int bluetoothState) {
+ // To handle the case that Bluetooth on and no connected devices
+ updateState(mPreference);
+ }
+
+ @Override
public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
updateState(mPreference);
}
@@ -236,21 +207,15 @@
}
/**
- * get A2dp connected device
+ * get A2dp devices on all states
+ * (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING)
*/
- protected List<BluetoothDevice> getConnectedA2dpDevices() {
- final List<BluetoothDevice> connectedDevices = new ArrayList<>();
+ protected List<BluetoothDevice> getConnectableA2dpDevices() {
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
if (a2dpProfile == null) {
- return connectedDevices;
+ return new ArrayList<>();
}
- final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
- for (BluetoothDevice device : devices) {
- if (device.isConnected()) {
- connectedDevices.add(device);
- }
- }
- return connectedDevices;
+ return a2dpProfile.getConnectableDevices();
}
/**
@@ -277,6 +242,31 @@
}
/**
+ * get hearing aid profile devices on all states
+ * (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING)
+ * exclude other devices with same hiSyncId.
+ */
+ protected List<BluetoothDevice> getConnectableHearingAidDevices() {
+ final List<BluetoothDevice> connectedDevices = new ArrayList<>();
+ final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
+ if (hapProfile == null) {
+ return connectedDevices;
+ }
+ final List<Long> devicesHiSyncIds = new ArrayList<>();
+ final List<BluetoothDevice> devices = hapProfile.getConnectableDevices();
+ for (BluetoothDevice device : devices) {
+ final long hiSyncId = hapProfile.getHiSyncId(device);
+ // device with same hiSyncId should not be shown in the UI.
+ // So do not add it into connectedDevices.
+ if (!devicesHiSyncIds.contains(hiSyncId)) {
+ devicesHiSyncIds.add(hiSyncId);
+ connectedDevices.add(device);
+ }
+ }
+ return connectedDevices;
+ }
+
+ /**
* Find active hearing aid device
*/
protected BluetoothDevice findActiveHearingAidDevice() {
@@ -306,52 +296,6 @@
*/
public abstract BluetoothDevice findActiveDevice();
- int getDefaultDeviceIndex() {
- // Default device is after all connected devices.
- return mConnectedDevices.size();
- }
-
- void setupPreferenceEntries(CharSequence[] mediaOutputs, CharSequence[] mediaValues,
- BluetoothDevice activeDevice) {
- // default to current device
- mSelectedIndex = getDefaultDeviceIndex();
- // default device is after all connected devices.
- mediaOutputs[mSelectedIndex] = mContext.getText(R.string.media_output_default_summary);
- // use default device name as address
- mediaValues[mSelectedIndex] = mContext.getText(R.string.media_output_default_summary);
- for (int i = 0, size = mConnectedDevices.size(); i < size; i++) {
- final BluetoothDevice btDevice = mConnectedDevices.get(i);
- mediaOutputs[i] = btDevice.getAliasName();
- mediaValues[i] = btDevice.getAddress();
- if (btDevice.equals(activeDevice)) {
- // select the active connected device.
- mSelectedIndex = i;
- }
- }
- }
-
- void setPreference(CharSequence[] mediaOutputs, CharSequence[] mediaValues,
- Preference preference) {
- final ListPreference listPreference = (ListPreference) preference;
- listPreference.setEntries(mediaOutputs);
- listPreference.setEntryValues(mediaValues);
- listPreference.setValueIndex(mSelectedIndex);
- listPreference.setSummary(mediaOutputs[mSelectedIndex]);
- mAudioSwitchPreferenceCallback.onPreferenceDataChanged(listPreference);
- }
-
- private int getConnectedDeviceIndex(String hardwareAddress) {
- if (mConnectedDevices != null) {
- for (int i = 0, size = mConnectedDevices.size(); i < size; i++) {
- final BluetoothDevice btDevice = mConnectedDevices.get(i);
- if (TextUtils.equals(btDevice.getAddress(), hardwareAddress)) {
- return i;
- }
- }
- }
- return INVALID_INDEX;
- }
-
private void register() {
mLocalBluetoothManager.getEventManager().registerCallback(this);
mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler);
diff --git a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
index a02c0b2..9157477 100644
--- a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
+++ b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
@@ -20,7 +20,9 @@
import android.bluetooth.BluetoothDevice;
import android.content.Context;
+import android.text.TextUtils;
+import androidx.preference.ListPreference;
import androidx.preference.Preference;
import com.android.settings.R;
@@ -32,14 +34,56 @@
* This class allows switching between HFP-connected & HAP-connected BT devices
* while in on-call state.
*/
-public class HandsFreeProfileOutputPreferenceController extends
- AudioSwitchPreferenceController {
+public class HandsFreeProfileOutputPreferenceController extends AudioSwitchPreferenceController
+ implements Preference.OnPreferenceChangeListener {
+
+ private static final int INVALID_INDEX = -1;
public HandsFreeProfileOutputPreferenceController(Context context, String key) {
super(context, key);
}
@Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final String address = (String) newValue;
+ if (!(preference instanceof ListPreference)) {
+ return false;
+ }
+
+ final CharSequence defaultSummary = mContext.getText(R.string.media_output_default_summary);
+ final ListPreference listPreference = (ListPreference) preference;
+ if (TextUtils.equals(address, defaultSummary)) {
+ // Switch to default device which address is device name
+ mSelectedIndex = getDefaultDeviceIndex();
+ setActiveBluetoothDevice(null);
+ listPreference.setSummary(defaultSummary);
+ } else {
+ // Switch to BT device which address is hardware address
+ final int connectedDeviceIndex = getConnectedDeviceIndex(address);
+ if (connectedDeviceIndex == INVALID_INDEX) {
+ return false;
+ }
+ final BluetoothDevice btDevice = mConnectedDevices.get(connectedDeviceIndex);
+ mSelectedIndex = connectedDeviceIndex;
+ setActiveBluetoothDevice(btDevice);
+ listPreference.setSummary(btDevice.getAliasName());
+ }
+ return true;
+ }
+
+ private int getConnectedDeviceIndex(String hardwareAddress) {
+ if (mConnectedDevices != null) {
+ for (int i = 0, size = mConnectedDevices.size(); i < size; i++) {
+ final BluetoothDevice btDevice = mConnectedDevices.get(i);
+ if (TextUtils.equals(btDevice.getAddress(), hardwareAddress)) {
+ return i;
+ }
+ }
+ }
+ return INVALID_INDEX;
+ }
+
+ @Override
public void updateState(Preference preference) {
if (preference == null) {
// In case UI is not ready.
@@ -83,7 +127,41 @@
setPreference(mediaOutputs, mediaValues, preference);
}
- @Override
+ int getDefaultDeviceIndex() {
+ // Default device is after all connected devices.
+ return mConnectedDevices.size();
+ }
+
+ void setupPreferenceEntries(CharSequence[] mediaOutputs, CharSequence[] mediaValues,
+ BluetoothDevice activeDevice) {
+ // default to current device
+ mSelectedIndex = getDefaultDeviceIndex();
+ // default device is after all connected devices.
+ final CharSequence defaultSummary = mContext.getText(R.string.media_output_default_summary);
+ mediaOutputs[mSelectedIndex] = defaultSummary;
+ // use default device name as address
+ mediaValues[mSelectedIndex] = defaultSummary;
+ for (int i = 0, size = mConnectedDevices.size(); i < size; i++) {
+ final BluetoothDevice btDevice = mConnectedDevices.get(i);
+ mediaOutputs[i] = btDevice.getAliasName();
+ mediaValues[i] = btDevice.getAddress();
+ if (btDevice.equals(activeDevice)) {
+ // select the active connected device.
+ mSelectedIndex = i;
+ }
+ }
+ }
+
+ void setPreference(CharSequence[] mediaOutputs, CharSequence[] mediaValues,
+ Preference preference) {
+ final ListPreference listPreference = (ListPreference) preference;
+ listPreference.setEntries(mediaOutputs);
+ listPreference.setEntryValues(mediaValues);
+ listPreference.setValueIndex(mSelectedIndex);
+ listPreference.setSummary(mediaOutputs[mSelectedIndex]);
+ mAudioSwitchPreferenceCallback.onPreferenceDataChanged(listPreference);
+ }
+
public void setActiveBluetoothDevice(BluetoothDevice device) {
if (!Utils.isAudioModeOngoingCall(mContext)) {
return;
diff --git a/src/com/android/settings/sound/MediaOutputPreferenceController.java b/src/com/android/settings/sound/MediaOutputPreferenceController.java
index ce476ad..47810f7 100644
--- a/src/com/android/settings/sound/MediaOutputPreferenceController.java
+++ b/src/com/android/settings/sound/MediaOutputPreferenceController.java
@@ -16,13 +16,14 @@
package com.android.settings.sound;
-import static android.bluetooth.IBluetoothHearingAid.HI_SYNC_ID_INVALID;
import static android.media.AudioManager.STREAM_MUSIC;
import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
+import android.content.Intent;
import android.media.AudioManager;
+import android.text.TextUtils;
import androidx.preference.Preference;
@@ -30,12 +31,16 @@
import com.android.settingslib.Utils;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.media.MediaOutputSliceConstants;
+
+import java.util.List;
/**
- * This class which allows switching between A2dp-connected & HAP-connected BT devices.
- * A few conditions will disable this switcher:
- * - No available BT device(s)
- * - Media stream captured by cast device
+ * This class allows launching MediaOutputSlice to switch output device.
+ * Preference would hide only when
+ * - Bluetooth = OFF
+ * - Bluetooth = ON and Connected Devices = 0 and Previously Connected = 0
+ * - Media stream captured by remote device
* - During a call.
*/
public class MediaOutputPreferenceController extends AudioSwitchPreferenceController {
@@ -66,40 +71,22 @@
return;
}
- mConnectedDevices.clear();
- // Otherwise, list all of the A2DP connected device and display the active device.
- if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) {
- mConnectedDevices.addAll(getConnectedA2dpDevices());
- mConnectedDevices.addAll(getConnectedHearingAidDevices());
+ boolean deviceConnectable = false;
+ BluetoothDevice activeDevice = null;
+ // Show preference if there is connected or previously connected device
+ // Find active device and set its name as the preference's summary
+ List<BluetoothDevice> connectableA2dpDevices = getConnectableA2dpDevices();
+ List<BluetoothDevice> connectableHADevices = getConnectableHearingAidDevices();
+ if (mAudioManager.getMode() == AudioManager.MODE_NORMAL
+ && ((connectableA2dpDevices != null && !connectableA2dpDevices.isEmpty())
+ || (connectableHADevices != null && !connectableHADevices.isEmpty()))) {
+ deviceConnectable = true;
+ activeDevice = findActiveDevice();
}
-
- final int numDevices = mConnectedDevices.size();
- mPreference.setVisible((numDevices == 0) ? false : true);
- CharSequence[] mediaOutputs = new CharSequence[numDevices + 1];
- CharSequence[] mediaValues = new CharSequence[numDevices + 1];
-
- // Setup devices entries, select active connected device
- setupPreferenceEntries(mediaOutputs, mediaValues, findActiveDevice());
-
- // Display connected devices, default device and show the active device
- setPreference(mediaOutputs, mediaValues, preference);
- }
-
- @Override
- public void setActiveBluetoothDevice(BluetoothDevice device) {
- if (mAudioManager.getMode() != AudioManager.MODE_NORMAL) {
- return;
- }
- final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
- final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
- if (hapProfile != null && a2dpProfile != null && device == null) {
- hapProfile.setActiveDevice(null);
- a2dpProfile.setActiveDevice(null);
- } else if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) {
- hapProfile.setActiveDevice(device);
- } else if (a2dpProfile != null) {
- a2dpProfile.setActiveDevice(device);
- }
+ mPreference.setVisible(deviceConnectable);
+ mPreference.setSummary((activeDevice == null) ?
+ mContext.getText(R.string.media_output_default_summary) :
+ activeDevice.getAliasName());
}
@Override
@@ -112,4 +99,34 @@
}
return activeDevice;
}
+
+ /**
+ * Find active hearing aid device
+ */
+ @Override
+ protected BluetoothDevice findActiveHearingAidDevice() {
+ final HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile();
+
+ if (hearingAidProfile != null) {
+ List<BluetoothDevice> activeDevices = hearingAidProfile.getActiveDevices();
+ for (BluetoothDevice btDevice : activeDevices) {
+ if (btDevice != null) {
+ return btDevice;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+ final Intent intent = new Intent()
+ .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ return true;
+ }
+ return false;
+ }
}
diff --git a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
index c097d41..f931fa4 100644
--- a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
+++ b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
@@ -38,9 +38,13 @@
mUserCaps.updateAddUserCapabilities(mContext);
final RestrictedSwitchPreference restrictedSwitchPreference =
(RestrictedSwitchPreference) preference;
- restrictedSwitchPreference.setDisabledByAdmin(
- mUserCaps.disallowAddUser() ? mUserCaps.getEnforcedAdmin() : null);
- restrictedSwitchPreference.setVisible(mUserCaps.mUserSwitcherEnabled);
+ if (!isAvailable()) {
+ restrictedSwitchPreference.setVisible(false);
+ } else {
+ restrictedSwitchPreference.setDisabledByAdmin(
+ mUserCaps.disallowAddUser() ? mUserCaps.getEnforcedAdmin() : null);
+ restrictedSwitchPreference.setVisible(mUserCaps.mUserSwitcherEnabled);
+ }
}
@Override
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 5a83f34..98263e2 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -289,10 +289,8 @@
}
final PreferenceScreen screen = getPreferenceScreen();
- if (mAddUserWhenLockedPreferenceController.isAvailable()) {
- mAddUserWhenLockedPreferenceController.updateState(screen.findPreference(
- mAddUserWhenLockedPreferenceController.getPreferenceKey()));
- }
+ mAddUserWhenLockedPreferenceController.updateState(screen.findPreference(
+ mAddUserWhenLockedPreferenceController.getPreferenceKey()));
if (mShouldUpdateUserList) {
updateUI();
diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java
index de2755e..07e957d 100644
--- a/src/com/android/settings/vpn2/ConfigDialog.java
+++ b/src/com/android/settings/vpn2/ConfigDialog.java
@@ -18,6 +18,8 @@
import android.content.Context;
import android.content.DialogInterface;
+import android.net.Proxy;
+import android.net.ProxyInfo;
import android.os.Bundle;
import android.os.SystemProperties;
import android.security.Credentials;
@@ -67,6 +69,9 @@
private TextView mSearchDomains;
private TextView mDnsServers;
private TextView mRoutes;
+ private Spinner mProxySettings;
+ private TextView mProxyHost;
+ private TextView mProxyPort;
private CheckBox mMppe;
private TextView mL2tpSecret;
private TextView mIpsecIdentifier;
@@ -105,6 +110,9 @@
mSearchDomains = (TextView) mView.findViewById(R.id.search_domains);
mDnsServers = (TextView) mView.findViewById(R.id.dns_servers);
mRoutes = (TextView) mView.findViewById(R.id.routes);
+ mProxySettings = (Spinner) mView.findViewById(R.id.vpn_proxy_settings);
+ mProxyHost = (TextView) mView.findViewById(R.id.vpn_proxy_host);
+ mProxyPort = (TextView) mView.findViewById(R.id.vpn_proxy_port);
mMppe = (CheckBox) mView.findViewById(R.id.mppe);
mL2tpSecret = (TextView) mView.findViewById(R.id.l2tp_secret);
mIpsecIdentifier = (TextView) mView.findViewById(R.id.ipsec_identifier);
@@ -128,6 +136,11 @@
mSearchDomains.setText(mProfile.searchDomains);
mDnsServers.setText(mProfile.dnsServers);
mRoutes.setText(mProfile.routes);
+ if (mProfile.proxy != null) {
+ mProxyHost.setText(mProfile.proxy.getHost());
+ int port = mProfile.proxy.getPort();
+ mProxyPort.setText(port == 0 ? "" : Integer.toString(port));
+ }
mMppe.setChecked(mProfile.mppe);
mL2tpSecret.setText(mProfile.l2tpSecret);
mIpsecIdentifier.setText(mProfile.ipsecIdentifier);
@@ -153,6 +166,9 @@
mPassword.addTextChangedListener(this);
mDnsServers.addTextChangedListener(this);
mRoutes.addTextChangedListener(this);
+ mProxySettings.setOnItemSelectedListener(this);
+ mProxyHost.addTextChangedListener(this);
+ mProxyPort.addTextChangedListener(this);
mIpsecSecret.addTextChangedListener(this);
mIpsecUserCert.setOnItemSelectedListener(this);
mShowOptions.setOnClickListener(this);
@@ -175,7 +191,8 @@
// Switch to advanced view immediately if any advanced options are on
if (!mProfile.searchDomains.isEmpty() || !mProfile.dnsServers.isEmpty() ||
- !mProfile.routes.isEmpty()) {
+ !mProfile.routes.isEmpty() || (mProfile.proxy != null &&
+ (!mProfile.proxy.getHost().isEmpty() || mProfile.proxy.getPort() != 0))) {
showAdvancedOptions();
}
@@ -246,6 +263,8 @@
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (parent == mType) {
changeType(position);
+ } else if (parent == mProxySettings) {
+ updateProxyFieldsVisibility(position);
}
updateUiControls();
}
@@ -271,6 +290,7 @@
* These include:
* "Always-on VPN" checkbox
* Reason for "Always-on VPN" being disabled, when necessary
+ * Proxy info if manually configured
* "Save account information" checkbox
* "Save" and "Connect" buttons
*/
@@ -298,6 +318,13 @@
mAlwaysOnInvalidReason.setVisibility(View.VISIBLE);
}
+ // Show proxy fields if any proxy field is filled.
+ if (mProfile.proxy != null && (!mProfile.proxy.getHost().isEmpty() ||
+ mProfile.proxy.getPort() != 0)) {
+ mProxySettings.setSelection(VpnProfile.PROXY_MANUAL);
+ updateProxyFieldsVisibility(VpnProfile.PROXY_MANUAL);
+ }
+
// Save account information
if (mAlwaysOnVpn.isChecked()) {
mSaveLogin.setChecked(true);
@@ -311,6 +338,11 @@
getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(validate(mEditing));
}
+ private void updateProxyFieldsVisibility(int position) {
+ final int visible = position == VpnProfile.PROXY_MANUAL ? View.VISIBLE : View.GONE;
+ mView.findViewById(R.id.vpn_proxy_fields).setVisibility(visible);
+ }
+
private void showAdvancedOptions() {
mView.findViewById(R.id.options).setVisibility(View.VISIBLE);
mShowOptions.setVisibility(View.GONE);
@@ -361,6 +393,11 @@
!validateAddresses(mRoutes.getText().toString(), true)) {
return false;
}
+
+ if (!validateProxy()) {
+ return false;
+ }
+
switch (mType.getSelectedItemPosition()) {
case VpnProfile.TYPE_PPTP:
case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
@@ -435,6 +472,10 @@
return mEditing;
}
+ boolean hasProxy() {
+ return mProxySettings.getSelectedItemPosition() == VpnProfile.PROXY_MANUAL;
+ }
+
VpnProfile getProfile() {
// First, save common fields.
VpnProfile profile = new VpnProfile(mProfile.key);
@@ -446,7 +487,16 @@
profile.searchDomains = mSearchDomains.getText().toString().trim();
profile.dnsServers = mDnsServers.getText().toString().trim();
profile.routes = mRoutes.getText().toString().trim();
-
+ if (hasProxy()) {
+ String proxyHost = mProxyHost.getText().toString().trim();
+ String proxyPort = mProxyPort.getText().toString().trim();
+ // 0 is a last resort default, but the interface validates that the proxy port is
+ // present and non-zero.
+ int port = proxyPort.isEmpty() ? 0 : Integer.parseInt(proxyPort);
+ profile.proxy = new ProxyInfo(proxyHost, port, null);
+ } else {
+ profile.proxy = null;
+ }
// Then, save type-specific fields.
switch (profile.type) {
case VpnProfile.TYPE_PPTP:
@@ -483,4 +533,15 @@
profile.saveLogin = mSaveLogin.isChecked() || (mEditing && hasLogin);
return profile;
}
+
+ private boolean validateProxy() {
+ if (!hasProxy()) {
+ return true;
+ }
+
+ final String host = mProxyHost.getText().toString().trim();
+ final String port = mProxyPort.getText().toString().trim();
+ return Proxy.validate(host, port, "") == Proxy.PROXY_VALID;
+ }
+
}
diff --git a/src/com/android/settings/widget/SingleTargetGearPreference.java b/src/com/android/settings/widget/SingleTargetGearPreference.java
index 48876fa..f6496ed 100644
--- a/src/com/android/settings/widget/SingleTargetGearPreference.java
+++ b/src/com/android/settings/widget/SingleTargetGearPreference.java
@@ -18,9 +18,10 @@
import android.content.Context;
import android.util.AttributeSet;
+import android.view.View;
-import androidx.core.content.res.TypedArrayUtils;
import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
@@ -28,23 +29,38 @@
* A preference with single target and a gear icon on the side.
*/
public class SingleTargetGearPreference extends Preference {
-
- public SingleTargetGearPreference(Context context, AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
+ public SingleTargetGearPreference(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- setWidgetLayoutResource(R.layout.preference_widget_gear_no_bg);
+ init();
}
public SingleTargetGearPreference(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0 /* defStyleRes */);
+ super(context, attrs, defStyleAttr);
+ init();
}
public SingleTargetGearPreference(Context context, AttributeSet attrs) {
- this(context, attrs, TypedArrayUtils.getAttr(context, R.attr.preferenceStyle,
- android.R.attr.preferenceStyle));
+ super(context, attrs);
+ init();
}
public SingleTargetGearPreference(Context context) {
- this(context, null /* attrs */);
+ super(context);
+ init();
}
-}
\ No newline at end of file
+
+ private void init() {
+ setLayoutResource(R.layout.preference_single_target);
+ setWidgetLayoutResource(R.layout.preference_widget_gear_optional_background);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ final View divider = holder.findViewById(com.android.settingslib.R.id.two_target_divider);
+ if (divider != null) {
+ divider.setVisibility(View.INVISIBLE);
+ }
+ }
+}
diff --git a/src/com/android/settings/wifi/ButtonPreference.java b/src/com/android/settings/wifi/ButtonPreference.java
index 9a0abf6..5169d7a 100644
--- a/src/com/android/settings/wifi/ButtonPreference.java
+++ b/src/com/android/settings/wifi/ButtonPreference.java
@@ -49,6 +49,7 @@
private ImageButton mImageButton;
private Drawable mButtonIcon;
private View.OnClickListener mClickListener;
+ private String mContentDescription;
// Used for dummy pref.
public ButtonPreference(Context context, AttributeSet attrs) {
@@ -57,6 +58,7 @@
mImageButton = null;
mButtonIcon = null;
mClickListener = null;
+ mContentDescription = null;
}
public ButtonPreference(Context context) {
@@ -83,6 +85,7 @@
if (mImageButton != null) {
mImageButton.setImageDrawable(mButtonIcon);
mImageButton.setOnClickListener(mClickListener);
+ mImageButton.setContentDescription(mContentDescription);
}
setButtonVisibility();
}
@@ -96,9 +99,9 @@
/**
* Sets the drawable to be displayed in button.
*/
- public ButtonPreference setButtonIcon(@DrawableRes int iconResId) {
+ public void setButtonIcon(@DrawableRes int iconResId) {
if (iconResId == 0) {
- return this;
+ return;
}
try {
@@ -107,17 +110,26 @@
} catch (Resources.NotFoundException exception) {
Log.e(TAG, "Resource does not exist: " + iconResId);
}
- return this;
}
/**
* Register a callback to be invoked when button is clicked.
*/
- public ButtonPreference setButtonOnClickListener(View.OnClickListener listener) {
+ public void setButtonOnClickListener(View.OnClickListener listener) {
if (listener != mClickListener) {
mClickListener = listener;
notifyChanged();
}
- return this;
+ }
+
+ /**
+ * A content description briefly describes the button and is primarily used for accessibility
+ * support to determine how a button should be presented to the user.
+ */
+ public void setButtonContentDescription(String contentDescription) {
+ if (contentDescription != mContentDescription) {
+ mContentDescription = contentDescription;
+ notifyChanged();
+ }
}
}
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index e7db5db..0adbd8d 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -248,8 +248,8 @@
mMeteredSettingsSpinner = mView.findViewById(R.id.metered_settings);
mHiddenSettingsSpinner = mView.findViewById(R.id.hidden_settings);
mPrivacySettingsSpinner = mView.findViewById(R.id.privacy_settings);
- if (FeatureFlagUtils.isEnabled(mContext,
- com.android.settings.core.FeatureFlags.WIFI_MAC_RANDOMIZATION)) {
+ if (mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) {
View privacySettingsLayout = mView.findViewById(R.id.privacy_settings_fields);
privacySettingsLayout.setVisibility(View.VISIBLE);
}
@@ -265,11 +265,7 @@
configureSecuritySpinner();
mConfigUi.setSubmitButton(res.getString(R.string.wifi_save));
} else {
- if (!mAccessPoint.isPasspointConfig()) {
- mConfigUi.setTitle(mAccessPoint.getSsid());
- } else {
- mConfigUi.setTitle(mAccessPoint.getConfigName());
- }
+ mConfigUi.setTitle(mAccessPoint.getTitle());
ViewGroup group = (ViewGroup) mView.findViewById(R.id.info);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index c00fe24..a8fc34d 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -67,6 +67,7 @@
import com.android.settings.widget.SwitchBarController;
import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
import com.android.settings.wifi.dpp.WifiDppUtils;
+import com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.search.SearchIndexable;
@@ -247,6 +248,7 @@
getContext().startActivity(
WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null));
});
+ mAddPreference.setButtonContentDescription(getString(R.string.wifi_dpp_scan_qr_code));
mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE);
mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
@@ -483,7 +485,7 @@
if (preference instanceof LongPressAccessPointPreference) {
mSelectedAccessPoint =
((LongPressAccessPointPreference) preference).getAccessPoint();
- menu.setHeaderTitle(mSelectedAccessPoint.getSsid());
+ menu.setHeaderTitle(mSelectedAccessPoint.getTitle());
if (mSelectedAccessPoint.isConnectable()) {
menu.add(Menu.NONE, MENU_ID_CONNECT, 0, R.string.wifi_menu_connect);
}
@@ -967,8 +969,13 @@
}
private void launchNetworkDetailsFragment(ConnectedAccessPointPreference pref) {
+ final AccessPoint accessPoint = pref.getAccessPoint();
+ final Context context = getContext();
+ final CharSequence title = SavedAccessPointsWifiSettings.usingDetailsFragment(context) ?
+ accessPoint.getTitle() : context.getText(R.string.pref_title_network_details);
+
new SubSettingLauncher(getContext())
- .setTitleRes(R.string.pref_title_network_details)
+ .setTitleText(title)
.setDestination(WifiNetworkDetailsFragment.class.getName())
.setArguments(pref.getExtras())
.setSourceMetricsCategory(getMetricsCategory())
diff --git a/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreference.java b/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreference.java
new file mode 100644
index 0000000..a44fcbe
--- /dev/null
+++ b/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreference.java
@@ -0,0 +1,203 @@
+/*
+ * 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.wifi.calling;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
+import android.widget.RadioButton;
+import android.widget.TextView;
+import androidx.appcompat.app.AlertDialog.Builder;
+import com.android.settings.CustomListPreference;
+import com.android.settings.R;
+
+/**
+ * ListPreference contain the entry summary.
+ */
+public class ListWithEntrySummaryPreference extends CustomListPreference {
+ private static final String LOG_TAG = "ListWithEntrySummaryPreference";
+ private final Context mContext;
+ private CharSequence[] mSummaries;
+
+ /**
+ * ListWithEntrySummaryPreference constructor.
+ *
+ * @param context The context of view.
+ * @param attrs The attributes of the XML tag that is inflating the linear layout.
+ */
+ public ListWithEntrySummaryPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+
+ TypedArray array = context.obtainStyledAttributes(attrs,
+ R.styleable.ListWithEntrySummaryPreference, 0, 0);
+ mSummaries = array.getTextArray(R.styleable.ListWithEntrySummaryPreference_entrySummaries);
+ array.recycle();
+ }
+
+ /**
+ * Sets the summaries of mode items to be shown in the mode select dialog.
+ *
+ * @param summariesResId The summaries of mode items.
+ */
+ public void setEntrySummaries(int summariesResId) {
+ mSummaries = getContext().getResources().getTextArray(summariesResId);
+ }
+
+ /**
+ * Sets the summaries of mode items to be shown in the mode select dialog.
+ *
+ * @param summaries The summaries of mode items.
+ */
+ public void setEntrySummaries(CharSequence[] summaries) {
+ mSummaries = summaries;
+ }
+
+ private CharSequence getEntrySummary(int index) {
+ if (mSummaries == null) {
+ Log.w(LOG_TAG, "getEntrySummary : mSummaries is null");
+ return "";
+ }
+ return mSummaries[index];
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(Builder builder,
+ DialogInterface.OnClickListener listener) {
+ ListAdapter la = (ListAdapter) new SelectorAdapter(mContext,
+ R.xml.single_choice_list_item_2, this);
+ builder.setSingleChoiceItems(la, findIndexOfValue(getValue()), listener);
+ super.onPrepareDialogBuilder(builder, listener);
+ }
+
+ private static class SelectorAdapter extends ArrayAdapter<CharSequence> {
+ private final Context mContext;
+ private ListWithEntrySummaryPreference mSelector;
+
+ /**
+ * SelectorAdapter constructor.
+ *
+ * @param context The current context.
+ * @param rowResourceId The resource id of the XML tag that is inflating the linear layout.
+ * @param listPreference The instance of ListWithEntrySummaryPreference.
+ */
+ public SelectorAdapter(Context context, int rowResourceId,
+ ListWithEntrySummaryPreference listPreference) {
+ super(context, rowResourceId, listPreference.getEntryValues());
+ mContext = context;
+ mSelector = listPreference;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ View row = inflater.inflate(R.xml.single_choice_list_item_2, parent, false);
+
+ TextView title = (TextView) row.findViewById(R.id.title);
+ title.setText(mSelector.getEntries()[position]);
+
+ TextView summary = (TextView) row.findViewById(R.id.summary);
+ summary.setText(mSelector.getEntrySummary(position));
+
+ RadioButton rb = (RadioButton) row.findViewById(R.id.radio);
+ if (position == mSelector.findIndexOfValue(mSelector.getValue())) {
+ rb.setChecked(true);
+ }
+
+ return row;
+ }
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+
+ final SavedState myState = new SavedState(superState);
+ myState.mEntries = getEntries();
+ myState.mEntryValues = getEntryValues();
+ myState.mSummaries = mSummaries;
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state == null || !state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ setEntries(myState.mEntries);
+ setEntryValues(myState.mEntryValues);
+ mSummaries = myState.mSummaries;
+ }
+
+ /**
+ * We save entries, entryValues and summaries into bundle.
+ * At onCreate of fragment, dialog will be restored if it was open. In this case,
+ * we need to restore entries, entryValues and summaries. Without those information,
+ * crash when entering multi window during wfc modes dialog shown.
+ */
+ private static class SavedState extends BaseSavedState {
+ private CharSequence[] mEntries;
+ private CharSequence[] mEntryValues;
+ private CharSequence[] mSummaries;
+
+ public SavedState(Parcel source) {
+ super(source);
+ mEntries = source.readCharSequenceArray();
+ mEntryValues = source.readCharSequenceArray();
+ mSummaries = source.readCharSequenceArray();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeCharSequenceArray(mEntries);
+ dest.writeCharSequenceArray(mEntryValues);
+ dest.writeCharSequenceArray(mSummaries);
+ }
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ @Override
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ @Override
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+}
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
index 6fe1795..625de38 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
@@ -40,7 +40,6 @@
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
-import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceScreen;
@@ -82,8 +81,8 @@
//UI objects
private SwitchBar mSwitchBar;
private Switch mSwitch;
- private ListPreference mButtonWfcMode;
- private ListPreference mButtonWfcRoamingMode;
+ private ListWithEntrySummaryPreference mButtonWfcMode;
+ private ListWithEntrySummaryPreference mButtonWfcRoamingMode;
private Preference mUpdateAddress;
private TextView mEmptyView;
@@ -141,20 +140,17 @@
}
};
+ /*
+ * Launch carrier emergency address managemnent activity
+ */
private final OnPreferenceClickListener mUpdateAddressListener =
- new OnPreferenceClickListener() {
- /*
- * Launch carrier emergency address managemnent activity
- */
- @Override
- public boolean onPreferenceClick(Preference preference) {
- Intent carrierAppIntent = getCarrierActivityIntent();
- if (carrierAppIntent != null) {
- carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_UPDATE);
- startActivity(carrierAppIntent);
- }
- return true;
+ preference -> {
+ Intent carrierAppIntent = getCarrierActivityIntent();
+ if (carrierAppIntent != null) {
+ carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_UPDATE);
+ startActivity(carrierAppIntent);
}
+ return true;
};
private final ProvisioningManager.Callback mProvisioningCallback =
@@ -174,8 +170,6 @@
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- final SettingsActivity activity = (SettingsActivity) getActivity();
-
mEmptyView = getView().findViewById(android.R.id.empty);
setEmptyView(mEmptyView);
final Resources res = SubscriptionManager.getResourcesForSubId(getContext(), mSubId);
@@ -265,13 +259,13 @@
mTelephonyManager = ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE))
.createForSubscriptionId(mSubId);
- mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE);
+ mButtonWfcMode = findPreference(BUTTON_WFC_MODE);
mButtonWfcMode.setOnPreferenceChangeListener(this);
- mButtonWfcRoamingMode = (ListPreference) findPreference(BUTTON_WFC_ROAMING_MODE);
+ mButtonWfcRoamingMode = findPreference(BUTTON_WFC_ROAMING_MODE);
mButtonWfcRoamingMode.setOnPreferenceChangeListener(this);
- mUpdateAddress = (Preference) findPreference(PREFERENCE_EMERGENCY_ADDRESS);
+ mUpdateAddress = findPreference(PREFERENCE_EMERGENCY_ADDRESS);
mUpdateAddress.setOnPreferenceClickListener(mUpdateAddressListener);
mIntentFilter = new IntentFilter();
@@ -329,10 +323,14 @@
if (!isWifiOnlySupported) {
mButtonWfcMode.setEntries(R.array.wifi_calling_mode_choices_without_wifi_only);
mButtonWfcMode.setEntryValues(R.array.wifi_calling_mode_values_without_wifi_only);
+ mButtonWfcMode.setEntrySummaries(R.array.wifi_calling_mode_summaries_without_wifi_only);
+
mButtonWfcRoamingMode.setEntries(
R.array.wifi_calling_mode_choices_v2_without_wifi_only);
mButtonWfcRoamingMode.setEntryValues(
R.array.wifi_calling_mode_values_without_wifi_only);
+ mButtonWfcRoamingMode.setEntrySummaries(
+ R.array.wifi_calling_mode_summaries_without_wifi_only);
}
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 01673e3..89565df 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -21,16 +21,12 @@
import android.app.Activity;
import android.app.AlertDialog;
-import android.app.KeyguardManager;
import android.app.settings.SettingsEnums;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
-import android.hardware.biometrics.BiometricPrompt;
-import android.os.CancellationSignal;
-import android.os.Looper;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.LinkAddress;
@@ -46,6 +42,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;
@@ -55,12 +52,14 @@
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
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.datausage.WifiDataUsageSummaryPreferenceController;
import com.android.settings.development.featureflags.FeatureFlagPersistent;
import com.android.settings.widget.EntityHeaderController;
import com.android.settings.wifi.WifiDialog;
@@ -154,6 +153,9 @@
private Preference mDnsPref;
private PreferenceCategory mIpv6Category;
private Preference mIpv6AddressPref;
+ private Lifecycle mLifecycle;
+ Preference mDataUsageSummaryPref;
+ WifiDataUsageSummaryPreferenceController mSummaryHeaderController;
private final IconInjector mIconInjector;
private final IntentFilter mFilter;
@@ -266,6 +268,7 @@
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
+ mLifecycle = lifecycle;
lifecycle.addObserver(this);
}
@@ -317,6 +320,17 @@
private void setupEntityHeader(PreferenceScreen screen) {
LayoutPreference headerPref = screen.findPreference(KEY_HEADER);
+
+ if (usingDataUsageHeader(mContext)) {
+ headerPref.setVisible(false);
+ mDataUsageSummaryPref = screen.findPreference("status_header");
+ mDataUsageSummaryPref.setVisible(true);
+ mSummaryHeaderController =
+ new WifiDataUsageSummaryPreferenceController(mFragment.getActivity(),
+ mLifecycle, (PreferenceFragmentCompat) mFragment, mAccessPoint.getSsid());
+ return;
+ }
+
mEntityHeaderController =
EntityHeaderController.newInstance(
mFragment.getActivity(), mFragment,
@@ -327,7 +341,16 @@
mContext.getDrawable(R.drawable.ic_settings_widget_background));
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
- mEntityHeaderController.setLabel(mAccessPoint.getSsidStr());
+ mEntityHeaderController.setLabel(mAccessPoint.getTitle());
+ }
+
+ private void refreshEntityHeader() {
+ if (usingDataUsageHeader(mContext)) {
+ mSummaryHeaderController.updateState(mDataUsageSummaryPref);
+ } else {
+ mEntityHeaderController.setSummary(mAccessPoint.getSettingsSummary())
+ .done(mFragment.getActivity(), true /* rebind */);
+ }
}
@Override
@@ -364,9 +387,7 @@
// MAC Address Pref
mMacAddressPref.setSummary(mWifiConfig.getRandomizedMacAddress().toString());
- // TODO(b/124700353): Change header to data usage chart
- mEntityHeaderController.setSummary(mAccessPoint.getSettingsSummary())
- .done(mFragment.getActivity(), true /* rebind */);
+ refreshEntityHeader();
updateIpLayerInfo();
@@ -433,8 +454,7 @@
private void refreshNetworkState() {
mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
- mEntityHeaderController.setSummary(mAccessPoint.getSettingsSummary())
- .done(mFragment.getActivity(), true /* rebind */);
+ refreshEntityHeader();
}
private void refreshRssiViews() {
@@ -447,7 +467,10 @@
Drawable wifiIcon = mIconInjector.getIcon(mRssiSignalLevel);
wifiIcon.setTintList(Utils.getColorAccent(mContext));
- mEntityHeaderController.setIcon(wifiIcon).done(mFragment.getActivity(), true /* rebind */);
+ if (mEntityHeaderController != null) {
+ mEntityHeaderController.setIcon(wifiIcon).done(mFragment.getActivity(),
+ true /* rebind */);
+ }
Drawable wifiIconDark = wifiIcon.getConstantState().newDrawable().mutate();
wifiIconDark.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal));
@@ -619,48 +642,16 @@
* 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 title = mContext.getString(
- R.string.lockpassword_confirm_your_pattern_header);
- final String description = String.format(
- mContext.getString(R.string.wifi_sharing_message),
- mAccessPoint.getSsidStr());
+ final String title = mContext.getString(
+ R.string.lockpassword_confirm_your_pattern_header);
+ final String description = String.format(
+ mContext.getString(R.string.wifi_sharing_message),
+ mAccessPoint.getSsidStr());
- final BiometricPrompt.Builder builder = new BiometricPrompt.Builder(mContext)
- .setTitle(title)
- .setDescription(description);
-
- if (keyguardManager.isDeviceSecure()) {
- builder.setDeviceCredentialAllowed(true);
- }
-
- final BiometricPrompt bp = builder.build();
- final Handler handler = new Handler(Looper.getMainLooper());
- bp.authenticate(new CancellationSignal(),
- runnable -> handler.post(runnable),
- mAuthenticationCallback);
- } else {
- launchWifiDppConfiguratorActivity();
- }
+ WifiDppUtils.showLockScreen(mContext, title, description,
+ () -> launchWifiDppConfiguratorActivity());
}
- private BiometricPrompt.AuthenticationCallback mAuthenticationCallback =
- new BiometricPrompt.AuthenticationCallback() {
- @Override
- public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
- launchWifiDppConfiguratorActivity();
- }
-
- @Override
- public void onAuthenticationError(int errorCode, CharSequence errString) {
- //Do nothing
- }
- };
-
/**
* Sign in to the captive portal found on this wifi network associated with this preference.
*/
@@ -706,4 +697,8 @@
return mContext.getDrawable(Utils.getWifiIconResource(level)).mutate();
}
}
+
+ private boolean usingDataUsageHeader(Context context) {
+ return FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_DATAUSAGE_HEADER);
+ }
}
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index fd2e14a..7edd227 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -153,11 +153,11 @@
controllers.add(mWifiDetailPreferenceController);
controllers.add(new WifiMeteredPreferenceController(context, mAccessPoint.getConfig()));
- WifiPrivacyPreferenceController preferenceController = new WifiPrivacyPreferenceController(
+ WifiPrivacyPreferenceController privacyController = new WifiPrivacyPreferenceController(
context);
- preferenceController.setWifiConfiguration(mAccessPoint.getConfig());
- preferenceController.setIsEphemeral(mAccessPoint.isEphemeral());
- controllers.add(preferenceController);
+ privacyController.setWifiConfiguration(mAccessPoint.getConfig());
+ privacyController.setIsEphemeral(mAccessPoint.isEphemeral());
+ controllers.add(privacyController);
return controllers;
}
diff --git a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
index b79f2d4..a549e21 100644
--- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
@@ -58,8 +58,9 @@
@Override
public int getAvailabilityStatus() {
- return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.WIFI_MAC_RANDOMIZATION)
- ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported) ?
+ AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
index 9e731ba..3a9308e 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
@@ -29,6 +29,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
@@ -99,6 +100,7 @@
if (!isConfigurationChange) {
mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_SUCCESS;
+ changeFocusAndAnnounceChange(mButtonRight, mTitle);
}
}
@@ -168,15 +170,17 @@
mButtonLeft.setVisibility(View.INVISIBLE);
}
- if (!isConfigurationChange) {
- mLatestStatusCode = code;
- }
-
if (isGoingInitiator()) {
mSummary.setText(R.string.wifi_dpp_sharing_wifi_with_this_device);
}
+
mProgressBar.setVisibility(isGoingInitiator() ? View.VISIBLE : View.INVISIBLE);
mButtonRight.setVisibility(isGoingInitiator() ? View.INVISIBLE : View.VISIBLE);
+
+ if (!isConfigurationChange) {
+ mLatestStatusCode = code;
+ changeFocusAndAnnounceChange(mButtonRight, mSummary);
+ }
}
private boolean hasRetryButton(int code) {
@@ -277,6 +281,7 @@
mButtonRight.setVisibility(View.INVISIBLE);
startWifiDppConfiguratorInitiator();
updateSummary();
+ mTitleSummaryContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
});
if (savedInstanceState != null) {
@@ -288,6 +293,8 @@
} else {
showErrorUi(mLatestStatusCode, /* isConfigurationChange */ true);
}
+ } else {
+ changeFocusAndAnnounceChange(mButtonRight, mTitleSummaryContainer);
}
}
@@ -354,4 +361,17 @@
mSummary.setText(getString(R.string.wifi_dpp_add_device_to_wifi, getSsid()));
}
}
+
+ /**
+ * This fragment will change UI display and text messages for events. To improve Talkback user
+ * experienience, using this method to focus on a right component and announce a changed text
+ * after an UI changing event.
+ *
+ * @param focusView The UI component which will be focused
+ * @param announceView The UI component's text will be talked
+ */
+ private void changeFocusAndAnnounceChange(View focusView, View announceView) {
+ focusView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ announceView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
index 72e845f..ddba933 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
@@ -23,6 +23,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
import android.widget.Button;
import android.widget.ListView;
@@ -105,5 +106,11 @@
mButtonRight = view.findViewById(R.id.button_right);
mButtonRight.setVisibility(View.GONE);
+
+ if (savedInstanceState == null) {
+ // For Talkback to describe this fragment
+ mTitleSummaryContainer.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
}
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
index 0a2c09b..7308741 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
@@ -75,6 +75,7 @@
private static final String KEY_WIFI_PRESHARED_KEY = "key_wifi_preshared_key";
private static final String KEY_WIFI_HIDDEN_SSID = "key_wifi_hidden_ssid";
private static final String KEY_WIFI_NETWORK_ID = "key_wifi_network_id";
+ private static final String KEY_IS_HOTSPOT = "key_is_hotspot";
private FragmentManager mFragmentManager;
@@ -104,14 +105,15 @@
mWifiDppQrCode = WifiQrCode.getValidWifiDppQrCodeOrNull(qrCode);
- String security = savedInstanceState.getString(KEY_WIFI_SECURITY);
- String ssid = savedInstanceState.getString(KEY_WIFI_SSID);
- String preSharedKey = savedInstanceState.getString(KEY_WIFI_PRESHARED_KEY);
- boolean hiddenSsid = savedInstanceState.getBoolean(KEY_WIFI_HIDDEN_SSID);
- int networkId = savedInstanceState.getInt(KEY_WIFI_NETWORK_ID);
+ final String security = savedInstanceState.getString(KEY_WIFI_SECURITY);
+ final String ssid = savedInstanceState.getString(KEY_WIFI_SSID);
+ final String preSharedKey = savedInstanceState.getString(KEY_WIFI_PRESHARED_KEY);
+ final boolean hiddenSsid = savedInstanceState.getBoolean(KEY_WIFI_HIDDEN_SSID);
+ final int networkId = savedInstanceState.getInt(KEY_WIFI_NETWORK_ID);
+ final boolean isHotspot = savedInstanceState.getBoolean(KEY_IS_HOTSPOT);
mWifiNetworkConfig = WifiNetworkConfig.getValidConfigOrNull(security, ssid,
- preSharedKey, hiddenSsid, networkId);
+ preSharedKey, hiddenSsid, networkId, isHotspot);
} else {
handleIntent(getIntent());
}
@@ -361,6 +363,7 @@
outState.putString(KEY_WIFI_PRESHARED_KEY, mWifiNetworkConfig.getPreSharedKey());
outState.putBoolean(KEY_WIFI_HIDDEN_SSID, mWifiNetworkConfig.getHiddenSsid());
outState.putInt(KEY_WIFI_NETWORK_ID, mWifiNetworkConfig.getNetworkId());
+ outState.putBoolean(KEY_IS_HOTSPOT, mWifiNetworkConfig.isHotspot());
}
super.onSaveInstanceState(outState);
@@ -393,7 +396,8 @@
wifiConfiguration.getPrintableSsid(),
wifiConfiguration.preSharedKey,
/* hiddenSsid */ false,
- wifiConfiguration.networkId);
+ wifiConfiguration.networkId,
+ /* isHotspot */ false);
}
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
index fab495d..eafbe68 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
@@ -38,6 +38,7 @@
private ImageView mDevicesCheckCircleGreenHeaderIcon;
protected TextView mTitle;
protected TextView mSummary;
+ protected View mTitleSummaryContainer;
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
@@ -48,6 +49,10 @@
view.findViewById(R.id.devices_check_circle_green_icon);
mTitle = view.findViewById(android.R.id.title);
mSummary = view.findViewById(android.R.id.summary);
+
+ // This is the LinearLayout which groups mTitle and mSummary for Talkback to announce the
+ // content in a way that reflects its natural groupings.
+ mTitleSummaryContainer = view.findViewById(R.id.title_summary_container);
}
protected void setHeaderIconImageResource(int resId) {
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
index daa41d9f..2cd5e23 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -60,6 +60,14 @@
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
+ // setTitle for Talkback
+ final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity();
+ if (wifiNetworkConfig.isHotspot()) {
+ getActivity().setTitle(R.string.wifi_dpp_share_hotspot);
+ } else {
+ getActivity().setTitle(R.string.wifi_dpp_share_wifi);
+ }
+
setHasOptionsMenu(true);
final ActionBar actionBar = getActivity().getActionBar();
if (actionBar != null) {
@@ -86,7 +94,8 @@
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity();
MenuItem menuItem;
- if (wifiNetworkConfig.isSupportWifiDpp(getActivity())) {
+ if (!wifiNetworkConfig.isHotspot() &&
+ wifiNetworkConfig.isSupportWifiDpp(getActivity())) {
menuItem = menu.add(0, Menu.FIRST, 0, R.string.next_label);
menuItem.setIcon(R.drawable.ic_scan_24dp);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
@@ -127,9 +136,15 @@
setHeaderIconImageResource(R.drawable.ic_qrcode_24dp);
final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity();
- mTitle.setText(R.string.wifi_dpp_share_wifi);
- mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_with_another_device,
- wifiNetworkConfig.getSsid()));
+ if (wifiNetworkConfig.isHotspot()) {
+ mTitle.setText(R.string.wifi_dpp_share_hotspot);
+ mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_to_share_hotspot,
+ wifiNetworkConfig.getSsid()));
+ } else {
+ mTitle.setText(R.string.wifi_dpp_share_wifi);
+ mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_with_another_device,
+ wifiNetworkConfig.getSsid()));
+ }
mQrCode = wifiNetworkConfig.getQrCode();
setQrCode();
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index a19069b..4535599 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -41,6 +41,7 @@
import android.view.TextureView.SurfaceTextureListener;
import android.view.View;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -174,6 +175,13 @@
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
+ // setTitle for Talkback
+ if (mIsConfiguratorMode) {
+ getActivity().setTitle(R.string.wifi_dpp_add_device_to_network);
+ } else {
+ getActivity().setTitle(R.string.wifi_dpp_scan_qr_code);
+ }
+
final ActionBar actionBar = getActivity().getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
@@ -380,6 +388,7 @@
public void showErrorMessage(String message) {
mErrorMessage.setVisibility(View.VISIBLE);
mErrorMessage.setText(message);
+ mErrorMessage.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
mHandler.removeMessages(MESSAGE_HIDE_ERROR_MESSAGE);
mHandler.sendEmptyMessageDelayed(MESSAGE_HIDE_ERROR_MESSAGE,
@@ -410,6 +419,8 @@
mProgressBar.setVisibility(View.VISIBLE);
startWifiDppEnrolleeInitiator((WifiQrCode)msg.obj);
updateEnrolleeSummary();
+ mSummary.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
break;
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 4d8cca5..fe7af27 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -16,11 +16,16 @@
package com.android.settings.wifi.dpp;
+import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
+import android.hardware.biometrics.BiometricPrompt;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.Looper;
import android.text.TextUtils;
import android.util.FeatureFlagUtils;
@@ -70,6 +75,9 @@
/** The data corresponding to {@code WifiConfiguration} networkId */
public static final String EXTRA_WIFI_NETWORK_ID = "networkId";
+ /** The data to recognize if it's a Wi-Fi hotspot for configuration */
+ public static final String EXTRA_IS_HOTSPOT = "isHotspot";
+
/** Used by {@link android.provider.Settings#ACTION_PROCESS_WIFI_EASY_CONNECT_URI} to
* indicate test mode UI should be shown. Test UI does not make API calls. Value is a boolean.*/
public static final String EXTRA_TEST = "test";
@@ -142,24 +150,12 @@
return str.substring(begin, end+1);
}
- private static String getSecurityString(AccessPoint accessPoint) {
- switch(accessPoint.getSecurity()) {
- case AccessPoint.SECURITY_WEP:
- return WifiQrCode.SECURITY_WEP;
- case AccessPoint.SECURITY_PSK:
- return WifiQrCode.SECURITY_WPA_PSK;
- case AccessPoint.SECURITY_SAE:
- return WifiQrCode.SECURITY_SAE;
- default:
- return WifiQrCode.SECURITY_NO_PASSWORD;
- }
- }
-
static String getSecurityString(WifiConfiguration config) {
if (config.allowedKeyManagement.get(KeyMgmt.SAE)) {
return WifiQrCode.SECURITY_SAE;
}
- if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
+ if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ||
+ config.allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
return WifiQrCode.SECURITY_WPA_PSK;
}
return (config.wepKeys[0] == null) ?
@@ -171,6 +167,9 @@
* security. It may return null if the security is not supported by QR code generator nor
* scanner.
*
+ * Do not use this method for Wi-Fi hotspot network, use
+ * {@code getHotspotConfiguratorIntentOrNull} instead.
+ *
* @param context The context to use for the content resolver
* @param wifiManager An instance of {@link WifiManager}
* @param accessPoint An instance of {@link AccessPoint}
@@ -187,15 +186,63 @@
return null;
}
- final WifiConfiguration wifiConfig = accessPoint.getConfig();
- final String ssid = removeFirstAndLastDoubleQuotes(wifiConfig.SSID);
- final String security = getSecurityString(accessPoint);
- String preSharedKey = wifiConfig.preSharedKey;
+ final WifiConfiguration wifiConfiguration = accessPoint.getConfig();
+ setConfiguratorIntentExtra(intent, wifiManager, wifiConfiguration);
+
+ if (wifiConfiguration.networkId == WifiConfiguration.INVALID_NETWORK_ID) {
+ throw new IllegalArgumentException("Invalid network ID");
+ } else {
+ intent.putExtra(EXTRA_WIFI_NETWORK_ID, wifiConfiguration.networkId);
+ }
+
+ return intent;
+ }
+
+ /**
+ * Returns an intent to launch QR code generator for the Wi-Fi hotspot. It may return null if
+ * the security is not supported by QR code generator.
+ *
+ * @param context The context to use for the content resolver
+ * @param wifiManager An instance of {@link WifiManager}
+ * @param wifiConfiguration {@link WifiConfiguration} of the Wi-Fi hotspot
+ * @return Intent for launching QR code generator
+ */
+ public static Intent getHotspotConfiguratorIntentOrNull(Context context,
+ WifiManager wifiManager, WifiConfiguration wifiConfiguration) {
+ final Intent intent = new Intent(context, WifiDppConfiguratorActivity.class);
+ if (isSupportHotspotConfiguratorQrCodeGenerator(wifiConfiguration)) {
+ intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+ } else {
+ return null;
+ }
+
+ setConfiguratorIntentExtra(intent, wifiManager, wifiConfiguration);
+
+ intent.putExtra(EXTRA_WIFI_NETWORK_ID, WifiConfiguration.INVALID_NETWORK_ID);
+ intent.putExtra(EXTRA_IS_HOTSPOT, true);
+
+ return intent;
+ }
+
+ /**
+ * Set all extra except {@code EXTRA_WIFI_NETWORK_ID} for the intent to
+ * launch configurator activity later.
+ *
+ * @param intent the target to set extra
+ * @param wifiManager an instance of {@code WifiManager}
+ * @param wifiConfiguration the Wi-Fi network for launching configurator activity
+ */
+ private static void setConfiguratorIntentExtra(Intent intent, WifiManager wifiManager,
+ WifiConfiguration wifiConfiguration) {
+ final String ssid = removeFirstAndLastDoubleQuotes(wifiConfiguration.SSID);
+ final String security = getSecurityString(wifiConfiguration);
+ String preSharedKey = wifiConfiguration.preSharedKey;
if (preSharedKey != null) {
// When the value of this key is read, the actual key is not returned, just a "*".
// Call privileged system API to obtain actual key.
- preSharedKey = removeFirstAndLastDoubleQuotes(getPresharedKey(wifiManager, wifiConfig));
+ preSharedKey = removeFirstAndLastDoubleQuotes(getPresharedKey(wifiManager,
+ wifiConfiguration));
}
if (!TextUtils.isEmpty(ssid)) {
@@ -207,13 +254,6 @@
if (!TextUtils.isEmpty(preSharedKey)) {
intent.putExtra(EXTRA_WIFI_PRE_SHARED_KEY, preSharedKey);
}
- if (wifiConfig.networkId == WifiConfiguration.INVALID_NETWORK_ID) {
- throw new IllegalArgumentException("Invalid network ID");
- } else {
- intent.putExtra(EXTRA_WIFI_NETWORK_ID, wifiConfig.networkId);
- }
-
- return intent;
}
/**
@@ -228,6 +268,54 @@
isSupportConfiguratorQrCodeGenerator(accessPoint);
}
+ /**
+ * Shows authentication screen to confirm credentials (pin, pattern or password) for the current
+ * user of the device.
+ *
+ * @param context The {@code Context} used to get {@code KeyguardManager} service
+ * @param title The title on lock screen
+ * @param description The description on lock screen
+ * @param successRunnable The {@code Runnable} which will be executed if the user does not setup
+ * device security or if lock screen is unlocked
+ */
+ public static void showLockScreen(Context context, String title, String description,
+ Runnable successRunnable) {
+ final KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(
+ Context.KEYGUARD_SERVICE);
+
+ if (keyguardManager.isKeyguardSecure()) {
+ final BiometricPrompt.AuthenticationCallback authenticationCallback =
+ new BiometricPrompt.AuthenticationCallback() {
+ @Override
+ public void onAuthenticationSucceeded(
+ BiometricPrompt.AuthenticationResult result) {
+ successRunnable.run();
+ }
+
+ @Override
+ public void onAuthenticationError(int errorCode, CharSequence errString) {
+ //Do nothing
+ }
+ };
+
+ final BiometricPrompt.Builder builder = new BiometricPrompt.Builder(context)
+ .setTitle(title)
+ .setDescription(description);
+
+ if (keyguardManager.isDeviceSecure()) {
+ builder.setDeviceCredentialAllowed(true);
+ }
+
+ final BiometricPrompt bp = builder.build();
+ final Handler handler = new Handler(Looper.getMainLooper());
+ bp.authenticate(new CancellationSignal(),
+ runnable -> handler.post(runnable),
+ authenticationCallback);
+ } else {
+ successRunnable.run();
+ }
+ }
+
private static boolean isSupportConfiguratorQrCodeScanner(Context context,
AccessPoint accessPoint) {
if (!isWifiDppEnabled(context)) {
@@ -254,4 +342,13 @@
return false;
}
+
+ private static boolean isSupportHotspotConfiguratorQrCodeGenerator(
+ WifiConfiguration wifiConfiguration) {
+ // QR code generator produces QR code with ZXing's Wi-Fi network config format,
+ // it supports PSK and WEP and non security
+ // KeyMgmt.NONE is for WEP or non security
+ return wifiConfiguration.allowedKeyManagement.get(KeyMgmt.WPA2_PSK) ||
+ wifiConfiguration.allowedKeyManagement.get(KeyMgmt.NONE);
+ }
}
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
index a483073..fdc74d8 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
@@ -30,7 +30,6 @@
import android.text.TextUtils;
import android.util.Log;
-import androidx.annotation.Keep;
import androidx.annotation.VisibleForTesting;
/**
@@ -52,15 +51,17 @@
private String mPreSharedKey;
private boolean mHiddenSsid;
private int mNetworkId;
+ private boolean mIsHotspot;
@VisibleForTesting
WifiNetworkConfig(String security, String ssid, String preSharedKey,
- boolean hiddenSsid, int networkId) {
+ boolean hiddenSsid, int networkId, boolean isHotspot) {
mSecurity = security;
mSsid = ssid;
mPreSharedKey = preSharedKey;
mHiddenSsid = hiddenSsid;
mNetworkId = networkId;
+ mIsHotspot = isHotspot;
}
public WifiNetworkConfig(WifiNetworkConfig config) {
@@ -69,6 +70,7 @@
mPreSharedKey = config.mPreSharedKey;
mHiddenSsid = config.mHiddenSsid;
mNetworkId = config.mNetworkId;
+ mIsHotspot = config.mIsHotspot;
}
/**
@@ -86,23 +88,26 @@
* android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER
*/
public static WifiNetworkConfig getValidConfigOrNull(Intent intent) {
- String security = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SECURITY);
- String ssid = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SSID);
- String preSharedKey = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY);
- boolean hiddenSsid = intent.getBooleanExtra(WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID, false);
- int networkId = intent.getIntExtra(WifiDppUtils.EXTRA_WIFI_NETWORK_ID,
+ final String security = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SECURITY);
+ final String ssid = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SSID);
+ final String preSharedKey = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY);
+ final boolean hiddenSsid = intent.getBooleanExtra(WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID,
+ false);
+ final int networkId = intent.getIntExtra(WifiDppUtils.EXTRA_WIFI_NETWORK_ID,
WifiConfiguration.INVALID_NETWORK_ID);
+ final boolean isHotspot = intent.getBooleanExtra(WifiDppUtils.EXTRA_IS_HOTSPOT, false);
- return getValidConfigOrNull(security, ssid, preSharedKey, hiddenSsid, networkId);
+ return getValidConfigOrNull(security, ssid, preSharedKey, hiddenSsid, networkId, isHotspot);
}
public static WifiNetworkConfig getValidConfigOrNull(String security, String ssid,
- String preSharedKey, boolean hiddenSsid, int networkId) {
+ String preSharedKey, boolean hiddenSsid, int networkId, boolean isHotspot) {
if (!isValidConfig(security, ssid, preSharedKey, hiddenSsid)) {
return null;
}
- return new WifiNetworkConfig(security, ssid, preSharedKey, hiddenSsid, networkId);
+ return new WifiNetworkConfig(security, ssid, preSharedKey, hiddenSsid, networkId,
+ isHotspot);
}
public static boolean isValidConfig(WifiNetworkConfig config) {
@@ -174,31 +179,30 @@
return barcode;
}
- @Keep
public String getSecurity() {
return mSecurity;
}
- @Keep
public String getSsid() {
return mSsid;
}
- @Keep
public String getPreSharedKey() {
return mPreSharedKey;
}
- @Keep
public boolean getHiddenSsid() {
return mHiddenSsid;
}
- @Keep
public int getNetworkId() {
return mNetworkId;
}
+ public boolean isHotspot() {
+ return mIsHotspot;
+ }
+
public void connect(Context context, WifiManager.ActionListener listener) {
WifiConfiguration wifiConfiguration = getWifiConfigurationOrNull();
if (wifiConfiguration == null) {
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
index ce92f90..4688d76 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
@@ -218,7 +218,7 @@
final WifiNetworkConfig networkConfig = WifiNetworkConfig.getValidConfigOrNull(
selectedAccessPoint.getSecurityString(/* concise */ true),
wifiConfig.getPrintableSsid(), wifiConfig.preSharedKey, /* hiddenSsid */ false,
- wifiConfig.networkId);
+ wifiConfig.networkId, /* isHotspot */ false);
if (mOnChooseNetworkListener != null) {
mOnChooseNetworkListener.onChooseNetwork(networkConfig);
}
@@ -232,7 +232,8 @@
/* ssid */ WifiNetworkConfig.FAKE_SSID,
/* preSharedKey */ WifiNetworkConfig.FAKE_PASSWORD,
/* hiddenSsid */ true,
- /* networkId */ WifiConfiguration.INVALID_NETWORK_ID));
+ /* networkId */ WifiConfiguration.INVALID_NETWORK_ID,
+ /* isHotspot*/ false));
}
} else {
return super.onPreferenceTreeClick(preference);
diff --git a/src/com/android/settings/wifi/dpp/WifiQrCode.java b/src/com/android/settings/wifi/dpp/WifiQrCode.java
index 10971cf..8296a62 100644
--- a/src/com/android/settings/wifi/dpp/WifiQrCode.java
+++ b/src/com/android/settings/wifi/dpp/WifiQrCode.java
@@ -133,7 +133,7 @@
password = removeBackSlash(password);
mWifiNetworkConfig = WifiNetworkConfig.getValidConfigOrNull(security, ssid, password,
- hiddenSsid, WifiConfiguration.INVALID_NETWORK_ID);
+ hiddenSsid, WifiConfiguration.INVALID_NETWORK_ID, /* isHotspot */ false);
if (mWifiNetworkConfig == null) {
throw new IllegalArgumentException("Invalid format");
diff --git a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceController.java b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceController.java
index 4155ef7..40e6e56 100644
--- a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceController.java
+++ b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceController.java
@@ -28,6 +28,7 @@
import com.android.settings.core.BasePreferenceController;
import com.android.settings.utils.PreferenceGroupChildrenCache;
+import com.android.settings.R;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.utils.ThreadUtils;
@@ -122,6 +123,12 @@
final int accessPointsSize = accessPoints.size();
for (int i = 0; i < accessPointsSize; ++i) {
AccessPoint ap = accessPoints.get(i);
+
+ if (mHost != null && mHost.isSubscriptionsFeatureEnabled()
+ && ap.isPasspointConfig()) {
+ continue;
+ }
+
String key = ap.getKey();
AccessPointPreference preference =
(AccessPointPreference) mChildrenCache.getCachedPreference(key);
@@ -139,6 +146,15 @@
if (mPreferenceGroup.getPreferenceCount() < 1) {
Log.w(TAG, "Saved networks activity loaded, but there are no saved networks!");
+ mPreferenceGroup.setVisible(false);
+ } else {
+ mPreferenceGroup.setVisible(true);
+ }
+
+ if (mHost != null && !mHost.isSubscriptionsFeatureEnabled()) {
+ mPreferenceGroup.setVisible(true);
+ mPreferenceGroup.setTitle(null);
+ mPreferenceGroup.setLayoutResource(R.layout.preference_category_no_label);
}
}
}
diff --git a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
index 6a9e8a2..ea858f3 100644
--- a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
@@ -75,6 +75,8 @@
.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
use(SavedAccessPointsPreferenceController.class)
.setHost(this);
+ use(SubscribedAccessPointsPreferenceController.class)
+ .setHost(this);
}
@Override
@@ -172,10 +174,15 @@
Log.e(TAG, "Failed to remove Passpoint configuration for "
+ mSelectedAccessPoint.getConfigName());
}
- use(SavedAccessPointsPreferenceController.class)
- .postRefreshSavedAccessPoints();
+ if (isSubscriptionsFeatureEnabled()) {
+ use(SubscribedAccessPointsPreferenceController.class)
+ .postRefreshSubscribedAccessPoints();
+ } else {
+ use(SavedAccessPointsPreferenceController.class)
+ .postRefreshSavedAccessPoints();
+ }
} else {
- // mForgetListener will call initPreferences upon completion
+ // both onSuccess/onFailure will call postRefreshSavedAccessPoints
mWifiManager.forget(mSelectedAccessPoint.getConfig().networkId,
use(SavedAccessPointsPreferenceController.class));
}
@@ -192,10 +199,11 @@
* Checks if showing WifiNetworkDetailsFragment when clicking saved network item.
*/
public static boolean usingDetailsFragment(Context context) {
- if (FeatureFlagUtils.isEnabled(context, FeatureFlags.MOBILE_NETWORK_V2)
- && FeatureFlagPersistent.isEnabled(context, FeatureFlags.NETWORK_INTERNET_V2)) {
- return false; // TODO(b/124695272): mark true when UI is ready.
- }
- return false;
+ return FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_SAVED_SCREEN);
+ }
+
+ boolean isSubscriptionsFeatureEnabled() {
+ return FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.MOBILE_NETWORK_V2)
+ && FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2);
}
}
diff --git a/src/com/android/settings/wifi/savedaccesspoints/SubscribedAccessPointsPreferenceController.java b/src/com/android/settings/wifi/savedaccesspoints/SubscribedAccessPointsPreferenceController.java
new file mode 100644
index 0000000..8d31c82
--- /dev/null
+++ b/src/com/android/settings/wifi/savedaccesspoints/SubscribedAccessPointsPreferenceController.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2019 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.wifi.savedaccesspoints;
+
+
+import android.content.Context;
+import android.net.wifi.WifiManager;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.utils.PreferenceGroupChildrenCache;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.utils.ThreadUtils;
+import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.AccessPointPreference;
+import com.android.settingslib.wifi.AccessPointPreference.UserBadgeCache;
+import com.android.settingslib.wifi.WifiSavedConfigUtils;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Controller that manages a PreferenceGroup, which contains a list of subscribed access points.
+ */
+// TODO(b/127206629): Code refactor to avoid duplicated coding after removed feature flag.
+public class SubscribedAccessPointsPreferenceController extends BasePreferenceController implements
+ LifecycleObserver, OnStart, Preference.OnPreferenceClickListener,
+ WifiManager.ActionListener {
+
+ private static final String TAG = "SubscribedAPPrefCtrl";
+
+ private final WifiManager mWifiManager;
+ private final PreferenceGroupChildrenCache mChildrenCache;
+ private final UserBadgeCache mUserBadgeCache;
+ private PreferenceGroup mPreferenceGroup;
+ private SavedAccessPointsWifiSettings mHost;
+
+ public SubscribedAccessPointsPreferenceController(Context context,
+ String preferenceKey) {
+ super(context, preferenceKey);
+ mUserBadgeCache = new AccessPointPreference.UserBadgeCache(context.getPackageManager());
+ mWifiManager = context.getSystemService(WifiManager.class);
+ mChildrenCache = new PreferenceGroupChildrenCache();
+ }
+
+ public SubscribedAccessPointsPreferenceController setHost(SavedAccessPointsWifiSettings host) {
+ mHost = host;
+ return this;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreferenceGroup = screen.findPreference(getPreferenceKey());
+ }
+
+ @Override
+ public void onStart() {
+ refreshSubscribedAccessPoints();
+ }
+
+ public void postRefreshSubscribedAccessPoints() {
+ ThreadUtils.postOnMainThread(() -> refreshSubscribedAccessPoints());
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (mHost != null) {
+ mHost.showWifiDialog((AccessPointPreference) preference);
+ }
+ return false;
+ }
+
+ @Override
+ public void onSuccess() {
+ postRefreshSubscribedAccessPoints();
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ postRefreshSubscribedAccessPoints();
+ }
+
+ @VisibleForTesting
+ void refreshSubscribedAccessPoints() {
+ if (mPreferenceGroup == null) {
+ Log.w(TAG, "PreferenceGroup is null, skipping.");
+ return;
+ }
+
+ if (mHost != null && !mHost.isSubscriptionsFeatureEnabled()) {
+ mPreferenceGroup.setVisible(false);
+ return;
+ }
+
+ final Context prefContext = mPreferenceGroup.getContext();
+
+ final List<AccessPoint> accessPoints =
+ WifiSavedConfigUtils.getAllConfigs(mContext, mWifiManager);
+ Collections.sort(accessPoints, SavedNetworkComparator.INSTANCE);
+ mChildrenCache.cacheRemoveAllPrefs(mPreferenceGroup);
+
+ final int accessPointsSize = accessPoints.size();
+ for (int i = 0; i < accessPointsSize; ++i) {
+ AccessPoint ap = accessPoints.get(i);
+ if (!ap.isPasspointConfig()) {
+ continue;
+ }
+
+ final String key = ap.getKey();
+ AccessPointPreference preference =
+ (AccessPointPreference) mChildrenCache.getCachedPreference(key);
+ if (preference == null) {
+ preference = new AccessPointPreference(ap, prefContext, mUserBadgeCache, true);
+ preference.setKey(key);
+ preference.setIcon(null);
+ preference.setOnPreferenceClickListener(this);
+ mPreferenceGroup.addPreference(preference);
+ }
+ preference.setOrder(i);
+ }
+
+ mChildrenCache.removeCachedPrefs(mPreferenceGroup);
+
+ if (mPreferenceGroup.getPreferenceCount() < 1) {
+ Log.w(TAG, "Subscribed networks activity loaded,"
+ + " but there are no subscribed networks!");
+ mPreferenceGroup.setVisible(false);
+ } else {
+ mPreferenceGroup.setVisible(true);
+ }
+ }
+}
diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java
index 8d20f7f..a2debb8 100644
--- a/src/com/android/settings/wifi/slice/WifiSlice.java
+++ b/src/com/android/settings/wifi/slice/WifiSlice.java
@@ -198,7 +198,7 @@
private IconCompat getEndIcon(AccessPoint accessPoint) {
if (accessPoint.isActive()) {
- return IconCompat.createWithResource(mContext, R.drawable.ic_settings_accent);
+ return null;
} else if (accessPoint.getSecurity() != AccessPoint.SECURITY_NONE) {
return IconCompat.createWithResource(mContext, R.drawable.ic_friction_lock_closed);
} else if (accessPoint.isMetered()) {
diff --git a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
index 2ae6b58..8f6d489 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
@@ -43,9 +43,6 @@
implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop {
private static final String WIFI_TETHER_SETTINGS = "wifi_tether";
- private static final IntentFilter AIRPLANE_INTENT_FILTER = new IntentFilter(
- Intent.ACTION_AIRPLANE_MODE_CHANGED);
- private static final int ID_NULL = -1;
private final ConnectivityManager mConnectivityManager;
private final String[] mWifiRegexs;
@@ -103,8 +100,6 @@
@Override
public void onStart() {
if (mPreference != null) {
- mContext.registerReceiver(mReceiver, AIRPLANE_INTENT_FILTER);
- clearSummaryForAirplaneMode();
if (mWifiTetherSoftApManager != null) {
mWifiTetherSoftApManager.registerSoftApCallback();
}
@@ -114,7 +109,6 @@
@Override
public void onStop() {
if (mPreference != null) {
- mContext.unregisterReceiver(mReceiver);
if (mWifiTetherSoftApManager != null) {
mWifiTetherSoftApManager.unRegisterSoftApCallback();
}
@@ -146,19 +140,6 @@
});
}
- //
- // Everything below is copied from WifiApEnabler
- //
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
- clearSummaryForAirplaneMode(R.string.wifi_hotspot_off_subtext);
- }
- }
- };
-
@VisibleForTesting
void handleWifiApStateChanged(int state, int reason) {
switch (state) {
@@ -174,7 +155,6 @@
break;
case WifiManager.WIFI_AP_STATE_DISABLED:
mPreference.setSummary(R.string.wifi_hotspot_off_subtext);
- clearSummaryForAirplaneMode();
break;
default:
if (reason == WifiManager.SAP_START_FAILURE_NO_CHANNEL) {
@@ -182,7 +162,6 @@
} else {
mPreference.setSummary(R.string.wifi_error);
}
- clearSummaryForAirplaneMode();
}
}
@@ -194,21 +173,4 @@
BidiFormatter.getInstance().unicodeWrap(
(wifiConfig == null) ? s : wifiConfig.SSID)));
}
-
- private void clearSummaryForAirplaneMode() {
- clearSummaryForAirplaneMode(ID_NULL);
- }
-
- private void clearSummaryForAirplaneMode(int defaultId) {
- boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
- if (isAirplaneMode) {
- mPreference.setSummary(R.string.wifi_tether_disabled_by_airplane);
- } else if (defaultId != ID_NULL){
- mPreference.setSummary(defaultId);
- }
- }
- //
- // Everything above is copied from WifiApEnabler
- //
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
index eb6a123..10f3e56 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
@@ -17,13 +17,18 @@
package com.android.settings.wifi.tether;
import android.content.Context;
+import android.content.Intent;
import android.net.wifi.WifiConfiguration;
+import android.util.Log;
+import android.view.View;
import androidx.annotation.VisibleForTesting;
import androidx.preference.EditTextPreference;
import androidx.preference.Preference;
+import com.android.settings.R;
import com.android.settings.widget.ValidatedEditTextPreference;
+import com.android.settings.wifi.dpp.WifiDppUtils;
public class WifiTetherSSIDPreferenceController extends WifiTetherBasePreferenceController
implements ValidatedEditTextPreference.Validator {
@@ -56,6 +61,23 @@
mSSID = DEFAULT_SSID;
}
((ValidatedEditTextPreference) mPreference).setValidator(this);
+
+ if (mWifiManager.isWifiApEnabled() && config != null) {
+ final Intent intent = WifiDppUtils.getHotspotConfiguratorIntentOrNull(mContext,
+ mWifiManager, config);
+
+ if (intent == null) {
+ Log.e(TAG, "Invalid security to share hotspot");
+ ((WifiTetherSsidPreference) mPreference).setButtonVisible(false);
+ } else {
+ ((WifiTetherSsidPreference) mPreference).setButtonOnClickListener(
+ view -> shareHotspotNetwork(intent));
+ ((WifiTetherSsidPreference) mPreference).setButtonVisible(true);
+ }
+ } else {
+ ((WifiTetherSsidPreference) mPreference).setButtonVisible(false);
+ }
+
updateSsidDisplay((EditTextPreference) mPreference);
}
@@ -80,4 +102,19 @@
preference.setText(mSSID);
preference.setSummary(mSSID);
}
+
+ private void shareHotspotNetwork(Intent intent) {
+ final String title = mContext.getString(
+ R.string.lockpassword_confirm_your_pattern_header);
+ final String description = String.format(
+ mContext.getString(R.string.wifi_sharing_message), mSSID);
+
+ WifiDppUtils.showLockScreen(mContext, title, description,
+ () -> mContext.startActivity(intent));
+ }
+
+ @VisibleForTesting
+ boolean isQrCodeButtonAvailable() {
+ return ((WifiTetherSsidPreference) mPreference).isQrCodeButtonAvailable();
+ }
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSsidPreference.java b/src/com/android/settings/wifi/tether/WifiTetherSsidPreference.java
new file mode 100644
index 0000000..64014d9
--- /dev/null
+++ b/src/com/android/settings/wifi/tether/WifiTetherSsidPreference.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 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.wifi.tether;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageButton;
+
+import androidx.annotation.DrawableRes;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.widget.ValidatedEditTextPreference;
+
+/**
+ * Support a QR code share button for {@code EditTextPreference} that supports input validation.
+ */
+public class WifiTetherSsidPreference extends ValidatedEditTextPreference {
+ private static final String TAG = "WifiTetherSsidPreference";
+
+ private ImageButton mImageButton;
+ private Drawable mButtonIcon;
+ private View.OnClickListener mClickListener;
+ private boolean mVisible;
+
+ public WifiTetherSsidPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ initialize();
+ }
+
+ public WifiTetherSsidPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ initialize();
+ }
+
+ public WifiTetherSsidPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ initialize();
+ }
+
+ public WifiTetherSsidPreference(Context context) {
+ super(context);
+
+ initialize();
+ }
+
+ private void initialize() {
+ setWidgetLayoutResource(R.layout.wifi_button_preference_widget);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ if (mImageButton == null) {
+ mImageButton = (ImageButton) holder.findViewById(R.id.button_icon);
+
+ mImageButton.setContentDescription(
+ getContext().getString(R.string.wifi_dpp_share_hotspot));
+ setButtonIcon(R.drawable.ic_qrcode_24dp);
+ mImageButton.setImageDrawable(mButtonIcon);
+ }
+
+ if (mVisible) {
+ mImageButton.setOnClickListener(mClickListener);
+ mImageButton.setVisibility(View.VISIBLE);
+ } else {
+ mImageButton.setVisibility(View.GONE);
+ }
+ }
+
+ public void setButtonOnClickListener(View.OnClickListener listener) {
+ mClickListener = listener;
+ }
+
+ public void setButtonVisible(boolean visible) {
+ mVisible = visible;
+ }
+
+ private void setButtonIcon(@DrawableRes int iconResId) {
+ try {
+ mButtonIcon = getContext().getDrawable(iconResId);
+ } catch (Resources.NotFoundException exception) {
+ Log.e(TAG, "Resource does not exist: " + iconResId);
+ }
+ }
+
+ @VisibleForTesting
+ boolean isQrCodeButtonAvailable() {
+ return mVisible && mClickListener != null;
+ }
+}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
index 8d87b32..0f31d19 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
@@ -61,7 +61,6 @@
static {
WIFI_INTENT_FILTER = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
- WIFI_INTENT_FILTER.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
}
WifiTetherSwitchBarController(Context context, SwitchWidgetController switchBar) {
@@ -119,8 +118,6 @@
final int state = intent.getIntExtra(
WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED);
handleWifiApStateChanged(state);
- } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
- updateWifiSwitch();
}
}
};
@@ -154,13 +151,7 @@
}
private void updateWifiSwitch() {
- boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
- if (!isAirplaneMode) {
- mSwitchBar.setEnabled(!mDataSaverBackend.isDataSaverEnabled());
- } else {
- mSwitchBar.setEnabled(false);
- }
+ mSwitchBar.setEnabled(!mDataSaverBackend.isDataSaverEnabled());
}
@Override
diff --git a/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor b/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor
index ce03d95..675108d 100644
--- a/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor
+++ b/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor
@@ -6,6 +6,7 @@
com.android.settings.bluetooth.BluetoothDeviceNamePreferenceController
com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController
com.android.settings.datausage.DataUsageSummaryPreferenceController
+com.android.settings.datausage.WifiDataUsageSummaryPreferenceController
com.android.settings.fuelgauge.RestrictAppPreferenceController
com.android.settings.fuelgauge.batterysaver.BatterySaverButtonPreferenceController
com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController
diff --git a/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarPreferenceTest.java
new file mode 100644
index 0000000..ba7bd2c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarPreferenceTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 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.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.preference.PreferenceViewHolder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BalanceSeekBarPreferenceTest {
+ private static final int BALANCE_CENTER_VALUE = 100;
+ private static final int BALANCE_MAX_VALUE = 200;
+
+ private Context mContext;
+ private AttributeSet mAttrs;
+ private PreferenceViewHolder mHolder;
+ private BalanceSeekBar mSeekBar;
+ private BalanceSeekBarPreference mSeekBarPreference;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mSeekBarPreference = new BalanceSeekBarPreference(mContext, mAttrs);
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ final View view =
+ inflater.inflate(mSeekBarPreference.getLayoutResource(),
+ new LinearLayout(mContext), false);
+ mHolder = PreferenceViewHolder.createInstanceForTests(view);
+ mSeekBar = (BalanceSeekBar) view.findViewById(com.android.internal.R.id.seekbar);
+ }
+
+ @Test
+ public void seekBarPreferenceOnBindViewHolder_shouldInitSeekBarValue() {
+ mSeekBarPreference.onBindViewHolder(mHolder);
+
+ assertThat(mSeekBar.getMax()).isEqualTo(BALANCE_MAX_VALUE);
+ assertThat(mSeekBar.getProgress()).isEqualTo(BALANCE_CENTER_VALUE);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarTest.java b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarTest.java
new file mode 100644
index 0000000..e0dc681
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2019 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.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BalanceSeekBarTest {
+ // Fix the maximum process value to 200 for testing the BalanceSeekBar.
+ // It affects the SeekBar value of center(100) and snapThreshold(200 * SNAP_TO_PERCENTAGE).
+ private static final int MAX_PROGRESS_VALUE = 200;
+
+ private Context mContext;
+ private AttributeSet mAttrs;
+ private BalanceSeekBar mSeekBar;
+ private BalanceSeekBar.OnSeekBarChangeListener mProxySeekBarListener;
+ private SeekBar.OnSeekBarChangeListener mockSeekBarChangeListener;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mSeekBar = new BalanceSeekBar(mContext, mAttrs);
+ mProxySeekBarListener = mSeekBar.getProxySeekBarListener();
+ mockSeekBarChangeListener = mock(SeekBar.OnSeekBarChangeListener.class);
+ mSeekBar.setOnSeekBarChangeListener(mockSeekBarChangeListener);
+ }
+
+ @Test
+ public void onStartTrackingTouch_shouldInvokeMethod() {
+ mProxySeekBarListener.onStartTrackingTouch(mSeekBar);
+
+ verify(mockSeekBarChangeListener, times(1)).onStartTrackingTouch(mSeekBar);
+ }
+
+ @Test
+ public void onStopTrackingTouch_shouldInvokeMethod() {
+ mProxySeekBarListener.onStopTrackingTouch(mSeekBar);
+
+ verify(mockSeekBarChangeListener, times(1)).onStopTrackingTouch(mSeekBar);
+ }
+
+ @Test
+ public void onProgressChanged_shouldInvokeMethod() {
+ // Assign the test value of SeekBar progress
+ mProxySeekBarListener.onProgressChanged(mSeekBar, MAX_PROGRESS_VALUE, true);
+
+ verify(mockSeekBarChangeListener, times(1)).onProgressChanged(eq(mSeekBar),
+ eq(MAX_PROGRESS_VALUE), eq(true));
+ }
+
+ @Test
+ public void setMaxTest_shouldSetValue() {
+ mSeekBar.setMax(MAX_PROGRESS_VALUE);
+
+ assertThat(getBalanceSeekBarCenter(mSeekBar)).isEqualTo(MAX_PROGRESS_VALUE / 2);
+ assertThat(getBalanceSeekBarSnapThreshold(mSeekBar)).isEqualTo(
+ MAX_PROGRESS_VALUE * BalanceSeekBar.SNAP_TO_PERCENTAGE);
+ }
+
+ @Test
+ public void setProgressTest_shouldSnapToCenter() {
+ // Assign the test value of SeekBar progress within the threshold (94-106 in this case).
+ final int progressWithinThreshold = 102;
+ mSeekBar.setMax(MAX_PROGRESS_VALUE);
+ mSeekBar.setProgress(progressWithinThreshold + 10); //set progress which is over threshold.
+ mProxySeekBarListener.onProgressChanged(mSeekBar, progressWithinThreshold, true);
+
+ assertThat(mSeekBar.getProgress()).isEqualTo(getBalanceSeekBarCenter(mSeekBar));
+ }
+
+ @Test
+ public void setProgressTest_shouldMaintainInputValue() {
+ // Assign the test value of SeekBar progress without the threshold.
+ final int progressWithoutThreshold = 107;
+ mSeekBar.setMax(MAX_PROGRESS_VALUE);
+ mSeekBar.setProgress(progressWithoutThreshold);
+ mProxySeekBarListener.onProgressChanged(mSeekBar, progressWithoutThreshold, true);
+
+ assertThat(mSeekBar.getProgress()).isEqualTo(progressWithoutThreshold);
+ }
+
+ // method to get the center from BalanceSeekBar for testing setMax().
+ private int getBalanceSeekBarCenter(BalanceSeekBar seekBar) {
+ return seekBar.getMax() / 2;
+ }
+
+ // method to get the snapThreshold from BalanceSeekBar for testing setMax().
+ private float getBalanceSeekBarSnapThreshold(BalanceSeekBar seekBar) {
+ return seekBar.getMax() * BalanceSeekBar.SNAP_TO_PERCENTAGE;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
index 6a2348c..8c75e33 100644
--- a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.verify;
import android.accounts.Account;
+import android.app.ActivityManager;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -55,6 +56,7 @@
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowActivityManager;
import org.robolectric.shadows.ShadowContentResolver;
import org.robolectric.shadows.ShadowPackageManager;
@@ -101,6 +103,19 @@
}
@Test
+ public void onStart_lowRamDevice_doNothing() {
+ final AvatarViewMixin mixin = spy(new AvatarViewMixin(mActivity, mImageView));
+
+ final ShadowActivityManager activityManager =
+ Shadow.extract(mContext.getSystemService(ActivityManager.class));
+ activityManager.setIsLowRamDevice(true);
+
+ mixin.onStart();
+
+ verify(mixin, never()).hasAccount();
+ }
+
+ @Test
@Config(qualifiers = "mcc999",
shadows = {
BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java
index 7b9bc25..81d52d2 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java
@@ -25,11 +25,11 @@
import static org.robolectric.Shadows.shadowOf;
import android.app.Activity;
+import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.Intent;
import android.os.UserManager;
-import android.permission.PermissionControllerManager;
import androidx.preference.Preference;
@@ -63,7 +63,7 @@
@Mock
private RoleManager mRoleManager;
@Mock
- private PermissionControllerManager mPermissionControllerManager;
+ private RoleControllerManager mRoleControllerManager;
@Mock
private Preference mPreference;
@@ -77,8 +77,7 @@
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
shadowApplication.setSystemService(Context.ROLE_SERVICE, mRoleManager);
- shadowApplication.setSystemService(Context.PERMISSION_CONTROLLER_SERVICE,
- mPermissionControllerManager);
+ shadowApplication.setSystemService(Context.ROLE_CONTROLLER_SERVICE, mRoleControllerManager);
mActivity = Robolectric.setupActivity(Activity.class);
mShadowUserManager = shadowOf(mActivity.getSystemService(UserManager.class));
mController = new TestRolePreferenceController(mActivity);
@@ -87,7 +86,7 @@
@Test
public void constructor_callsIsApplicationQualifiedForRole() {
- verify(mPermissionControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq(
+ verify(mRoleControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq(
TEST_PACKAGE_NAME), any(Executor.class), any(Consumer.class));
}
@@ -154,7 +153,7 @@
private void setRoleIsVisible(boolean visible) {
final ArgumentCaptor<Consumer<Boolean>> callbackCaptor = ArgumentCaptor.forClass(
Consumer.class);
- verify(mPermissionControllerManager).isRoleVisible(eq(TEST_ROLE_NAME), any(Executor.class),
+ verify(mRoleControllerManager).isRoleVisible(eq(TEST_ROLE_NAME), any(Executor.class),
callbackCaptor.capture());
final Consumer<Boolean> callback = callbackCaptor.getValue();
callback.accept(visible);
@@ -163,7 +162,7 @@
private void setApplicationIsQualifiedForRole(boolean qualified) {
final ArgumentCaptor<Consumer<Boolean>> callbackCaptor = ArgumentCaptor.forClass(
Consumer.class);
- verify(mPermissionControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq(
+ verify(mRoleControllerManager).isApplicationQualifiedForRole(eq(TEST_ROLE_NAME), eq(
TEST_PACKAGE_NAME), any(Executor.class), callbackCaptor.capture());
final Consumer<Boolean> callback = callbackCaptor.getValue();
callback.accept(qualified);
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java
index c2a3b4a..5940d72 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java
@@ -18,8 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.role.RoleControllerManager;
import android.content.Context;
-import android.permission.PermissionControllerManager;
import org.junit.Before;
import org.junit.Test;
@@ -34,15 +34,15 @@
public class DefaultBrowserShortcutPreferenceControllerTest {
@Mock
- private PermissionControllerManager mPermissionControllerManager;
+ private RoleControllerManager mRoleControllerManager;
private DefaultBrowserShortcutPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- ShadowApplication.getInstance().setSystemService(Context.PERMISSION_CONTROLLER_SERVICE,
- mPermissionControllerManager);
+ ShadowApplication.getInstance().setSystemService(Context.ROLE_CONTROLLER_SERVICE,
+ mRoleControllerManager);
mController = new DefaultBrowserShortcutPreferenceController(RuntimeEnvironment.application,
"Package1");
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultEmergencyShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultEmergencyShortcutPreferenceControllerTest.java
index 8466092..8dcf530 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultEmergencyShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultEmergencyShortcutPreferenceControllerTest.java
@@ -18,8 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.role.RoleControllerManager;
import android.content.Context;
-import android.permission.PermissionControllerManager;
import org.junit.Before;
import org.junit.Test;
@@ -34,15 +34,15 @@
public class DefaultEmergencyShortcutPreferenceControllerTest {
@Mock
- private PermissionControllerManager mPermissionControllerManager;
+ private RoleControllerManager mRoleControllerManager;
private DefaultEmergencyShortcutPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- ShadowApplication.getInstance().setSystemService(Context.PERMISSION_CONTROLLER_SERVICE,
- mPermissionControllerManager);
+ ShadowApplication.getInstance().setSystemService(Context.ROLE_CONTROLLER_SERVICE,
+ mRoleControllerManager);
mController = new DefaultEmergencyShortcutPreferenceController(
RuntimeEnvironment.application, "Package1");
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultHomeShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultHomeShortcutPreferenceControllerTest.java
index c5cae3a..7071fec 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultHomeShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultHomeShortcutPreferenceControllerTest.java
@@ -18,8 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.role.RoleControllerManager;
import android.content.Context;
-import android.permission.PermissionControllerManager;
import org.junit.Before;
import org.junit.Test;
@@ -34,15 +34,15 @@
public class DefaultHomeShortcutPreferenceControllerTest {
@Mock
- private PermissionControllerManager mPermissionControllerManager;
+ private RoleControllerManager mRoleControllerManager;
private DefaultHomeShortcutPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- ShadowApplication.getInstance().setSystemService(Context.PERMISSION_CONTROLLER_SERVICE,
- mPermissionControllerManager);
+ ShadowApplication.getInstance().setSystemService(Context.ROLE_CONTROLLER_SERVICE,
+ mRoleControllerManager);
mController = new DefaultHomeShortcutPreferenceController(RuntimeEnvironment.application,
"Package1");
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java
index 4e7a800..d1b6aeb 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java
@@ -18,8 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.role.RoleControllerManager;
import android.content.Context;
-import android.permission.PermissionControllerManager;
import org.junit.Before;
import org.junit.Test;
@@ -37,15 +37,15 @@
private static final String PREFERENCE_KEY = "default_phone_app";
@Mock
- private PermissionControllerManager mPermissionControllerManager;
+ private RoleControllerManager mRoleControllerManager;
private DefaultPhoneShortcutPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- ShadowApplication.getInstance().setSystemService(Context.PERMISSION_CONTROLLER_SERVICE,
- mPermissionControllerManager);
+ ShadowApplication.getInstance().setSystemService(Context.ROLE_CONTROLLER_SERVICE,
+ mRoleControllerManager);
mController = new DefaultPhoneShortcutPreferenceController(RuntimeEnvironment.application,
TEST_PACKAGE_NAME);
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java
index b31a10d..8626d2d 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java
@@ -18,8 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.role.RoleControllerManager;
import android.content.Context;
-import android.permission.PermissionControllerManager;
import org.junit.Before;
import org.junit.Test;
@@ -37,15 +37,15 @@
private static final String PREFERENCE_KEY = "default_sms_app";
@Mock
- private PermissionControllerManager mPermissionControllerManager;
+ private RoleControllerManager mRoleControllerManager;
private DefaultSmsShortcutPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- ShadowApplication.getInstance().setSystemService(Context.PERMISSION_CONTROLLER_SERVICE,
- mPermissionControllerManager);
+ ShadowApplication.getInstance().setSystemService(Context.ROLE_CONTROLLER_SERVICE,
+ mRoleControllerManager);
mController = new DefaultSmsShortcutPreferenceController(RuntimeEnvironment.application,
TEST_PACKAGE_NAME);
}
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultEmergencyPickerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultEmergencyPickerTest.java
index 5d97f52..b7b046c 100644
--- a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultEmergencyPickerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultEmergencyPickerTest.java
@@ -19,7 +19,6 @@
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.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -27,15 +26,10 @@
import android.app.Activity;
import android.app.role.RoleManager;
-import android.app.role.RoleManagerCallback;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.os.AsyncTask;
-import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings;
-import android.util.Log;
import org.junit.Before;
import org.junit.Test;
@@ -50,6 +44,7 @@
import java.util.Arrays;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
@RunWith(RobolectricTestRunner.class)
public class DefaultEmergencyPickerTest {
@@ -90,7 +85,7 @@
eq(0),
any(UserHandle.class),
any(Executor.class),
- any(RoleManagerCallback.class));
+ any(Consumer.class));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java
index 4347637..eab3dde 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java
@@ -164,7 +164,8 @@
verify(mSummaryPreference).setUsageInfo(info.cycleEnd, now - UPDATE_BACKOFF_MS,
CARRIER_NAME, 1 /* numPlans */, intent);
verify(mSummaryPreference).setChartEnabled(true);
- verify(mSummaryPreference).setWifiMode(false, null);
+ verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */,
+ false /* isSingleWifi */);
}
@Test
@@ -188,7 +189,8 @@
verify(mSummaryPreference).setUsageInfo(info.cycleEnd, now - UPDATE_BACKOFF_MS,
CARRIER_NAME, 0 /* numPlans */, intent);
verify(mSummaryPreference).setChartEnabled(true);
- verify(mSummaryPreference).setWifiMode(false, null);
+ verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */,
+ false /* isSingleWifi */);
}
@Test
@@ -214,7 +216,8 @@
0 /* numPlans */,
null /* launchIntent */);
verify(mSummaryPreference).setChartEnabled(true);
- verify(mSummaryPreference).setWifiMode(false, null);
+ verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */,
+ false /* isSingleWifi */);
}
@Test
@@ -240,7 +243,8 @@
0 /* numPlans */,
null /* launchIntent */);
verify(mSummaryPreference).setChartEnabled(false);
- verify(mSummaryPreference).setWifiMode(false, null);
+ verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */,
+ false /* isSingleWifi */);
}
@Test
@@ -321,7 +325,8 @@
verify(mSummaryPreference).setLimitInfo(captor.capture());
CharSequence value = captor.getValue();
assertThat(value.toString()).isEqualTo("1.00 MB data warning / 1.00 MB data limit");
- verify(mSummaryPreference).setWifiMode(false, null);
+ verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */,
+ false /* isSingleWifi */);
}
@Test
@@ -340,7 +345,8 @@
when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_ABSENT);
mController.updateState(mSummaryPreference);
- verify(mSummaryPreference).setWifiMode(true, info.period);
+ verify(mSummaryPreference).setWifiMode(true /* isWifiMode */, info.period /* usagePeriod */,
+ false /* isSingleWifi */);
verify(mSummaryPreference).setLimitInfo(null);
verify(mSummaryPreference).setUsageNumbers(info.usageLevel, -1L, true);
verify(mSummaryPreference).setChartEnabled(false);
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
index 525b82e..35e6b1d 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
@@ -488,7 +488,7 @@
new Intent());
mSummaryPreference.setUsageNumbers(1000000L, -1L, true);
final String cycleText = "The quick fox";
- mSummaryPreference.setWifiMode(true, cycleText);
+ mSummaryPreference.setWifiMode(true /* isWifiMode */, cycleText, false /* isSingleWifi */);
doReturn(200L).when(mSummaryPreference).getHistoricalUsageLevel();
bindViewHolder();
@@ -524,7 +524,8 @@
@Test
public void testSetWifiMode_noUsageInfo_shouldDisableLaunchButton() {
mSummaryPreference = spy(mSummaryPreference);
- mSummaryPreference.setWifiMode(true, "Test cycle text");
+ mSummaryPreference.setWifiMode(true /* isWifiMode */, "Test cycle text",
+ false /* isSingleWifi */);
doReturn(0L).when(mSummaryPreference).getHistoricalUsageLevel();
bindViewHolder();
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
index 8fae45c..18ddd8a 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
@@ -16,18 +16,14 @@
package com.android.settings.deviceinfo;
-import static android.content.Context.CLIPBOARD_SERVICE;
-
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Answers.RETURNS_DEEP_STUBS;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.app.Activity;
-import android.content.ClipboardManager;
import android.content.Context;
import android.os.Process;
import android.os.UserManager;
@@ -35,7 +31,6 @@
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.core.InstrumentedPreferenceFragment;
@@ -62,13 +57,8 @@
public class BuildNumberPreferenceControllerTest {
private static final String KEY_BUILD_NUMBER = "build_number";
-
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Activity mActivity;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private InstrumentedPreferenceFragment mFragment;
- @Mock(answer = RETURNS_DEEP_STUBS)
- private PreferenceScreen mScreen;
private ShadowUserManager mShadowUserManager;
@@ -200,14 +190,4 @@
assertThat(activityResultHandled).isTrue();
assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isTrue();
}
-
- @Test
- public void copy_shouldCopyBuildNumberToClipboard() {
- mController.copy();
-
- final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
- CLIPBOARD_SERVICE);
- final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
- assertThat(data.toString()).isEqualTo(mController.getSummary());
- }
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceControllerTest.java
new file mode 100644
index 0000000..3784f08
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceControllerTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.firmwareversion;
+
+import static android.content.Context.CLIPBOARD_SERVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ClipboardManager;
+import android.content.Context;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class SimpleBuildNumberPreferenceControllerTest {
+
+ private SimpleBuildNumberPreferenceController mController;
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+
+ mController = new SimpleBuildNumberPreferenceController(mContext, "test");
+ }
+
+ @Test
+ public void copy_shouldCopyBuildNumberToClipboard() {
+ mController.copy();
+
+ final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
+ CLIPBOARD_SERVICE);
+ final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
+ assertThat(data.toString()).isEqualTo(mController.getSummary());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java
index 0103031..d5e0ed8 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java
@@ -65,7 +65,9 @@
private static final String STATUS_NOT_CHARGING = "Not charging";
private static final long REMAINING_TIME_NULL = -1;
private static final long REMAINING_TIME = 2;
+ // Strings are defined in frameworks/base/packages/SettingsLib/res/values/strings.xml
private static final String ENHANCED_STRING_SUFFIX = "based on your usage";
+ private static final String EXTEND_PREFIX = "Extend battery life past";
private static final long TEST_CHARGE_TIME_REMAINING = TimeUnit.MINUTES.toMicros(1);
private static final String TEST_CHARGE_TIME_REMAINING_STRINGIFIED =
"1 min left until fully charged";
@@ -148,8 +150,10 @@
// We only add special mention for the long string
assertThat(info.remainingLabel.toString()).contains(ENHANCED_STRING_SUFFIX);
+ assertThat(info.suggestionLabel).contains(EXTEND_PREFIX);
// shortened string should not have extra text
assertThat(info2.remainingLabel.toString()).doesNotContain(ENHANCED_STRING_SUFFIX);
+ assertThat(info2.suggestionLabel).contains(EXTEND_PREFIX);
}
@Test
@@ -169,6 +173,19 @@
mContext.getString(R.string.power_remaining_duration_only_shutdown_imminent));
assertThat(info2.remainingLabel.toString()).isEqualTo(
mContext.getString(R.string.power_remaining_duration_only_shutdown_imminent));
+ assertThat(info2.suggestionLabel).contains(EXTEND_PREFIX);
+ }
+
+ @Test
+ public void getBatteryInfo_MoreThanOneDay_suggestionLabelIsCorrectString() {
+ Estimate estimate = new Estimate(Duration.ofDays(3).toMillis(),
+ true /* isBasedOnUsage */,
+ 1000 /* averageDischargeTime */);
+ BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
+ mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000,
+ false /* shortString */);
+
+ assertThat(info.suggestionLabel).doesNotContain(EXTEND_PREFIX);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java
new file mode 100644
index 0000000..a441864
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batterysaver;
+
+import static com.android.settings.fuelgauge.batterysaver.BatterySaverStickyPreferenceController.LOW_POWER_STICKY_AUTO_DISABLE_ENABLED;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.Settings;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BatterySaverStickyPreferenceControllerTest {
+
+ private static final String PREF_KEY = "battery_saver_sticky";
+
+ private Context mContext;
+ private BatterySaverStickyPreferenceController mController;
+
+ @Before
+ public void setup() {
+ mContext = RuntimeEnvironment.application;
+ mController = new BatterySaverStickyPreferenceController(mContext, PREF_KEY);
+ }
+
+ private int getAutoDisableSetting() {
+ return Settings.System.getInt(mContext.getContentResolver(),
+ LOW_POWER_STICKY_AUTO_DISABLE_ENABLED,
+ 1);
+ }
+
+ @Test
+ public void testOnPreferenceChange_turnOnKeepActive_autoDisableOff() {
+ mController.onPreferenceChange(null, true);
+ final int isOn = getAutoDisableSetting();
+ assertThat(isOn).isEqualTo(0);
+ }
+
+ @Test
+ public void testOnPreferenceChange_TurnOffKeepActive_autoDisableOff() {
+ mController.onPreferenceChange(null, false);
+ final int isOn = getAutoDisableSetting();
+ assertThat(isOn).isEqualTo(1);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceControllerTest.java
similarity index 61%
copy from tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
copy to tests/robotests/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceControllerTest.java
index e98bdc8..5e6cd55 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceControllerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -16,17 +16,31 @@
package com.android.settings.gestures;
+import static com.android.settings.gestures.SystemNavigationEdgeToEdgePreferenceController.PREF_KEY_EDGE_TO_EDGE;
+import static com.android.settings.gestures.SystemNavigationLegacyPreferenceController.PREF_KEY_LEGACY;
+import static com.android.settings.gestures.SystemNavigationSwipeUpPreferenceController.PREF_KEY_SWIPE_UP;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
import com.android.internal.R;
import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.widget.RadioButtonPreference;
import org.junit.After;
import org.junit.Before;
@@ -40,14 +54,14 @@
@RunWith(RobolectricTestRunner.class)
@Config(shadows = SettingsShadowResources.class)
-public class SwipeUpPreferenceControllerTest {
+public class SystemNavigationEdgeToEdgePreferenceControllerTest {
private Context mContext;
private ShadowPackageManager mPackageManager;
- private SwipeUpPreferenceController mController;
+
+ private SystemNavigationEdgeToEdgePreferenceController mController;
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
- private static final String KEY_SWIPE_UP = "gesture_swipe_up";
@Before
public void setUp() {
@@ -56,8 +70,12 @@
SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, true);
mContext = RuntimeEnvironment.application;
+ Settings.Global.putInt(mContext.getContentResolver(), "prototype_enabled", 1);
+
mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
- mController = new SwipeUpPreferenceController(mContext, KEY_SWIPE_UP);
+
+ mController = new SystemNavigationEdgeToEdgePreferenceController(mContext,
+ PREF_KEY_EDGE_TO_EDGE);
}
@After
@@ -80,7 +98,8 @@
info.serviceInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
mPackageManager.addResolveInfoForIntent(quickStepIntent, info);
- assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isTrue();
+ assertThat(SystemNavigationEdgeToEdgePreferenceController.isGestureAvailable(mContext))
+ .isTrue();
}
@Test
@@ -94,12 +113,14 @@
.setPackage(recentsComponentName.getPackageName());
mPackageManager.addResolveInfoForIntent(quickStepIntent, new ResolveInfo());
- assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isFalse();
+ assertThat(SystemNavigationEdgeToEdgePreferenceController.isGestureAvailable(mContext))
+ .isFalse();
}
@Test
public void testIsGestureAvailable_noMatchingServiceExists_shouldReturnFalse() {
- assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isFalse();
+ assertThat(SystemNavigationEdgeToEdgePreferenceController.isGestureAvailable(mContext))
+ .isFalse();
}
@Test
@@ -109,35 +130,45 @@
@Test
public void testIsChecked_defaultIsFalse_shouldReturnFalse() {
- SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, false);
+ Settings.Global.putInt(mContext.getContentResolver(), "prototype_enabled", 0);
assertThat(mController.isChecked()).isFalse();
}
@Test
- public void testIsChecked_setCheckedTrue_shouldReturnTrue() {
+ public void testIsChecked_radioButtonClicked_shouldReturnTrue() {
// Set the setting to be enabled.
- mController.setChecked(true);
+ mController.onRadioButtonClicked(null);
assertThat(mController.isChecked()).isTrue();
}
@Test
- public void testIsChecked_setCheckedFalse_shouldReturnFalse() {
- // Set the setting to be disabled.
- mController.setChecked(false);
- assertThat(mController.isChecked()).isFalse();
+ public void testOnRadioButtonClicked_setsCorrectRadioButtonChecked() {
+ RadioButtonPreference radioLegacy = mock(RadioButtonPreference.class);
+ RadioButtonPreference radioSwipeUp = mock(RadioButtonPreference.class);
+ RadioButtonPreference radioEdgeToEdge = mock(RadioButtonPreference.class);
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+
+ when(screen.findPreference(PREF_KEY_LEGACY)).thenReturn(radioLegacy);
+ when(screen.findPreference(PREF_KEY_SWIPE_UP)).thenReturn(radioSwipeUp);
+ when(screen.findPreference(PREF_KEY_EDGE_TO_EDGE)).thenReturn(radioEdgeToEdge);
+
+ mController.displayPreference(screen);
+ mController.onRadioButtonClicked(radioEdgeToEdge);
+
+ verify(radioLegacy, times(1)).setChecked(false);
+ verify(radioSwipeUp, times(1)).setChecked(false);
+ verify(radioEdgeToEdge, times(1)).setChecked(true);
}
@Test
public void isSliceableCorrectKey_returnsTrue() {
- final SwipeUpPreferenceController controller =
- new SwipeUpPreferenceController(mContext, "gesture_swipe_up");
- assertThat(controller.isSliceable()).isTrue();
+ assertThat(mController.isSliceable()).isTrue();
}
@Test
public void isSliceableIncorrectKey_returnsFalse() {
- final SwipeUpPreferenceController controller =
- new SwipeUpPreferenceController(mContext, "bad_key");
+ final SystemNavigationEdgeToEdgePreferenceController controller =
+ new SystemNavigationEdgeToEdgePreferenceController(mContext, "bad_key");
assertThat(controller.isSliceable()).isFalse();
}
}
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceControllerTest.java
similarity index 63%
copy from tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
copy to tests/robotests/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceControllerTest.java
index e98bdc8..fe0a061 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceControllerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -16,8 +16,17 @@
package com.android.settings.gestures;
+import static com.android.settings.gestures.SystemNavigationEdgeToEdgePreferenceController.PREF_KEY_EDGE_TO_EDGE;
+import static com.android.settings.gestures.SystemNavigationLegacyPreferenceController.PREF_KEY_LEGACY;
+import static com.android.settings.gestures.SystemNavigationSwipeUpPreferenceController.PREF_KEY_SWIPE_UP;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -25,8 +34,12 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
import com.android.internal.R;
import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.widget.RadioButtonPreference;
import org.junit.After;
import org.junit.Before;
@@ -40,24 +53,25 @@
@RunWith(RobolectricTestRunner.class)
@Config(shadows = SettingsShadowResources.class)
-public class SwipeUpPreferenceControllerTest {
+public class SystemNavigationLegacyPreferenceControllerTest {
private Context mContext;
private ShadowPackageManager mPackageManager;
- private SwipeUpPreferenceController mController;
+
+ private SystemNavigationLegacyPreferenceController mController;
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
- private static final String KEY_SWIPE_UP = "gesture_swipe_up";
@Before
public void setUp() {
SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_setting_available,
true);
- SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, true);
+ SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, false);
mContext = RuntimeEnvironment.application;
mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
- mController = new SwipeUpPreferenceController(mContext, KEY_SWIPE_UP);
+
+ mController = new SystemNavigationLegacyPreferenceController(mContext, PREF_KEY_LEGACY);
}
@After
@@ -80,7 +94,8 @@
info.serviceInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
mPackageManager.addResolveInfoForIntent(quickStepIntent, info);
- assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isTrue();
+ assertThat(SystemNavigationLegacyPreferenceController.isGestureAvailable(mContext))
+ .isTrue();
}
@Test
@@ -94,12 +109,14 @@
.setPackage(recentsComponentName.getPackageName());
mPackageManager.addResolveInfoForIntent(quickStepIntent, new ResolveInfo());
- assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isFalse();
+ assertThat(
+ SystemNavigationLegacyPreferenceController.isGestureAvailable(mContext)).isFalse();
}
@Test
public void testIsGestureAvailable_noMatchingServiceExists_shouldReturnFalse() {
- assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isFalse();
+ assertThat(
+ SystemNavigationLegacyPreferenceController.isGestureAvailable(mContext)).isFalse();
}
@Test
@@ -109,35 +126,46 @@
@Test
public void testIsChecked_defaultIsFalse_shouldReturnFalse() {
- SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, false);
+ // Turn on the Swipe Up mode (2-buttons)
+ SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, true);
assertThat(mController.isChecked()).isFalse();
}
@Test
- public void testIsChecked_setCheckedTrue_shouldReturnTrue() {
+ public void testIsChecked_radioButtonClicked_shouldReturnTrue() {
// Set the setting to be enabled.
- mController.setChecked(true);
+ mController.onRadioButtonClicked(null);
assertThat(mController.isChecked()).isTrue();
}
@Test
- public void testIsChecked_setCheckedFalse_shouldReturnFalse() {
- // Set the setting to be disabled.
- mController.setChecked(false);
- assertThat(mController.isChecked()).isFalse();
+ public void testOnRadioButtonClicked_setsCorrectRadioButtonChecked() {
+ RadioButtonPreference radioLegacy = mock(RadioButtonPreference.class);
+ RadioButtonPreference radioSwipeUp = mock(RadioButtonPreference.class);
+ RadioButtonPreference radioEdgeToEdge = mock(RadioButtonPreference.class);
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+
+ when(screen.findPreference(PREF_KEY_LEGACY)).thenReturn(radioLegacy);
+ when(screen.findPreference(PREF_KEY_SWIPE_UP)).thenReturn(radioSwipeUp);
+ when(screen.findPreference(PREF_KEY_EDGE_TO_EDGE)).thenReturn(radioEdgeToEdge);
+
+ mController.displayPreference(screen);
+ mController.onRadioButtonClicked(radioLegacy);
+
+ verify(radioLegacy, times(1)).setChecked(true);
+ verify(radioSwipeUp, times(1)).setChecked(false);
+ verify(radioEdgeToEdge, times(1)).setChecked(false);
}
@Test
public void isSliceableCorrectKey_returnsTrue() {
- final SwipeUpPreferenceController controller =
- new SwipeUpPreferenceController(mContext, "gesture_swipe_up");
- assertThat(controller.isSliceable()).isTrue();
+ assertThat(mController.isSliceable()).isTrue();
}
@Test
public void isSliceableIncorrectKey_returnsFalse() {
- final SwipeUpPreferenceController controller =
- new SwipeUpPreferenceController(mContext, "bad_key");
+ final SystemNavigationLegacyPreferenceController controller =
+ new SystemNavigationLegacyPreferenceController(mContext, "bad_key");
assertThat(controller.isSliceable()).isFalse();
}
}
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceControllerTest.java
similarity index 63%
rename from tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceControllerTest.java
index e98bdc8..97b4762 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceControllerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -16,8 +16,17 @@
package com.android.settings.gestures;
+import static com.android.settings.gestures.SystemNavigationEdgeToEdgePreferenceController.PREF_KEY_EDGE_TO_EDGE;
+import static com.android.settings.gestures.SystemNavigationLegacyPreferenceController.PREF_KEY_LEGACY;
+import static com.android.settings.gestures.SystemNavigationSwipeUpPreferenceController.PREF_KEY_SWIPE_UP;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -25,8 +34,12 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
import com.android.internal.R;
import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.widget.RadioButtonPreference;
import org.junit.After;
import org.junit.Before;
@@ -40,14 +53,14 @@
@RunWith(RobolectricTestRunner.class)
@Config(shadows = SettingsShadowResources.class)
-public class SwipeUpPreferenceControllerTest {
+public class SystemNavigationSwipeUpPreferenceControllerTest {
private Context mContext;
private ShadowPackageManager mPackageManager;
- private SwipeUpPreferenceController mController;
+
+ private SystemNavigationSwipeUpPreferenceController mController;
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
- private static final String KEY_SWIPE_UP = "gesture_swipe_up";
@Before
public void setUp() {
@@ -57,7 +70,8 @@
mContext = RuntimeEnvironment.application;
mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
- mController = new SwipeUpPreferenceController(mContext, KEY_SWIPE_UP);
+
+ mController = new SystemNavigationSwipeUpPreferenceController(mContext, PREF_KEY_SWIPE_UP);
}
@After
@@ -80,7 +94,8 @@
info.serviceInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
mPackageManager.addResolveInfoForIntent(quickStepIntent, info);
- assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isTrue();
+ assertThat(SystemNavigationSwipeUpPreferenceController.isGestureAvailable(mContext))
+ .isTrue();
}
@Test
@@ -94,12 +109,14 @@
.setPackage(recentsComponentName.getPackageName());
mPackageManager.addResolveInfoForIntent(quickStepIntent, new ResolveInfo());
- assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isFalse();
+ assertThat(SystemNavigationSwipeUpPreferenceController.isGestureAvailable(mContext))
+ .isFalse();
}
@Test
public void testIsGestureAvailable_noMatchingServiceExists_shouldReturnFalse() {
- assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isFalse();
+ assertThat(SystemNavigationSwipeUpPreferenceController.isGestureAvailable(mContext))
+ .isFalse();
}
@Test
@@ -114,30 +131,40 @@
}
@Test
- public void testIsChecked_setCheckedTrue_shouldReturnTrue() {
+ public void testIsChecked_radioButtonClicked_shouldReturnTrue() {
// Set the setting to be enabled.
- mController.setChecked(true);
+ mController.onRadioButtonClicked(null);
assertThat(mController.isChecked()).isTrue();
}
@Test
- public void testIsChecked_setCheckedFalse_shouldReturnFalse() {
- // Set the setting to be disabled.
- mController.setChecked(false);
- assertThat(mController.isChecked()).isFalse();
+ public void testOnRadioButtonClicked_setsCorrectRadioButtonChecked() {
+ RadioButtonPreference radioLegacy = mock(RadioButtonPreference.class);
+ RadioButtonPreference radioSwipeUp = mock(RadioButtonPreference.class);
+ RadioButtonPreference radioEdgeToEdge = mock(RadioButtonPreference.class);
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+
+ when(screen.findPreference(PREF_KEY_LEGACY)).thenReturn(radioLegacy);
+ when(screen.findPreference(PREF_KEY_SWIPE_UP)).thenReturn(radioSwipeUp);
+ when(screen.findPreference(PREF_KEY_EDGE_TO_EDGE)).thenReturn(radioEdgeToEdge);
+
+ mController.displayPreference(screen);
+ mController.onRadioButtonClicked(radioSwipeUp);
+
+ verify(radioLegacy, times(1)).setChecked(false);
+ verify(radioSwipeUp, times(1)).setChecked(true);
+ verify(radioEdgeToEdge, times(1)).setChecked(false);
}
@Test
public void isSliceableCorrectKey_returnsTrue() {
- final SwipeUpPreferenceController controller =
- new SwipeUpPreferenceController(mContext, "gesture_swipe_up");
- assertThat(controller.isSliceable()).isTrue();
+ assertThat(mController.isSliceable()).isTrue();
}
@Test
public void isSliceableIncorrectKey_returnsFalse() {
- final SwipeUpPreferenceController controller =
- new SwipeUpPreferenceController(mContext, "bad_key");
+ final SystemNavigationSwipeUpPreferenceController controller =
+ new SystemNavigationSwipeUpPreferenceController(mContext, "bad_key");
assertThat(controller.isSliceable()).isFalse();
}
}
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 8b04ef3..40e6939 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -22,7 +22,7 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -87,6 +87,19 @@
}
@Test
+ public void isCardEligibleToDisplay_invalidRankingScore_returnFalse() {
+ final ContextualCard card = new ContextualCard.Builder()
+ .setName("test_card")
+ .setCardType(ContextualCard.CardType.SLICE)
+ .setSliceUri(CustomSliceRegistry.FLASHLIGHT_SLICE_URI)
+ .setRankingScore(-1)
+ .build();
+
+ assertThat(mEligibleCardChecker.isCardEligibleToDisplay(card))
+ .isFalse();
+ }
+
+ @Test
public void isCardEligibleToDisplay_nullSlice_returnFalse() {
doReturn(null).when(mEligibleCardChecker).bindSlice(Uri.parse(TEST_SLICE_URI));
@@ -108,7 +121,7 @@
public void getDisplayableCards_twoEligibleCards_shouldShowAll() {
final List<ContextualCard> cards = getContextualCardList().stream().limit(2)
.collect(Collectors.toList());
- doReturn(cards).when(mContextualCardLoader).filterEligibleCards(any(List.class));
+ doReturn(cards).when(mContextualCardLoader).filterEligibleCards(anyList());
final List<ContextualCard> result = mContextualCardLoader.getDisplayableCards(cards);
@@ -118,7 +131,7 @@
@Test
public void getDisplayableCards_fiveEligibleCardsNoLarge_shouldShowDefaultCardCount() {
final List<ContextualCard> fiveCards = getContextualCardListWithNoLargeCard();
- doReturn(fiveCards).when(mContextualCardLoader).filterEligibleCards(any(List.class));
+ doReturn(fiveCards).when(mContextualCardLoader).filterEligibleCards(anyList());
final List<ContextualCard> result = mContextualCardLoader.getDisplayableCards(
fiveCards);
@@ -136,7 +149,7 @@
.setSliceUri(Uri.parse(
"content://com.android.settings.test.slices/action/gesture_pick_up"))
.build());
- doReturn(cards).when(mContextualCardLoader).filterEligibleCards(any(List.class));
+ doReturn(cards).when(mContextualCardLoader).filterEligibleCards(anyList());
final List<ContextualCard> result = mContextualCardLoader.getDisplayableCards(cards);
@@ -147,7 +160,7 @@
public void getDisplayableCards_threeEligibleCardsTwoLarge_shouldShowTwoCards() {
final List<ContextualCard> threeCards = getContextualCardList().stream().limit(3)
.collect(Collectors.toList());
- doReturn(threeCards).when(mContextualCardLoader).filterEligibleCards(any(List.class));
+ doReturn(threeCards).when(mContextualCardLoader).filterEligibleCards(anyList());
final List<ContextualCard> result = mContextualCardLoader.getDisplayableCards(
threeCards);
@@ -167,25 +180,26 @@
public void getDisplayableCards_refreshCardUri_shouldLogContextualCardDisplay() {
mContextualCardLoader.mNotifyUri = CardContentProvider.REFRESH_CARD_URI;
- mContextualCardLoader.getDisplayableCards(new ArrayList<ContextualCard>());
+ mContextualCardLoader.getDisplayableCards(new ArrayList<>());
verify(mFakeFeatureFactory.mContextualCardFeatureProvider).logContextualCardDisplay(
- any(List.class), any(List.class));
+ anyList(), anyList());
}
@Test
public void getDisplayableCards_deleteCardUri_shouldNotLogContextualCardDisplay() {
mContextualCardLoader.mNotifyUri = CardContentProvider.DELETE_CARD_URI;
- mContextualCardLoader.getDisplayableCards(new ArrayList<ContextualCard>());
+ mContextualCardLoader.getDisplayableCards(new ArrayList<>());
verify(mFakeFeatureFactory.mContextualCardFeatureProvider, never())
- .logContextualCardDisplay(any(List.class), any(List.class));
+ .logContextualCardDisplay(anyList(), anyList());
}
private ContextualCard getContextualCard(String sliceUri) {
return new ContextualCard.Builder()
.setName("test_card")
+ .setRankingScore(0.5)
.setCardType(ContextualCard.CardType.SLICE)
.setSliceUri(Uri.parse(sliceUri))
.build();
@@ -215,11 +229,6 @@
.setSliceUri(Uri.parse(
"content://com.android.settings.test.slices/action/gesture_pick_up"))
.build());
- cards.add(new ContextualCard.Builder()
- .setName("test_battery")
- .setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
- .build());
return cards;
}
@@ -248,11 +257,6 @@
.setSliceUri(Uri.parse(
"content://com.android.settings.test.slices/action/gesture_pick_up"))
.build());
- cards.add(new ContextualCard.Builder()
- .setName("test_battery")
- .setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
- .build());
return cards;
}
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
index 1a0539c..8087716 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
@@ -31,6 +31,7 @@
import android.content.Context;
import android.net.Uri;
+import android.provider.Settings;
import android.util.ArrayMap;
import com.android.settings.homepage.contextualcards.conditional.ConditionFooterContextualCard;
@@ -126,6 +127,24 @@
}
@Test
+ public void getCardLoaderTimeout_noConfiguredTimeout_shouldReturnDefaultTimeout() {
+ final long timeout = mManager.getCardLoaderTimeout(mContext);
+
+ assertThat(timeout).isEqualTo(ContextualCardManager.CARD_CONTENT_LOADER_TIMEOUT_MS);
+ }
+
+ @Test
+ public void getCardLoaderTimeout_hasConfiguredTimeout_shouldReturnConfiguredTimeout() {
+ final long configuredTimeout = 5000L;
+ Settings.Global.putLong(mContext.getContentResolver(),
+ ContextualCardManager.KEY_GLOBAL_CARD_LOADER_TIMEOUT, configuredTimeout);
+
+ final long timeout = mManager.getCardLoaderTimeout(mContext);
+
+ assertThat(timeout).isEqualTo(configuredTimeout);
+ }
+
+ @Test
public void onFinishCardLoading_fastLoad_shouldCallOnContextualCardUpdated() {
mManager.mStartTime = System.currentTimeMillis();
final ContextualCardManager manager = spy(mManager);
@@ -441,7 +460,7 @@
cards.add(new ContextualCard.Builder()
.setName("test_battery")
.setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
+ .setSliceUri(CustomSliceRegistry.BATTERY_FIX_SLICE_URI)
.setViewType(VIEW_TYPE_FULL_WIDTH)
.build());
return cards;
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSliceTest.java
deleted file mode 100644
index ff276d6..0000000
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/deviceinfo/BatteryInfoSliceTest.java
+++ /dev/null
@@ -1,75 +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.deviceinfo;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-
-import android.content.Context;
-
-import androidx.core.graphics.drawable.IconCompat;
-import androidx.slice.Slice;
-import androidx.slice.SliceMetadata;
-import androidx.slice.SliceProvider;
-import androidx.slice.core.SliceAction;
-import androidx.slice.widget.SliceLiveData;
-
-import com.android.settings.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class BatteryInfoSliceTest {
-
- private Context mContext;
- private BatteryInfoSlice mBatteryInfoSlice;
-
- @Before
- public void setUp() {
- mContext = RuntimeEnvironment.application;
-
- // Set-up specs for SliceMetadata.
- SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
-
- mBatteryInfoSlice = spy(new BatteryInfoSlice(mContext));
- }
-
- @Test
- public void getSlice_shouldBeCorrectSliceContent() {
- doNothing().when(mBatteryInfoSlice).loadBatteryInfo();
- doReturn("10%").when(mBatteryInfoSlice).getBatteryPercentString();
- doReturn("test").when(mBatteryInfoSlice).getSummary();
-
- final Slice slice = mBatteryInfoSlice.getSlice();
-
- final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
- assertThat(metadata.getTitle()).isEqualTo(
- mContext.getString(R.string.power_usage_summary_title));
-
- final SliceAction primaryAction = metadata.getPrimaryAction();
- final IconCompat expectedIcon = IconCompat.createWithResource(mContext,
- R.drawable.ic_settings_battery);
- assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedIcon.toString());
- }
-}
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
index 77fc5d9..4a23c33 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -83,7 +84,7 @@
// Mock the icon and detail intent of Bluetooth.
mIcon = IconCompat.createWithResource(mContext,
- com.android.internal.R.drawable.ic_settings_bluetooth);
+ com.android.internal.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());
@@ -122,6 +123,27 @@
}
@Test
+ public void getSlice_hasMediaBluetoothDevice_shouldBuildMediaBluetoothAction() {
+ mockBluetoothDeviceList(1 /* deviceCount */);
+ doReturn(true).when(mBluetoothDeviceList.get(0)).isConnectedA2dpDevice();
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
+
+ mBluetoothDevicesSlice.getSlice();
+
+ verify(mBluetoothDevicesSlice).buildMediaBluetoothAction(any());
+ }
+
+ @Test
+ public void getSlice_noMediaBluetoothDevice_shouldNotBuildMediaBluetoothAction() {
+ mockBluetoothDeviceList(1 /* deviceCount */);
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
+
+ mBluetoothDevicesSlice.getSlice();
+
+ verify(mBluetoothDevicesSlice, never()).buildMediaBluetoothAction(any());
+ }
+
+ @Test
public void getSlice_noBluetoothDevices_shouldHaveNoBluetoothDevicesTitle() {
doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
@@ -175,7 +197,6 @@
doReturn(BLUETOOTH_MOCK_TITLE).when(mCachedBluetoothDevice).getName();
doReturn(BLUETOOTH_MOCK_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary();
doReturn(BLUETOOTH_MOCK_ADDRESS).when(mCachedBluetoothDevice).getAddress();
- doReturn(true).when(mCachedBluetoothDevice).isConnectedA2dpDevice();
for (int i = 0; i < deviceCount; i++) {
mBluetoothDeviceList.add(mCachedBluetoothDevice);
}
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
index daaba90..da0d85b 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
@@ -21,21 +21,15 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
-import android.util.IconDrawableFactory;
import androidx.slice.Slice;
import androidx.slice.SliceMetadata;
@@ -43,6 +37,7 @@
import androidx.slice.core.SliceAction;
import androidx.slice.widget.SliceLiveData;
+import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settingslib.media.LocalMediaManager;
import com.android.settingslib.media.MediaDevice;
@@ -53,70 +48,64 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
public class MediaOutputSliceTest {
private static final String TEST_PACKAGE_NAME = "com.fake.android.music";
- private static final String TEST_LABEL = "Test app";
private static final String TEST_DEVICE_1_ID = "test_device_1_id";
+ private static final String TEST_DEVICE_1_NAME = "test_device_1_name";
+ private static final int TEST_DEVICE_1_ICON =
+ com.android.internal.R.drawable.ic_bt_headphones_a2dp;
@Mock
- private PackageManager mPackageManager;
- @Mock
- private ApplicationInfo mApplicationInfo;
- @Mock
- private ApplicationInfo mApplicationInfo2;
- @Mock
private LocalMediaManager mLocalMediaManager;
- @Mock
- private IconDrawableFactory mIconDrawableFactory;
- @Mock
- private Drawable mTestDrawable;
private final List<MediaDevice> mDevices = new ArrayList<>();
private Context mContext;
private MediaOutputSlice mMediaOutputSlice;
private MediaDeviceUpdateWorker mMediaDeviceUpdateWorker;
+ private ShadowBluetoothAdapter mShadowBluetoothAdapter;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- when(mContext.getPackageManager()).thenReturn(mPackageManager);
- when(mPackageManager.getApplicationInfo(eq(TEST_PACKAGE_NAME), anyInt()))
- .thenReturn(mApplicationInfo);
- when(mPackageManager.getApplicationInfoAsUser(eq(TEST_PACKAGE_NAME), anyInt(), anyInt()))
- .thenReturn(mApplicationInfo2);
- when(mApplicationInfo.loadLabel(mPackageManager)).thenReturn(TEST_LABEL);
- when(mIconDrawableFactory.getBadgedIcon(mApplicationInfo2, UserHandle.myUserId()))
- .thenReturn(mTestDrawable);
- when(mTestDrawable.getIntrinsicWidth()).thenReturn(100);
- when(mTestDrawable.getIntrinsicHeight()).thenReturn(100);
-
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+ // Setup BluetoothAdapter
+ mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+ mShadowBluetoothAdapter.setEnabled(true);
mMediaOutputSlice = new MediaOutputSlice(mContext);
mMediaDeviceUpdateWorker = new MediaDeviceUpdateWorker(mContext, MEDIA_OUTPUT_SLICE_URI);
mMediaDeviceUpdateWorker.setPackageName(TEST_PACKAGE_NAME);
mMediaDeviceUpdateWorker.onDeviceListUpdate(mDevices);
mMediaDeviceUpdateWorker.mLocalMediaManager = mLocalMediaManager;
- mMediaOutputSlice.init(TEST_PACKAGE_NAME, mMediaDeviceUpdateWorker, mIconDrawableFactory);
+ mMediaOutputSlice.init(TEST_PACKAGE_NAME, mMediaDeviceUpdateWorker);
}
@Test
- public void getSlice_shouldHaveAppTitle() {
+ public void getSlice_shouldHaveActiveDeviceName() {
+ mDevices.clear();
+ final MediaDevice device = mock(MediaDevice.class);
+ when(device.getName()).thenReturn(TEST_DEVICE_1_NAME);
+ when(device.getIcon()).thenReturn(TEST_DEVICE_1_ICON);
+ when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(device);
+
final Slice mediaSlice = mMediaOutputSlice.getSlice();
final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice);
final SliceAction primaryAction = metadata.getPrimaryAction();
- assertThat(primaryAction.getTitle().toString()).isEqualTo(TEST_LABEL);
+ assertThat(primaryAction.getTitle().toString()).isEqualTo(TEST_DEVICE_1_NAME);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.java
index 2135331..e04262f 100644
--- a/tests/robotests/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/TopLevelNetworkEntryPreferenceControllerTest.java
@@ -16,6 +16,8 @@
package com.android.settings.network;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
@@ -24,8 +26,10 @@
import android.os.UserManager;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
+import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settings.wifi.WifiMasterSwitchPreferenceController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,7 +43,7 @@
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
-@Config(shadows = ShadowRestrictedLockUtilsInternal.class)
+@Config(shadows = {ShadowRestrictedLockUtilsInternal.class, ShadowUtils.class})
public class TopLevelNetworkEntryPreferenceControllerTest {
@Mock
@@ -70,6 +74,17 @@
mTetherPreferenceController);
}
+ @After
+ public void tearDown() {
+ ShadowUtils.reset();
+ }
+
+ @Test
+ public void getAvailabilityStatus_demoUser_unsupported() {
+ ShadowUtils.setIsDemoUser(true);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
@Test
public void getSummary_hasMobileAndHotspot_shouldReturnMobileSummary() {
when(mWifiPreferenceController.isAvailable()).thenReturn(true);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
index 072c835..a9882d9 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
@@ -22,7 +22,6 @@
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;
@@ -43,7 +42,6 @@
import com.android.ims.ImsManager;
import com.android.settings.R;
-import com.android.settings.slices.CustomSliceManager;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
@@ -85,10 +83,6 @@
mFeatureFactory = FakeFeatureFactory.setupForTest();
mSlicesFeatureProvider = mFeatureFactory.getSlicesFeatureProvider();
- CustomSliceManager manager = new CustomSliceManager(mContext);
- when(mSlicesFeatureProvider.getCustomSliceManager(any(Context.class)))
- .thenReturn(manager);
-
//setup for SettingsSliceProvider tests
mProvider = spy(new SettingsSliceProvider());
doReturn(mContext).when(mProvider).getContext();
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java
index c497cf8..e488d0c 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
@@ -162,4 +163,27 @@
assertThat(isMobileDataEnabled).isEqualTo(seed);
}
+
+ @Test
+ public void airplaneModeEnabled_slicePrimaryActionIsEmpty() {
+ doReturn(true).when(mMobileDataSlice).isAirplaneModeEnabled();
+ doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
+ final Slice mobileData = mMobileDataSlice.getSlice();
+
+ final SliceMetadata metadata = SliceMetadata.from(mContext, mobileData);
+ assertThat(metadata.getTitle())
+ .isEqualTo(mContext.getString(R.string.mobile_data_settings_title));
+
+ assertThat(metadata.getSubtitle())
+ .isEqualTo(mContext.getString(R.string.mobile_data_ap_mode_disabled));
+
+ final List<SliceAction> toggles = metadata.getToggles();
+ assertThat(toggles).hasSize(0);
+
+ final SliceAction primaryAction = metadata.getPrimaryAction();
+ final PendingIntent pendingIntent = primaryAction.getAction();
+ final Intent actionIntent = pendingIntent.getIntent();
+
+ assertThat(actionIntent).isNull();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
index 55a4224..011bca5 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
@@ -30,6 +30,8 @@
import android.provider.Settings;
import android.telephony.TelephonyManager;
+import androidx.fragment.app.FragmentActivity;
+
import com.android.settings.core.FeatureFlags;
import com.android.settings.datausage.DataUsageSummaryPreferenceController;
import com.android.settings.development.featureflags.FeatureFlagPersistent;
@@ -48,8 +50,6 @@
import java.util.List;
-import androidx.fragment.app.FragmentActivity;
-
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowEntityHeaderController.class)
public class MobileNetworkSettingsTest {
@@ -86,6 +86,7 @@
@Test
public void onAttach_noV2Flag_noCrash() {
+ FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, false);
mFragment.onAttach(mContext);
}
@@ -97,6 +98,7 @@
@Test
public void createPreferenceControllers_noV2Flag_noDataUsageSummaryController() {
+ FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, false);
final List<AbstractPreferenceController> controllers =
mFragment.createPreferenceControllers(mContext);
assertThat(controllers.stream().filter(
diff --git a/tests/robotests/src/com/android/settings/notification/AppNotificationSettingsTest.java b/tests/robotests/src/com/android/settings/notification/AppNotificationSettingsTest.java
new file mode 100644
index 0000000..9555a56
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/AppNotificationSettingsTest.java
@@ -0,0 +1,93 @@
+package com.android.settings.notification;
+
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.view.Window;
+import android.view.WindowManager;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@RunWith(RobolectricTestRunner.class)
+public class AppNotificationSettingsTest {
+
+ private WindowManager.LayoutParams mLayoutParams;
+ private AppNotificationSettings mFragment;
+ private FragmentActivity mActivity;
+ @Mock
+ private Window mWindow;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mActivity = spy(Robolectric.setupActivity(FragmentActivity.class));
+ mFragment = spy(new AppNotificationSettings());
+ when(mFragment.getActivity()).thenReturn(mActivity);
+ when(mFragment.getFragmentManager()).thenReturn(mock(FragmentManager.class));
+ when(mActivity.getWindow()).thenReturn(mWindow);
+ when(mWindow.getAttributes()).thenReturn(mLayoutParams);
+ }
+
+ @Test
+ @Config(shadows = {ShadowNotificationSettingsBase.class})
+ public void onResume_shouldHideSystemOverlay() {
+ mFragment.onResume();
+
+ verify(mWindow).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ }
+
+ @Test
+ @Config(shadows = {ShadowNotificationSettingsBase.class})
+ public void onPause_shouldRemoveHideSystemOverlay() {
+ mFragment.onResume();
+
+ verify(mWindow).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+
+ mFragment.onPause();
+
+ // There's no Window.clearPrivateFlags() method, so the Window.attributes are updated.
+ ArgumentCaptor<WindowManager.LayoutParams> paramCaptor = ArgumentCaptor.forClass(
+ WindowManager.LayoutParams.class);
+ verify(mWindow).setAttributes(paramCaptor.capture());
+ assertEquals(0,
+ paramCaptor.getValue().privateFlags
+ & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ }
+
+ @Implements(NotificationSettingsBase.class)
+ public static class ShadowNotificationSettingsBase {
+
+ protected void __constructor__() {
+ // Do nothing
+ }
+
+ @Implementation
+ protected void onResume() {
+ // No-op.
+ }
+
+ @Implementation
+ protected void onPause() {
+ // No-op.
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/panel/NfcPanelTest.java b/tests/robotests/src/com/android/settings/panel/NfcPanelTest.java
index bf6662d..1de2c5a 100644
--- a/tests/robotests/src/com/android/settings/panel/NfcPanelTest.java
+++ b/tests/robotests/src/com/android/settings/panel/NfcPanelTest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2019 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.panel;
import static com.google.common.truth.Truth.assertThat;
diff --git a/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java b/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
index a51b7b0..1d5c3c2 100644
--- a/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
+++ b/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
@@ -76,15 +76,16 @@
}
@Test
- public void startMediaOutputSlice_withoutPackageName_bundleShouldNotHaveValue() {
+ public void startMediaOutputSlice_withoutPackageName_bundleShouldHaveValue() {
final Intent intent = new Intent()
.setAction("com.android.settings.panel.action.MEDIA_OUTPUT");
final SettingsPanelActivity activity =
Robolectric.buildActivity(SettingsPanelActivity.class, intent).create().get();
- assertThat(activity.mBundle.containsKey(KEY_MEDIA_PACKAGE_NAME)).isFalse();
- assertThat(activity.mBundle.containsKey(KEY_PANEL_TYPE_ARGUMENT)).isFalse();
+ assertThat(activity.mBundle.containsKey(KEY_MEDIA_PACKAGE_NAME)).isTrue();
+ assertThat(activity.mBundle.getString(KEY_PANEL_TYPE_ARGUMENT))
+ .isEqualTo("com.android.settings.panel.action.MEDIA_OUTPUT");
}
@Test
diff --git a/tests/robotests/src/com/android/settings/panel/WifiPanelTest.java b/tests/robotests/src/com/android/settings/panel/WifiPanelTest.java
new file mode 100644
index 0000000..08db23e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/WifiPanelTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 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.panel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+
+import com.android.settings.slices.CustomSliceRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class WifiPanelTest {
+
+ private WifiPanel mPanel;
+
+ @Before
+ public void setUp() {
+ mPanel = WifiPanel.create(RuntimeEnvironment.application);
+ }
+
+ @Test
+ public void getSlices_containsNecessarySlices() {
+ final List<Uri> uris = mPanel.getSlices();
+
+ assertThat(uris).containsExactly(
+ CustomSliceRegistry.WIFI_SLICE_URI);
+ }
+
+ @Test
+ public void getSeeMoreIntent_notNull() {
+ assertThat(mPanel.getSeeMoreIntent()).isNotNull();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java b/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java
index 48f9fb4..bed09cb 100644
--- a/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java
@@ -16,7 +16,7 @@
package com.android.settings.password;
-import static android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY;
+import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
import static android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY;
@@ -139,7 +139,7 @@
public void testLaunchChooseLock_setNewPasswordExtraWithPermission() {
ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME);
- ShadowPasswordUtils.addGrantedPermission(REQUEST_SCREEN_LOCK_COMPLEXITY);
+ ShadowPasswordUtils.addGrantedPermission(REQUEST_PASSWORD_COMPLEXITY);
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
@@ -169,7 +169,7 @@
public void testLaunchChooseLock_setNewPasswordExtraInvalidValue() {
ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME);
- ShadowPasswordUtils.addGrantedPermission(REQUEST_SCREEN_LOCK_COMPLEXITY);
+ ShadowPasswordUtils.addGrantedPermission(REQUEST_PASSWORD_COMPLEXITY);
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
@@ -197,7 +197,7 @@
public void testLaunchChooseLock_setNewPasswordExtraNoneComplexity() {
ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME);
- ShadowPasswordUtils.addGrantedPermission(REQUEST_SCREEN_LOCK_COMPLEXITY);
+ ShadowPasswordUtils.addGrantedPermission(REQUEST_PASSWORD_COMPLEXITY);
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
@@ -225,7 +225,7 @@
public void testLaunchChooseLock_setNewPasswordWithoutExtra() {
ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME);
- ShadowPasswordUtils.addGrantedPermission(REQUEST_SCREEN_LOCK_COMPLEXITY);
+ ShadowPasswordUtils.addGrantedPermission(REQUEST_PASSWORD_COMPLEXITY);
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
@@ -252,7 +252,7 @@
public void testLaunchChooseLock_setNewParentProfilePasswordExtraWithPermission() {
ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME);
- ShadowPasswordUtils.addGrantedPermission(REQUEST_SCREEN_LOCK_COMPLEXITY);
+ ShadowPasswordUtils.addGrantedPermission(REQUEST_PASSWORD_COMPLEXITY);
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
@@ -280,7 +280,7 @@
public void testLaunchChooseLock_setNewParentProfilePasswordWithoutExtra() {
ShadowPasswordUtils.setCallingAppLabel(APP_LABEL);
ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME);
- ShadowPasswordUtils.addGrantedPermission(REQUEST_SCREEN_LOCK_COMPLEXITY);
+ ShadowPasswordUtils.addGrantedPermission(REQUEST_PASSWORD_COMPLEXITY);
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockGenericTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockGenericTest.java
index d35b38a..cd79f58 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockGenericTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockGenericTest.java
@@ -16,7 +16,7 @@
package com.android.settings.password;
-import static android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY;
+import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
@@ -68,7 +68,7 @@
@Test
@Config(shadows = {ShadowPasswordUtils.class})
public void setupChooseLockGenericPasswordComplexityExtraWithPermission() {
- ShadowPasswordUtils.addGrantedPermission(REQUEST_SCREEN_LOCK_COMPLEXITY);
+ ShadowPasswordUtils.addGrantedPermission(REQUEST_PASSWORD_COMPLEXITY);
Intent intent = new Intent("com.android.settings.SETUP_LOCK_SCREEN");
intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_HIGH);
diff --git a/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java
new file mode 100644
index 0000000..a379858
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 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.privacy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class EnableContentCapturePreferenceControllerTest {
+
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private EnableContentCapturePreferenceController mController;
+ private Preference mPreference;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new EnableContentCapturePreferenceController(mContext);
+ mPreference = new Preference(mContext);
+ mPreference.setKey(mController.getPreferenceKey());
+ }
+
+ @Test
+ public void isChecked_settingIsOff_false() throws Exception {
+ setProperty(0);
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void isChecked_settingIsOn_true() throws Exception {
+ setProperty(1);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void changePref_turnOn_shouldChangeSettingTo1() throws Exception {
+ setProperty(0);
+
+ mController.onPreferenceChange(mPreference, true);
+
+ assertThat(mController.isChecked()).isTrue();
+ assertProperty(1);
+ }
+
+ @Test
+ public void changePref_turnOff_shouldChangeSettingTo0() throws Exception {
+ setProperty(1);
+
+ mController.onPreferenceChange(mPreference, false);
+
+ assertThat(mController.isChecked()).isFalse();
+ assertProperty(0);
+ }
+
+ private void setProperty(int newValue) throws SettingNotFoundException {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Secure.putInt(contentResolver, Settings.Secure.CONTENT_CAPTURE_ENABLED, newValue);
+ }
+
+ private void assertProperty(int expectedValue) throws SettingNotFoundException {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ assertThat(Settings.Secure.getInt(contentResolver, Settings.Secure.CONTENT_CAPTURE_ENABLED))
+ .isEqualTo(expectedValue);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/slices/SpecialCaseSliceManagerTest.java b/tests/robotests/src/com/android/settings/slices/SpecialCaseSliceManagerTest.java
index 82726df..5392284 100644
--- a/tests/robotests/src/com/android/settings/slices/SpecialCaseSliceManagerTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SpecialCaseSliceManagerTest.java
@@ -47,8 +47,8 @@
public void setUp() {
mContext = RuntimeEnvironment.application;
mCustomSliceManager = spy(new CustomSliceManager(mContext));
- mCustomSliceManager.mUriMap.clear();
- mCustomSliceManager.mUriMap.put(FakeSliceable.URI, FakeSliceable.class);
+ CustomSliceRegistry.sUriToSlice.clear();
+ CustomSliceRegistry.sUriToSlice.put(FakeSliceable.URI, FakeSliceable.class);
}
@Test
@@ -69,14 +69,14 @@
@Test
public void isValidUri_validUri_returnsTrue() {
- final boolean isValidUri = mCustomSliceManager.isValidUri(FakeSliceable.URI);
+ final boolean isValidUri = CustomSliceRegistry.isValidUri(FakeSliceable.URI);
assertThat(isValidUri).isTrue();
}
@Test
public void isValidUri_invalidUri_returnsFalse() {
- final boolean isValidUri = mCustomSliceManager.isValidUri(null);
+ final boolean isValidUri = CustomSliceRegistry.isValidUri(null);
assertThat(isValidUri).isFalse();
}
@@ -84,14 +84,14 @@
@Test
public void isValidAction_validActions_returnsTrue() {
final boolean isValidAction =
- mCustomSliceManager.isValidAction(FakeSliceable.URI.toString());
+ CustomSliceRegistry.isValidAction(FakeSliceable.URI.toString());
assertThat(isValidAction).isTrue();
}
@Test
public void isValidAction_invalidAction_returnsFalse() {
- final boolean isValidAction = mCustomSliceManager.isValidAction("action");
+ final boolean isValidAction = CustomSliceRegistry.isValidAction("action");
assertThat(isValidAction).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java
index 54a79f4..5b7c863 100644
--- a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java
@@ -238,63 +238,6 @@
verify(mLocalBluetoothManager).setForegroundActivity(null);
}
- @Test
- public void onPreferenceChange_toThisDevice_shouldSetDefaultSummary() {
- mController.mConnectedDevices.clear();
- mController.mConnectedDevices.add(mBluetoothDevice);
-
- mController.onPreferenceChange(mPreference,
- mContext.getText(R.string.media_output_default_summary));
-
- assertThat(mPreference.getSummary()).isEqualTo(
- mContext.getText(R.string.media_output_default_summary));
- }
-
- /**
- * One Bluetooth devices are available, and select the device.
- * Preference summary should be device name.
- */
- @Test
- public void onPreferenceChange_toBtDevice_shouldSetBtDeviceName() {
- mController.mConnectedDevices.clear();
- mController.mConnectedDevices.add(mBluetoothDevice);
-
- mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1);
-
- assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1);
- }
-
- /**
- * More than one Bluetooth devices are available, and select second device.
- * Preference summary should be second device name.
- */
- @Test
- public void onPreferenceChange_toBtDevices_shouldSetSecondBtDeviceName() {
- ShadowBluetoothDevice shadowBluetoothDevice;
- BluetoothDevice secondBluetoothDevice;
- secondBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2);
- shadowBluetoothDevice = Shadows.shadowOf(secondBluetoothDevice);
- shadowBluetoothDevice.setName(TEST_DEVICE_NAME_2);
- mController.mConnectedDevices.clear();
- mController.mConnectedDevices.add(mBluetoothDevice);
- mController.mConnectedDevices.add(secondBluetoothDevice);
-
- mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_2);
-
- assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2);
- }
-
- /**
- * mConnectedDevices is empty.
- * onPreferenceChange should return false.
- */
- @Test
- public void onPreferenceChange_connectedDeviceIsNull_shouldReturnFalse() {
- mController.mConnectedDevices.clear();
-
- assertThat(mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1)).isFalse();
- }
-
/**
* Audio stream output to bluetooth sco headset which is the subset of all sco device.
* isStreamFromOutputDevice should return true.
@@ -416,39 +359,6 @@
}
/**
- * One A2dp device is connected.
- * getConnectedA2dpDevices should add this device to list.
- */
- @Test
- public void getConnectedA2dpDevices_oneConnectedA2dpDevice_shouldAddDeviceToList() {
- mEmptyDevices.clear();
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mBluetoothDevice);
- when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
-
- mEmptyDevices.addAll(mController.getConnectedA2dpDevices());
-
- assertThat(mEmptyDevices).containsExactly(mBluetoothDevice);
- }
-
- /**
- * More than one A2dp devices are connected.
- * getConnectedA2dpDevices should add all devices to list.
- */
- @Test
- public void getConnectedA2dpDevices_moreThanOneConnectedA2dpDevice_shouldAddDeviceToList() {
- mEmptyDevices.clear();
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mBluetoothDevice);
- mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
- when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
-
- mEmptyDevices.addAll(mController.getConnectedA2dpDevices());
-
- assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mLeftBluetoothHapDevice);
- }
-
- /**
* One hands free profile device is connected.
* getConnectedA2dpDevices should add this device to list.
*/
@@ -488,10 +398,6 @@
}
@Override
- public void setActiveBluetoothDevice(BluetoothDevice device) {
- }
-
- @Override
public BluetoothDevice findActiveDevice() {
return null;
}
diff --git a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
index 4010145..0eada60 100644
--- a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
@@ -57,6 +57,7 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowBluetoothDevice;
@@ -107,7 +108,7 @@
private BluetoothDevice mLeftBluetoothHapDevice;
private BluetoothDevice mRightBluetoothHapDevice;
private LocalBluetoothManager mLocalBluetoothManager;
- private AudioSwitchPreferenceController mController;
+ private HandsFreeProfileOutputPreferenceController mController;
private List<BluetoothDevice> mProfileConnectedDevices;
private List<BluetoothDevice> mHearingAidActiveDevices;
@@ -478,4 +479,61 @@
assertThat(mController.findActiveDevice()).isNull();
}
+
+ /**
+ * One Bluetooth devices are available, and select the device.
+ * Preference summary should be device name.
+ */
+ @Test
+ public void onPreferenceChange_toBtDevice_shouldSetBtDeviceName() {
+ mController.mConnectedDevices.clear();
+ mController.mConnectedDevices.add(mBluetoothDevice);
+
+ mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1);
+
+ assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1);
+ }
+
+ /**
+ * More than one Bluetooth devices are available, and select second device.
+ * Preference summary should be second device name.
+ */
+ @Test
+ public void onPreferenceChange_toBtDevices_shouldSetSecondBtDeviceName() {
+ ShadowBluetoothDevice shadowBluetoothDevice;
+ BluetoothDevice secondBluetoothDevice;
+ secondBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2);
+ shadowBluetoothDevice = Shadows.shadowOf(secondBluetoothDevice);
+ shadowBluetoothDevice.setName(TEST_DEVICE_NAME_2);
+ mController.mConnectedDevices.clear();
+ mController.mConnectedDevices.add(mBluetoothDevice);
+ mController.mConnectedDevices.add(secondBluetoothDevice);
+
+ mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_2);
+
+ assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2);
+ }
+
+ /**
+ * mConnectedDevices is empty.
+ * onPreferenceChange should return false.
+ */
+ @Test
+ public void onPreferenceChange_connectedDeviceIsNull_shouldReturnFalse() {
+ mController.mConnectedDevices.clear();
+
+ assertThat(mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1)).isFalse();
+ }
+
+ @Test
+ public void onPreferenceChange_toThisDevice_shouldSetDefaultSummary() {
+ mController.mConnectedDevices.clear();
+ mController.mConnectedDevices.add(mBluetoothDevice);
+
+ mController.onPreferenceChange(mPreference,
+ mContext.getText(R.string.media_output_default_summary));
+
+ assertThat(mPreference.getSummary()).isEqualTo(
+ mContext.getText(R.string.media_output_default_summary));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
index 8c7faef..7fcd3d2 100644
--- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
@@ -17,16 +17,15 @@
package com.android.settings.sound;
import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
+import static android.media.AudioSystem.DEVICE_OUT_EARPIECE;
import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID;
import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -34,9 +33,10 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
+import android.content.Intent;
import android.media.AudioManager;
-import androidx.preference.ListPreference;
+import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@@ -49,11 +49,13 @@
import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.media.MediaOutputSliceConstants;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -80,8 +82,6 @@
private static final String TEST_DEVICE_ADDRESS_2 = "00:B2:B2:B2:B2:B2";
private static final String TEST_DEVICE_ADDRESS_3 = "00:C3:C3:C3:C3:C3";
private static final String TEST_DEVICE_ADDRESS_4 = "00:D4:D4:D4:D4:D4";
- private final static long HISYNCID1 = 10;
- private final static long HISYNCID2 = 11;
@Mock
private LocalBluetoothManager mLocalManager;
@@ -98,7 +98,7 @@
private Context mContext;
private PreferenceScreen mScreen;
- private ListPreference mPreference;
+ private Preference mPreference;
private AudioManager mAudioManager;
private ShadowAudioManager mShadowAudioManager;
private BluetoothManager mBluetoothManager;
@@ -108,8 +108,8 @@
private BluetoothDevice mLeftBluetoothHapDevice;
private BluetoothDevice mRightBluetoothHapDevice;
private LocalBluetoothManager mLocalBluetoothManager;
- private AudioSwitchPreferenceController mController;
- private List<BluetoothDevice> mProfileConnectedDevices;
+ private MediaOutputPreferenceController mController;
+ private List<BluetoothDevice> mProfileConnectableDevices;
private List<BluetoothDevice> mHearingAidActiveDevices;
@Before
@@ -149,8 +149,8 @@
mController = new MediaOutputPreferenceController(mContext, TEST_KEY);
mScreen = spy(new PreferenceScreen(mContext, null));
- mPreference = new ListPreference(mContext);
- mProfileConnectedDevices = new ArrayList<>();
+ mPreference = new Preference(mContext);
+ mProfileConnectableDevices = new ArrayList<>();
mHearingAidActiveDevices = new ArrayList<>(2);
when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
@@ -166,61 +166,140 @@
ShadowBluetoothUtils.reset();
}
+
/**
- * In normal mode, bluetooth device with HisyncId.
- * HearingAidProfile should set active device to this device.
+ * A2DP Bluetooth device(s) are not connected nor previously connected
+ * Preference should be invisible
*/
@Test
- public void setActiveBluetoothDevice_btDeviceWithHisyncId_shouldSetBtDeviceActive() {
+ public void updateState_withoutConnectableBtDevice_preferenceInvisible() {
+ mShadowAudioManager.setOutputDevice(DEVICE_OUT_EARPIECE);
mAudioManager.setMode(AudioManager.MODE_NORMAL);
- when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
+ mProfileConnectableDevices.clear();
+ when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices);
+ mPreference.setVisible(true);
- mController.setActiveBluetoothDevice(mLeftBluetoothHapDevice);
-
- verify(mHearingAidProfile).setActiveDevice(mLeftBluetoothHapDevice);
- verify(mA2dpProfile, never()).setActiveDevice(mLeftBluetoothHapDevice);
+ assertThat(mPreference.isVisible()).isTrue();
+ mController.updateState(mPreference);
+ assertThat(mPreference.isVisible()).isFalse();
}
/**
- * In normal mode, bluetooth device without HisyncId.
- * A2dpProfile should set active device to this device.
+ * A2DP Bluetooth device(s) are connectable, no matter active or inactive
+ * Preference should be visible
*/
@Test
- public void setActiveBluetoothDevice_btDeviceWithoutHisyncId_shouldSetBtDeviceActive() {
+ public void updateState_withConnectableBtDevice_preferenceVisible() {
+ mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP);
mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ mProfileConnectableDevices.clear();
+ mProfileConnectableDevices.add(mBluetoothDevice);
+ when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices);
+ assertThat(mPreference.isVisible()).isFalse();
- mController.setActiveBluetoothDevice(mBluetoothDevice);
+ // Without Active Bluetooth Device
+ mController.updateState(mPreference);
+ assertThat(mPreference.isVisible()).isTrue();
- verify(mA2dpProfile).setActiveDevice(mBluetoothDevice);
- verify(mHearingAidProfile, never()).setActiveDevice(mBluetoothDevice);
+ // With Active Bluetooth Device
+ when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
+ mController.updateState(mPreference);
+ assertThat(mPreference.isVisible()).isTrue();
}
/**
- * In normal mode, set active device to "this device".
- * A2dpProfile should set to null.
- * HearingAidProfile should set to null.
+ * A2DP Bluetooth device(s) are connectable, but no device is set as activated
+ * Preference summary should be "This device"
*/
@Test
- public void setActiveBluetoothDevice_setNull_shouldSetNullToBothProfiles() {
+ public void updateState_withConnectableBtDevice_withoutActiveBtDevice_setDefaultSummary() {
+ mShadowAudioManager.setOutputDevice(DEVICE_OUT_EARPIECE);
mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ mProfileConnectableDevices.clear();
+ mProfileConnectableDevices.add(mBluetoothDevice);
+ mProfileConnectableDevices.add(mSecondBluetoothDevice);
+ when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices);
+ when(mA2dpProfile.getActiveDevice()).thenReturn(null);
- mController.setActiveBluetoothDevice(null);
-
- verify(mA2dpProfile).setActiveDevice(null);
- verify(mHearingAidProfile).setActiveDevice(null);
+ assertThat(mPreference.getSummary()).isNull();
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary()).isEqualTo(
+ mContext.getText(R.string.media_output_default_summary));
}
/**
- * During a call
- * A2dpProfile should not set active device.
+ * A2DP Bluetooth device(s) are connected and active
+ * Preference summary should be device's name
*/
@Test
- public void setActiveBluetoothDevice_duringACall_shouldNotSetActiveDeviceToA2dpProfile() {
- mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
+ public void updateState_withActiveBtDevice_setActivatedDeviceName() {
+ mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP);
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ mProfileConnectableDevices.clear();
+ mProfileConnectableDevices.add(mBluetoothDevice);
+ mProfileConnectableDevices.add(mSecondBluetoothDevice);
+ when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices);
+ when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
- mController.setActiveBluetoothDevice(mBluetoothDevice);
+ assertThat(mPreference.getSummary()).isNull();
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1);
+ }
- verify(mA2dpProfile, times(0)).setActiveDevice(any(BluetoothDevice.class));
+
+ /**
+ * Hearing Aid device(s) are connectable, no matter active or inactive
+ * Preference should be visible
+ */
+ @Test
+ public void updateState_withConnectableHADevice_preferenceVisible() {
+ mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ mHearingAidActiveDevices.clear();
+ mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
+ when(mHearingAidProfile.getConnectableDevices()).thenReturn(mHearingAidActiveDevices);
+ assertThat(mPreference.isVisible()).isFalse();
+
+ // Without Active Hearing Aid Device
+ mController.updateState(mPreference);
+ assertThat(mPreference.isVisible()).isTrue();
+
+ // With Active Hearing Aid Device
+ when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
+ mController.updateState(mPreference);
+ assertThat(mPreference.isVisible()).isTrue();
+ }
+
+ /**
+ * Hearing Aid device(s) are connected and active
+ * Preference summary should be device's name
+ */
+ @Test
+ public void updateState_withActiveHADevice_setActivatedDeviceName() {
+ mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ mHearingAidActiveDevices.clear();
+ mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
+ when(mHearingAidProfile.getConnectableDevices()).thenReturn(mHearingAidActiveDevices);
+ when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
+
+ assertThat(mPreference.getSummary()).isNull();
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary()).isEqualTo(TEST_HAP_DEVICE_NAME_1);
+
+ }
+
+ @Test
+ public void click_launch_outputSwitcherSlice() {
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ mController.handlePreferenceTreeClick(mPreference);
+ verify(mContext, never()).startActivity(intentCaptor.capture());
+
+ mPreference.setKey(TEST_KEY);
+ mController.handlePreferenceTreeClick(mPreference);
+ verify(mContext).startActivity(intentCaptor.capture());
+ assertThat(intentCaptor.getValue().getAction())
+ .isEqualTo(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT);
}
/**
@@ -254,24 +333,6 @@
}
/**
- * No available A2dp BT devices:
- * Preference should be invisible
- * Preference summary should be "This device"
- */
- @Test
- public void updateState_noAvailableA2dpBtDevices_shouldDisableAndSetDefaultSummary() {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
- List<BluetoothDevice> emptyDeviceList = new ArrayList<>();
- when(mA2dpProfile.getConnectedDevices()).thenReturn(emptyDeviceList);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isVisible()).isFalse();
- String defaultString = mContext.getString(R.string.media_output_default_summary);
- assertThat(mPreference.getSummary()).isEqualTo(defaultString);
- }
-
- /**
* Media stream is captured by something else (cast device):
* Preference should be invisible
* Preference summary should be "unavailable"
@@ -287,235 +348,6 @@
assertThat(mPreference.getSummary()).isEqualTo(defaultString);
}
- /**
- * One A2DP Bluetooth device is available and active.
- * Preference should be visible
- * Preference summary should be the activated device name
- */
- @Test
- public void updateState_oneA2dpBtDeviceAreAvailable_shouldSetActivatedDeviceName() {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
- mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP);
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mBluetoothDevice);
- when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
- when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isVisible()).isTrue();
- assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1);
- }
-
- /**
- * More than one A2DP Bluetooth devices are available, and second device is active.
- * Preference should be visible
- * Preference summary should be the activated device name
- */
- @Test
- public void updateState_moreThanOneA2DpBtDevicesAreAvailable_shouldSetActivatedDeviceName() {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
- mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP);
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mBluetoothDevice);
- mProfileConnectedDevices.add(mSecondBluetoothDevice);
- when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
- when(mA2dpProfile.getActiveDevice()).thenReturn(mSecondBluetoothDevice);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isVisible()).isTrue();
- assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2);
- }
-
- /**
- * A2DP Bluetooth device(s) are available, but wired headset is plugged in and activated
- * Preference should be visible
- * Preference summary should be "This device"
- */
- @Test
- public void updateState_a2dpDevicesAvailableWiredHeadsetIsActivated_shouldSetDefaultSummary() {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mBluetoothDevice);
- when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(null);
- when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
- when(mA2dpProfile.getActiveDevice()).thenReturn(null);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isVisible()).isTrue();
- assertThat(mPreference.getSummary()).isEqualTo(
- mContext.getString(R.string.media_output_default_summary));
- }
-
-
- /**
- * A2DP Bluetooth device(s) are available, but current device speaker is activated
- * Preference should be visible
- * Preference summary should be "This device"
- */
- @Test
- public void updateState_a2dpDevicesAvailableCurrentDeviceActivated_shouldSetDefaultSummary() {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mBluetoothDevice);
- when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
- when(mA2dpProfile.getActiveDevice()).thenReturn(null);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isVisible()).isTrue();
- assertThat(mPreference.getSummary()).isEqualTo(
- mContext.getString(R.string.media_output_default_summary));
- }
-
- /**
- * One hearing aid profile Bluetooth device is available and active.
- * Preference should be visible
- * Preference summary should be the activated device name
- */
- @Test
- public void updateState_oneHapBtDeviceAreAvailable_shouldSetActivatedDeviceName() {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
- mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
- mHearingAidActiveDevices.clear();
- mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
- when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
- when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
- when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isVisible()).isTrue();
- assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName());
- }
-
- /**
- * More than one hearing aid profile Bluetooth devices are available, and second
- * device is active.
- * Preference should be visible
- * Preference summary should be the activated device name
- */
- @Test
- public void updateState_moreThanOneHapBtDevicesAreAvailable_shouldSetActivatedDeviceName() {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
- mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
- mProfileConnectedDevices.add(mRightBluetoothHapDevice);
- mHearingAidActiveDevices.clear();
- mHearingAidActiveDevices.add(mRightBluetoothHapDevice);
- when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
- when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
- when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
- when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isVisible()).isTrue();
- assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName());
- }
-
- /**
- * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid
- * profile devices with same HisyncId are active. Both of HAP device are active,
- * "left" side HAP device is added first.
- * Preference should be visible
- * Preference summary should be the activated device name
- * ConnectedDevice should not contain second HAP device with same HisyncId
- */
- @Test
- public void updateState_hapBtDeviceWithSameId_shouldSetActivatedDeviceName() {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
- mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mBluetoothDevice);
- //with same HisyncId, first one will remain in UI.
- mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
- mProfileConnectedDevices.add(mRightBluetoothHapDevice);
- mHearingAidActiveDevices.clear();
- mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
- mHearingAidActiveDevices.add(mRightBluetoothHapDevice);
- when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
- when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
- when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
- when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isVisible()).isTrue();
- assertThat(mPreference.getSummary()).isEqualTo(mLeftBluetoothHapDevice.getName());
- assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isTrue();
- assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isFalse();
- }
-
- /**
- * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid
- * profile devices with same HisyncId. Both of HAP device are active,
- * "right" side HAP device is added first.
- * Preference should be visible
- * Preference summary should be the activated device name
- * ConnectedDevice should not contain second HAP device with same HisyncId
- */
- @Test
- public void updateState_hapBtDeviceWithSameIdButDifferentOrder_shouldSetActivatedDeviceName() {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
- mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mBluetoothDevice);
- //with same HisyncId, first one will remain in UI.
- mProfileConnectedDevices.add(mRightBluetoothHapDevice);
- mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
- mHearingAidActiveDevices.clear();
- mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
- mHearingAidActiveDevices.add(mRightBluetoothHapDevice);
- when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
- when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
- when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
- when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID1);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isVisible()).isTrue();
- assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName());
- assertThat(mController.mConnectedDevices.contains(mRightBluetoothHapDevice)).isTrue();
- assertThat(mController.mConnectedDevices.contains(mLeftBluetoothHapDevice)).isFalse();
- }
-
- /**
- * Both hearing aid profile and A2dp Bluetooth devices are available, and two hearing aid
- * profile devices with different HisyncId. One of HAP device is active.
- * Preference should be visible
- * Preference summary should be the activated device name
- * ConnectedDevice should contain both HAP device with different HisyncId
- */
- @Test
- public void updateState_hapBtDeviceWithDifferentId_shouldSetActivatedDeviceName() {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
- mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
- mProfileConnectedDevices.clear();
- mProfileConnectedDevices.add(mBluetoothDevice);
- mProfileConnectedDevices.add(mLeftBluetoothHapDevice);
- mProfileConnectedDevices.add(mRightBluetoothHapDevice);
- mHearingAidActiveDevices.clear();
- mHearingAidActiveDevices.add(null);
- mHearingAidActiveDevices.add(mRightBluetoothHapDevice);
- when(mHearingAidProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
- when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
- when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
- when(mHearingAidProfile.getHiSyncId(mRightBluetoothHapDevice)).thenReturn(HISYNCID2);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isVisible()).isTrue();
- assertThat(mPreference.getSummary()).isEqualTo(mRightBluetoothHapDevice.getName());
- assertThat(mController.mConnectedDevices).containsExactly(mBluetoothDevice,
- mLeftBluetoothHapDevice, mRightBluetoothHapDevice);
- }
-
@Test
public void findActiveDevice_onlyA2dpDeviceActive_returnA2dpDevice() {
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(null);
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiManager.java
index b69af2e..30d4c21 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiManager.java
@@ -27,12 +27,15 @@
import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Implements(value = WifiManager.class)
public class ShadowWifiManager extends org.robolectric.shadows.ShadowWifiManager {
+ private List<PasspointConfiguration> mPasspointConfiguration;
+
public WifiConfiguration savedWifiConfig;
private WifiConfiguration mSavedApConfig;
@@ -61,7 +64,15 @@
@Implementation
protected List<PasspointConfiguration> getPasspointConfigurations() {
- return Collections.emptyList();
+ return mPasspointConfiguration == null ? Collections.emptyList() : mPasspointConfiguration;
+ }
+
+ @Implementation
+ protected void addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
+ if (mPasspointConfiguration == null) {
+ mPasspointConfiguration = new ArrayList<>();
+ }
+ mPasspointConfiguration.add(config);
}
@Implementation
diff --git a/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java
index dd0260b..b27b636 100644
--- a/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/users/AddUserWhenLockedPreferenceControllerTest.java
@@ -30,6 +30,7 @@
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.RestrictedSwitchPreference;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,6 +58,12 @@
mContext = RuntimeEnvironment.application;
mUserManager = ShadowUserManager.getShadow();
mController = new AddUserWhenLockedPreferenceController(mContext, "fake_key");
+ mUserManager.setSupportsMultipleUsers(true);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowUserManager.reset();
}
@Test
@@ -72,6 +79,30 @@
}
@Test
+ public void updateState_NotAdmin_shouldNotDisplayPreference() {
+ mUserManager.setIsAdminUser(false);
+ final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class);
+
+ mController.updateState(preference);
+
+ verify(preference).setVisible(false);
+ }
+
+ @Test
+ public void updateState_Admin_shouldDisplayPreference() {
+ mUserManager.setIsAdminUser(true);
+ mUserManager.setUserSwitcherEnabled(true);
+ mUserManager.setSupportsMultipleUsers(true);
+ final AddUserWhenLockedPreferenceController controller =
+ new AddUserWhenLockedPreferenceController(mContext, "fake_key");
+ final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class);
+
+ controller.updateState(preference);
+
+ verify(preference).setVisible(true);
+ }
+
+ @Test
public void updateState_preferenceSetCheckedWhenSettingIsOn() {
final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class);
Global.putInt(mContext.getContentResolver(), Global.ADD_USERS_WHEN_LOCKED, 1);
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java
new file mode 100644
index 0000000..307c0ac
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/calling/ListWithEntrySummaryPreferenceTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.wifi.calling;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.Parcelable;
+import android.widget.ListAdapter;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class ListWithEntrySummaryPreferenceTest {
+
+ private Context mContext;
+ private ListWithEntrySummaryPreference mPreference;
+
+ private CharSequence[] mDefaultEntries =
+ {"default_entry1", "default_entry2", "default_entry3"};
+ private CharSequence[] mDefaultEntryValues = {"0", "1", "2"};
+ private CharSequence[] mDefaultEntrySummaries =
+ {"default_summary1", "default_summary2", "default_summary3"};
+
+ private CharSequence[] mCustomEntries = {"custom_entry1", "custom_entry2"};
+ private CharSequence[] mCustomEntryValues = {"0", "1"};
+ private CharSequence[] mCustomEntrySummaries = {"custom_summary1", "custom_summary2"};
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mContext.setTheme(R.style.Theme_Settings_Home);
+ mPreference = new ListWithEntrySummaryPreference(mContext, null);
+ mPreference.setEntries(mDefaultEntries);
+ mPreference.setEntryValues(mDefaultEntryValues);
+ mPreference.setEntrySummaries(mDefaultEntrySummaries);
+ }
+
+ @Test
+ public void initialize_defaultEntries_shouldDisplayDefalutEntries() {
+ AlertDialog dialog = showDialog(mPreference);
+ ListAdapter adapter = dialog.getListView().getAdapter();
+
+ int len = mDefaultEntries.length;
+ assertThat(adapter.getCount()).isEqualTo(len);
+ for (int i = 0; i < len; i++) {
+ TextView title = adapter.getView(i, null, null).findViewById(R.id.title);
+ TextView summary = adapter.getView(i, null, null).findViewById(R.id.summary);
+ assertThat(title.getText()).isEqualTo(mDefaultEntries[i]);
+ assertThat(summary.getText()).isEqualTo(mDefaultEntrySummaries[i]);
+ }
+ }
+
+ @Test
+ public void setEntries_customEntries_shouldUpdateEntries() {
+ mPreference.setEntries(mCustomEntries);
+ mPreference.setEntryValues(mCustomEntryValues);
+ mPreference.setEntrySummaries(mCustomEntrySummaries);
+
+ AlertDialog dialog = showDialog(mPreference);
+ ListAdapter adapter = dialog.getListView().getAdapter();
+
+ int len = mCustomEntries.length;
+ assertThat(adapter.getCount()).isEqualTo(len);
+ for (int i = 0; i < len; i++) {
+ TextView title = adapter.getView(i, null, null).findViewById(R.id.title);
+ TextView summary = adapter.getView(i, null, null).findViewById(R.id.summary);
+ assertThat(title.getText()).isEqualTo(mCustomEntries[i]);
+ assertThat(summary.getText()).isEqualTo(mCustomEntrySummaries[i]);
+ }
+ }
+
+ @Test
+ public void onSaveAndRestoreInstanceState_resumePreference_shouldNotChangeEntries() {
+ setEntries_customEntries_shouldUpdateEntries();
+
+ final Parcelable parcelable = mPreference.onSaveInstanceState();
+ ListWithEntrySummaryPreference preference
+ = new ListWithEntrySummaryPreference(mContext, null);
+ preference.setEntries(mDefaultEntries);
+ preference.setEntryValues(mDefaultEntryValues);
+ preference.setEntrySummaries(mDefaultEntrySummaries);
+ preference.onRestoreInstanceState(parcelable);
+
+ AlertDialog dialog = showDialog(preference);
+ ListAdapter adapter = dialog.getListView().getAdapter();
+
+ int len = mCustomEntries.length;
+ assertThat(adapter.getCount()).isEqualTo(len);
+ for (int i = 0; i < len; i++) {
+ TextView title = adapter.getView(i, null, null).findViewById(R.id.title);
+ TextView summary = adapter.getView(i, null, null).findViewById(R.id.summary);
+ assertThat(title.getText()).isEqualTo(mCustomEntries[i]);
+ assertThat(summary.getText()).isEqualTo(mCustomEntrySummaries[i]);
+ }
+ }
+
+ private AlertDialog showDialog(ListWithEntrySummaryPreference preference) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+ preference.onPrepareDialogBuilder(builder, null);
+ return builder.show();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
index 39de254..70f1916 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
@@ -41,11 +41,9 @@
import android.view.View;
import android.widget.TextView;
-import androidx.preference.ListPreference;
import androidx.preference.PreferenceScreen;
import com.android.ims.ImsConfig;
-import com.android.ims.ImsException;
import com.android.ims.ImsManager;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
@@ -80,11 +78,11 @@
@Mock private ToggleSwitch mToggleSwitch;
@Mock private View mView;
@Mock private ImsConfig mImsConfig;
- @Mock private ListPreference mButtonWfcMode;
- @Mock private ListPreference mButtonWfcRoamingMode;
+ @Mock private ListWithEntrySummaryPreference mButtonWfcMode;
+ @Mock private ListWithEntrySummaryPreference mButtonWfcRoamingMode;
@Before
- public void setUp() throws NoSuchFieldException, ImsException {
+ public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
@@ -100,7 +98,7 @@
final Bundle bundle = new Bundle();
when(mFragment.getArguments()).thenReturn(bundle);
doNothing().when(mFragment).addPreferencesFromResource(anyInt());
- doReturn(mock(ListPreference.class)).when(mFragment).findPreference(any());
+ doReturn(mock(ListWithEntrySummaryPreference.class)).when(mFragment).findPreference(any());
doReturn(mButtonWfcMode).when(mFragment).findPreference(BUTTON_WFC_MODE);
doReturn(mButtonWfcRoamingMode).when(mFragment).findPreference(BUTTON_WFC_ROAMING_MODE);
doNothing().when(mFragment).finish();
@@ -141,7 +139,7 @@
}
@Test
- public void onResume_provisioningAllowed_shouldNotFinish() throws ImsException {
+ public void onResume_provisioningAllowed_shouldNotFinish() {
// Call onResume while provisioning is allowed.
mFragment.onResume();
@@ -160,7 +158,7 @@
}
@Test
- public void onResumeOnPause_provisioningCallbackRegistration() throws ImsException {
+ public void onResumeOnPause_provisioningCallbackRegistration() throws Exception {
// Verify that provisioning callback is registered after call to onResume().
mFragment.onResume();
verify(mImsConfig).addConfigCallback(any(ProvisioningManager.Callback.class));
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
index f9109ce..644e5e8 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
@@ -22,7 +22,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -48,7 +47,6 @@
import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
import com.android.settings.R;
-import com.android.settings.slices.CustomSliceManager;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
@@ -99,9 +97,6 @@
mFeatureFactory = FakeFeatureFactory.setupForTest();
mSlicesFeatureProvider = mFeatureFactory.getSlicesFeatureProvider();
- CustomSliceManager manager = new CustomSliceManager(mContext);
- when(mSlicesFeatureProvider.getCustomSliceManager(any(Context.class)))
- .thenReturn(manager);
mWfcSliceHelper = new FakeWifiCallingSliceHelper(mContext);
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 640c426..db76722 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -384,9 +384,9 @@
}
@Test
- public void entityHeader_shouldHaveLabelSetToSsid() {
- String label = "ssid";
- when(mockAccessPoint.getSsidStr()).thenReturn(label);
+ public void entityHeader_shouldHaveLabelSetToTitle() {
+ String label = "title";
+ when(mockAccessPoint.getTitle()).thenReturn(label);
displayAndResume();
@@ -758,7 +758,9 @@
}
@Test
- public void forgetNetwork_Passpoint() {
+ public void forgetNetwork_v1_Passpoint() {
+ FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, false);
+
mockWifiConfig.networkId = 5;
when(mockWifiConfig.isPasspoint()).thenReturn(true);
@@ -776,9 +778,9 @@
mockWifiConfig.networkId = 5;
when(mockWifiConfig.isPasspoint()).thenReturn(true);
+ spyController.displayPreference(mockScreen);
FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, true);
- spyController.displayPreference(mockScreen);
mForgetClickListener.getValue().onClick(null);
verify(mockWifiManager, times(0)).removePasspointConfiguration(mockWifiConfig.FQDN);
diff --git a/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceControllerTest.java
index 7f7ecc5..51944d8 100644
--- a/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceControllerTest.java
@@ -20,7 +20,9 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -32,6 +34,8 @@
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
+import com.android.settings.core.FeatureFlags;
+import com.android.settings.development.featureflags.FeatureFlagPersistent;
import com.android.settings.testutils.shadow.ShadowAccessPoint;
import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settings.testutils.shadow.ShadowWifiManager;
@@ -58,6 +62,7 @@
private Context mContext;
private WifiManager mWifiManager;
+ private SavedAccessPointsWifiSettings mSettings;
private SavedAccessPointsPreferenceController mController;
@Before
@@ -65,7 +70,9 @@
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mWifiManager = mContext.getSystemService(WifiManager.class);
+ mSettings = spy(new SavedAccessPointsWifiSettings());
mController = spy(new SavedAccessPointsPreferenceController(mContext, "test_key"));
+ mController.setHost(mSettings);
when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
.thenReturn(mPreferenceCategory);
@@ -115,7 +122,7 @@
@Test
@Config(shadows = ShadowAccessPoint.class)
- public void refreshSavedAccessPoints_shouldListAllAPs() {
+ public void refreshSavedAccessPoints_shouldListNonSubscribedAPs() {
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "SSID";
config.BSSID = "BSSID";
@@ -132,4 +139,18 @@
final AccessPointPreference pref = captor.getValue();
assertThat(pref.getTitle()).isEqualTo(config.SSID);
}
+
+ @Test
+ @Config(shadows = ShadowAccessPoint.class)
+ public void refreshSavedAccessPoints_shouldNotListSubscribedAPs() {
+ FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, true);
+
+ mWifiManager.addOrUpdatePasspointConfiguration(
+ SubscribedAccessPointsPreferenceControllerTest.createMockPasspointConfiguration());
+
+ mController.displayPreference(mPreferenceScreen);
+ mController.refreshSavedAccessPoints();
+
+ verify(mPreferenceCategory, never()).addPreference(any(AccessPointPreference.class));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettingsTest.java
index f76184c..746456e 100644
--- a/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettingsTest.java
@@ -28,6 +28,8 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
+import com.android.settings.core.FeatureFlags;
+import com.android.settings.development.featureflags.FeatureFlagPersistent;
import com.android.settings.wifi.WifiConfigController;
import com.android.settings.wifi.WifiDialog;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -39,6 +41,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
@@ -55,6 +58,8 @@
@Mock
private AccessPoint mAccessPoint;
@Mock
+ private SubscribedAccessPointsPreferenceController mSubscribedApController;
+ @Mock
private SavedAccessPointsPreferenceController mSavedApController;
private TestFragment mSettings;
@@ -64,6 +69,8 @@
MockitoAnnotations.initMocks(this);
mSettings = spy(new TestFragment());
+ doReturn(mSubscribedApController).when(mSettings)
+ .use(SubscribedAccessPointsPreferenceController.class);
doReturn(mSavedApController).when(mSettings)
.use(SavedAccessPointsPreferenceController.class);
@@ -75,6 +82,8 @@
@Test
public void onForget_isPasspointConfig_shouldRefreshAPList() {
+ FeatureFlagPersistent.setEnabled(RuntimeEnvironment.application,
+ FeatureFlags.NETWORK_INTERNET_V2, false);
when(mAccessPoint.isPasspointConfig()).thenReturn(true);
ReflectionHelpers.setField(mSettings, "mSelectedAccessPoint", mAccessPoint);
@@ -84,6 +93,18 @@
}
@Test
+ public void onForget_isPasspointConfig_shouldRefreshSubscribedAPList() {
+ FeatureFlagPersistent.setEnabled(RuntimeEnvironment.application,
+ FeatureFlags.NETWORK_INTERNET_V2, true);
+ when(mAccessPoint.isPasspointConfig()).thenReturn(true);
+ ReflectionHelpers.setField(mSettings, "mSelectedAccessPoint", mAccessPoint);
+
+ mSettings.onForget(null);
+
+ verify(mSubscribedApController).postRefreshSubscribedAccessPoints();
+ }
+
+ @Test
public void onForget_shouldInvokeForgetApi() {
ReflectionHelpers.setField(mSettings, "mSelectedAccessPoint", mAccessPoint);
when(mAccessPoint.getConfig()).thenReturn(mWifiConfiguration);
diff --git a/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SubscribedAccessPointsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SubscribedAccessPointsPreferenceControllerTest.java
new file mode 100644
index 0000000..26933d8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SubscribedAccessPointsPreferenceControllerTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2019 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.wifi.savedaccesspoints;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.Context;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager;
+import android.net.wifi.WifiConfiguration;
+
+import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.pps.HomeSp;
+import android.net.wifi.WifiEnterpriseConfig;
+import android.net.wifi.WifiManager;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.FeatureFlags;
+import com.android.settings.development.featureflags.FeatureFlagPersistent;
+import com.android.settings.testutils.shadow.ShadowAccessPoint;
+import com.android.settings.testutils.shadow.ShadowThreadUtils;
+import com.android.settings.testutils.shadow.ShadowWifiManager;
+import com.android.settingslib.wifi.AccessPointPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowThreadUtils.class, ShadowWifiManager.class})
+public class SubscribedAccessPointsPreferenceControllerTest {
+
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ @Mock
+ private PreferenceCategory mPreferenceCategory;
+
+ private Context mContext;
+ private WifiManager mWifiManager;
+ private SavedAccessPointsWifiSettings mSettings;
+ private SubscribedAccessPointsPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mWifiManager = mContext.getSystemService(WifiManager.class);
+ mSettings = spy(new SavedAccessPointsWifiSettings());
+ mController = spy(new SubscribedAccessPointsPreferenceController(mContext, "test_key"));
+ mController.setHost(mSettings);
+
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreferenceCategory);
+ when(mPreferenceCategory.getContext()).thenReturn(mContext);
+
+ FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, true);
+ }
+
+ @Test
+ public void getAvailability_alwaysAvailable() {
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ public void onStart_shouldRefreshApList() {
+ doNothing().when(mController).refreshSubscribedAccessPoints();
+
+ mController.onStart();
+
+ verify(mController).refreshSubscribedAccessPoints();
+ }
+
+ @Test
+ public void postRefresh_shouldRefreshApList() {
+ doNothing().when(mController).refreshSubscribedAccessPoints();
+
+ mController.postRefreshSubscribedAccessPoints();
+
+ verify(mController).refreshSubscribedAccessPoints();
+ }
+
+ @Test
+ public void forget_onSuccess_shouldRefreshApList() {
+ doNothing().when(mController).refreshSubscribedAccessPoints();
+
+ mController.onSuccess();
+
+ verify(mController).refreshSubscribedAccessPoints();
+ }
+
+ @Test
+ public void forget_onFailure_shouldRefreshApList() {
+ doNothing().when(mController).refreshSubscribedAccessPoints();
+
+ mController.onFailure(0 /* reason */);
+
+ verify(mController).refreshSubscribedAccessPoints();
+ }
+
+ @Test
+ @Config(shadows = ShadowAccessPoint.class)
+ public void refreshSubscribedAccessPoints_shouldNotListNonSubscribedAPs() {
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "SSID";
+ config.BSSID = "BSSID";
+ config.networkId = 2;
+ mWifiManager.addNetwork(config);
+
+ mController.displayPreference(mPreferenceScreen);
+ mController.refreshSubscribedAccessPoints();
+
+ verify(mPreferenceCategory, never()).addPreference(any(AccessPointPreference.class));
+ }
+
+ @Test
+ @Config(shadows = ShadowAccessPoint.class)
+ public void refreshSubscribedAccessPoints_shouldListSubscribedAPs() {
+ mWifiManager.addOrUpdatePasspointConfiguration(createMockPasspointConfiguration());
+
+ mController.displayPreference(mPreferenceScreen);
+ mController.refreshSubscribedAccessPoints();
+
+ final ArgumentCaptor<AccessPointPreference> captor =
+ ArgumentCaptor.forClass(AccessPointPreference.class);
+ verify(mPreferenceCategory).addPreference(captor.capture());
+
+ final AccessPointPreference pref = captor.getValue();
+ assertThat(pref.getTitle()).isEqualTo("TESTPASSPOINT");
+ }
+
+ public static PasspointConfiguration createMockPasspointConfiguration() {
+ final PasspointConfiguration config = new PasspointConfiguration();
+ final HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn("FQDN");
+ homeSp.setFriendlyName("TESTPASSPOINT");
+ config.setHomeSp(homeSp);
+ return config;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
index d8cd878a..06716db 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
@@ -112,36 +112,6 @@
}
@Test
- public void testReceiver_turnOnAirplaneMode_clearPreferenceSummary() {
- final ContentResolver cr = mock(ContentResolver.class);
- when(mContext.getContentResolver()).thenReturn(cr);
- Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, 1);
- mController.displayPreference(mScreen);
- final BroadcastReceiver receiver = ReflectionHelpers.getField(mController, "mReceiver");
- final Intent broadcast = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-
- receiver.onReceive(RuntimeEnvironment.application, broadcast);
-
- assertThat(mPreference.getSummary().toString()).isEqualTo(
- "Unavailable because airplane mode is turned on");
- }
-
- @Test
- public void testReceiver_turnOffAirplaneMode_displayOffSummary() {
- final ContentResolver cr = mock(ContentResolver.class);
- when(mContext.getContentResolver()).thenReturn(cr);
- Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, 0);
- mController.displayPreference(mScreen);
- final BroadcastReceiver receiver = ReflectionHelpers.getField(mController, "mReceiver");
- final Intent broadcast = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-
- receiver.onReceive(RuntimeEnvironment.application, broadcast);
-
- assertThat(mPreference.getSummary().toString()).isEqualTo(
- "Not sharing internet or content with other devices");
- }
-
- @Test
public void testHandleWifiApStateChanged_stateEnabling_showEnablingSummary() {
mController.handleWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0 /* reason */);
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceControllerTest.java
index cb58778..3d15197 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceControllerTest.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
import androidx.preference.PreferenceScreen;
@@ -56,12 +57,12 @@
private PreferenceScreen mScreen;
private WifiTetherSSIDPreferenceController mController;
- private ValidatedEditTextPreference mPreference;
+ private WifiTetherSsidPreference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mPreference = new ValidatedEditTextPreference(RuntimeEnvironment.application);
+ mPreference = new WifiTetherSsidPreference(RuntimeEnvironment.application);
when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
@@ -121,4 +122,28 @@
assertThat(mController.getSSID()).isEqualTo(config.SSID);
assertThat(mPreference.getSummary()).isEqualTo(config.SSID);
}
+
+ @Test
+ public void displayPreference_wifiApDisabled_shouldHideQrCodeIcon() {
+ when(mWifiManager.isWifiApEnabled()).thenReturn(false);
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "test_1234";
+ config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+ when(mWifiManager.getWifiApConfiguration()).thenReturn(config);
+
+ mController.displayPreference(mScreen);
+ assertThat(mController.isQrCodeButtonAvailable()).isEqualTo(false);
+ }
+
+ @Test
+ public void displayPreference_wifiApEnabled_shouldShowQrCodeIcon() {
+ when(mWifiManager.isWifiApEnabled()).thenReturn(true);
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "test_1234";
+ config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+ when(mWifiManager.getWifiApConfiguration()).thenReturn(config);
+
+ mController.displayPreference(mScreen);
+ assertThat(mController.isQrCodeButtonAvailable()).isEqualTo(true);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
index 1a5a228..30358da 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
@@ -73,17 +73,7 @@
mController = new WifiTetherSwitchBarController(mContext,
new SwitchBarController(mSwitchBar));
}
-
- @Test
- public void constructor_airplaneModeOn_switchBarDisabled() {
- Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 1);
-
- new WifiTetherSwitchBarController(mContext, new SwitchBarController(mSwitchBar));
-
- assertThat(mSwitchBar.isEnabled()).isFalse();
- }
-
+
@Test
public void startTether_fail_resetSwitchBar() {
when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(false);
diff --git a/tests/unit/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/unit/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index 447e2b4..653e55e 100644
--- a/tests/unit/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/unit/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -86,6 +86,7 @@
private ContextualCard getContextualCard(Uri sliceUri) {
return new ContextualCard.Builder()
.setName("test_card")
+ .setRankingScore(0.5f)
.setCardType(ContextualCard.CardType.SLICE)
.setSliceUri(sliceUri)
.build();
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
index 405ed4a..38211b3 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
@@ -147,7 +147,7 @@
@Test
public void rotateScreen_shouldGetCorrectWifiNetworkConfig() {
final WifiNetworkConfig wifiNetworkConfig = new WifiNetworkConfig("WPA", "WifiSsid",
- "password", /* hiddenSsid */ false, /* networkId */ 0);
+ "password", /* hiddenSsid */ false, /* networkId */ 0, /* isHotspot */ true);
final Intent intent = new Intent(Settings.ACTION_PROCESS_WIFI_EASY_CONNECT_URI);
intent.setData(Uri.parse(VALID_WIFI_DPP_QR_CODE));
@@ -173,5 +173,6 @@
assertThat(restoredWifiNetworkConfig.getPreSharedKey()).isEqualTo("password");
assertThat(restoredWifiNetworkConfig.getHiddenSsid()).isFalse();
assertThat(restoredWifiNetworkConfig.getNetworkId()).isEqualTo(0);
+ assertThat(restoredWifiNetworkConfig.isHotspot()).isTrue();
}
}