Merge "Avoid getting app locale config for each app" into tm-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ae87edb..0472f07 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2855,7 +2855,7 @@
android:name="Settings$BatterySaverSettingsActivity"
android:label="@string/battery_saver"
android:exported="true"
- android:icon="@drawable/ic_settings_battery">
+ android:icon="@drawable/ic_homepage_battery">
<intent-filter android:priority="1">
<action android:name="android.settings.BATTERY_SAVER_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
@@ -2870,6 +2870,7 @@
<activity android:name=".fuelgauge.BatterySaverModeVoiceActivity"
android:label="@string/power_usage_summary_title"
+ android:icon="@drawable/ic_homepage_battery"
android:theme="@*android:style/Theme.DeviceDefault.Light.Voice"
android:exported="true">
<intent-filter>
@@ -4474,6 +4475,16 @@
</intent-filter>
</receiver>
+ <activity
+ android:name="com.android.settings.bluetooth.QrCodeScanModeActivity"
+ android:permission="android.permission.BLUETOOTH_CONNECT"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.settings.BLUETOOTH_LE_AUDIO_QR_CODE_SCANNER"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+
<!-- This is the longest AndroidManifest.xml ever. -->
</application>
</manifest>
diff --git a/res/drawable/homepage_app_bar_background.xml b/res/drawable/homepage_app_bar_background.xml
new file mode 100644
index 0000000..6872ab7
--- /dev/null
+++ b/res/drawable/homepage_app_bar_background.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid
+ android:color="@color/settings_two_pane_background_color" />
+ <corners
+ android:bottomLeftRadius="@dimen/homepage_app_bar_corner_radius"
+ android:bottomRightRadius="@dimen/homepage_app_bar_corner_radius" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/homepage_highlighted_item_background.xml b/res/drawable/homepage_highlighted_item_background.xml
index 7e0dea5..4656a46 100644
--- a/res/drawable/homepage_highlighted_item_background.xml
+++ b/res/drawable/homepage_highlighted_item_background.xml
@@ -14,10 +14,14 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid
- android:color="@color/accent_select_background" />
- <corners
- android:radius="@dimen/homepage_preference_corner_radius" />
-</shape>
\ No newline at end of file
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@*android:color/ripple_material_light">
+ <item>
+ <shape android:shape="rectangle">
+ <solid
+ android:color="@color/accent_select_background" />
+ <corners
+ android:radius="@dimen/homepage_preference_corner_radius" />
+ </shape>
+ </item>
+</ripple>
\ No newline at end of file
diff --git a/res/drawable/ic_qr_code_scanner.xml b/res/drawable/ic_qr_code_scanner.xml
new file mode 100644
index 0000000..f6f63c5
--- /dev/null
+++ b/res/drawable/ic_qr_code_scanner.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
+ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path android:fillColor="@android:color/white"
+ android:pathData="M2,7V2H7V4H4V7ZM2,22V17H4V20H7V22ZM17,22V20H20V17H22V22ZM20,7V4H17V2H22V7ZM17.5,17.5H19V19H17.5ZM17.5,14.5H19V16H17.5ZM16,16H17.5V17.5H16ZM14.5,17.5H16V19H14.5ZM13,16H14.5V17.5H13ZM16,13H17.5V14.5H16ZM14.5,14.5H16V16H14.5ZM13,13H14.5V14.5H13ZM19,5V11H13V5ZM11,13V19H5V13ZM11,5V11H5V5ZM9.5,17.5V14.5H6.5V17.5ZM9.5,9.5V6.5H6.5V9.5ZM17.5,9.5V6.5H14.5V9.5Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/layout/qrcode_scan_mode_activity.xml b/res/layout/qrcode_scan_mode_activity.xml
new file mode 100644
index 0000000..f0a182b
--- /dev/null
+++ b/res/layout/qrcode_scan_mode_activity.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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:id="@+id/root"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/fragment_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+
+</LinearLayout>
diff --git a/res/layout/qrcode_scanner_fragment.xml b/res/layout/qrcode_scanner_fragment.xml
new file mode 100644
index 0000000..2c543f2
--- /dev/null
+++ b/res/layout/qrcode_scanner_fragment.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/sud_layout_icon_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="3"
+ android:layout_marginBottom="35dp">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:gravity="center"
+ android:orientation="vertical">
+ <ImageView
+ android:id="@+id/sud_layout_icon"
+ android:src="@drawable/ic_qr_code_scanner"
+ android:tint="?androidprv:attr/colorAccentPrimaryVariant"
+ android:layout_width="@dimen/qrcode_icon_size"
+ android:layout_height="@dimen/qrcode_icon_size"
+ android:contentDescription="@null"/>
+
+ <TextView
+ android:id="@+id/sud_layout_title"
+ style="@style/QrCodeScanner"
+ android:textSize="24sp"
+ android:text="@string/bluetooth_find_broadcast_button_scan"
+ android:gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="19dp"/>
+
+ <TextView
+ android:id="@+id/sud_layout_subtitle"
+ style="@style/QrCodeScanner"
+ android:text="@string/bt_le_audio_scan_qr_code_scanner"
+ android:gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"/>
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="7"
+ android:orientation="vertical">
+
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:gravity="center"
+ android:clipChildren="true">
+ <TextureView
+ android:id="@+id/preview_view"
+ android:layout_marginStart="@dimen/qrcode_preview_margin"
+ android:layout_marginEnd="@dimen/qrcode_preview_margin"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qrcode_preview_size"/>
+ </FrameLayout>
+
+ <TextView
+ android:id="@+id/error_message"
+ style="@style/TextAppearance.ErrorText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:layout_marginStart="?attr/sudMarginStart"
+ android:layout_marginEnd="?attr/sudMarginEnd"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:visibility="invisible"/>
+
+ </LinearLayout>
+
+
+</LinearLayout>
+
diff --git a/res/layout/search_bar_two_pane_version.xml b/res/layout/search_bar_two_pane_version.xml
index ede5722..9ce220c 100644
--- a/res/layout/search_bar_two_pane_version.xml
+++ b/res/layout/search_bar_two_pane_version.xml
@@ -21,8 +21,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:layout_marginEnd="@dimen/search_bar_margin"
- android:layout_marginVertical="@dimen/search_bar_margin">
+ android:layout_marginEnd="@dimen/search_bar_margin">
<Toolbar
android:id="@+id/search_action_bar_two_pane"
android:layout_width="match_parent"
diff --git a/res/layout/settings_homepage_app_bar_two_pane_layout.xml b/res/layout/settings_homepage_app_bar_two_pane_layout.xml
index 0cd8c90..b9c1493 100644
--- a/res/layout/settings_homepage_app_bar_two_pane_layout.xml
+++ b/res/layout/settings_homepage_app_bar_two_pane_layout.xml
@@ -17,29 +17,21 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/app_bar_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:background="@color/settings_two_pane_background_color">
+ android:layout_marginHorizontal="@dimen/homepage_app_bar_margin_horizontal_two_pane"
+ android:padding="@dimen/homepage_app_bar_padding_two_pane"
+ android:orientation="horizontal"
+ android:background="@drawable/homepage_app_bar_background">
- <FrameLayout
- android:id="@+id/two_pane_suggestion_content"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
+ <include layout="@layout/search_bar_two_pane_version"/>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/account_avatar_two_pane_version"
+ android:layout_width="@dimen/avatar_length"
+ android:layout_height="@dimen/avatar_length"
+ android:layout_gravity="center"
+ android:contentDescription="@string/search_bar_account_avatar_content_description"/>
- <include layout="@layout/search_bar_two_pane_version"/>
-
- <ImageView
- android:id="@+id/account_avatar_two_pane_version"
- android:layout_width="@dimen/avatar_length"
- android:layout_height="@dimen/avatar_length"
- android:layout_gravity="center"
- android:contentDescription="@string/search_bar_account_avatar_content_description"/>
- </LinearLayout>
-
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 3de5a8a..89d40d0 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -34,6 +34,11 @@
android:layout_height="wrap_content"
android:orientation="vertical">
+ <include
+ android:id="@+id/suggestion_container_two_pane"
+ layout="@layout/suggestion_container_two_pane"
+ android:visibility="gone"/>
+
<FrameLayout
android:id="@+id/contextual_cards_content"
android:layout_width="match_parent"
diff --git a/res/layout/suggestion_container_two_pane.xml b/res/layout/suggestion_container_two_pane.xml
new file mode 100644
index 0000000..412a0d4
--- /dev/null
+++ b/res/layout/suggestion_container_two_pane.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/homepage_app_bar_margin_bottom_two_pane"
+ android:layout_marginHorizontal="@dimen/homepage_padding_horizontal_two_pane">
+
+ <FrameLayout
+ android:id="@+id/two_pane_suggestion_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+</FrameLayout>
diff --git a/res/layout/wifi_calling_settings_preferences.xml b/res/layout/wifi_calling_settings_preferences.xml
index 9a6cbe6..bad90ad 100644
--- a/res/layout/wifi_calling_settings_preferences.xml
+++ b/res/layout/wifi_calling_settings_preferences.xml
@@ -21,12 +21,6 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <com.android.settings.widget.SettingsMainSwitchBar
- android:id="@+id/switch_bar"
- android:title="@string/wifi_calling_main_switch_title"
- android:layout_height="wrap_content"
- android:layout_width="match_parent" />
-
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
diff --git a/res/values-af/arrays.xml b/res/values-af/arrays.xml
index 4c0ac1d..b7c367a 100644
--- a/res/values-af/arrays.xml
+++ b/res/values-af/arrays.xml
@@ -485,7 +485,7 @@
<item msgid="8186970968968646288">"Gekas (leeg)"</item>
</string-array>
<string-array name="color_picker">
- <item msgid="7216413848731287689">"Groenblou"</item>
+ <item msgid="7216413848731287689">"Siaan"</item>
<item msgid="5661027589207588703">"Blou"</item>
<item msgid="1219738214736244749">"Groen"</item>
<item msgid="6331809026622602308">"Pers"</item>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index dfb2596..91f3f3b 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Stelselverstek"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Taalkeuse vir hierdie program is nie in Instellings beskikbaar nie."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Taal kan verskil van tale wat in die program beskikbaar is. Sommige programme steun dalk nie hierdie instelling nie."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Net programme wat taalkeuses ondersteun, word hier gewys."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Verwyder gekose tale?</item>
<item quantity="one">Verwyder gekose taal?</item>
diff --git a/res/values-as/arrays.xml b/res/values-as/arrays.xml
index 52cbe56..02c8c51 100644
--- a/res/values-as/arrays.xml
+++ b/res/values-as/arrays.xml
@@ -180,7 +180,7 @@
</string-array>
<string-array name="wifi_proxy_settings">
<item msgid="4669222334822978847">"নাই"</item>
- <item msgid="6242198071587397280">"হস্তকৃত"</item>
+ <item msgid="6242198071587397280">"মেনুৱেল"</item>
<item msgid="464383874780058242">"প্ৰক্সি স্বয়ং-কনফিগাৰেশ্বন"</item>
</string-array>
<string-array name="apn_auth_entries">
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 147a818..80842d2 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"ছিষ্টেম ডিফ’ল্ট"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"এই এপ্টোৰ বাবে ছেটিঙৰ পৰা ভাষা বাছনি কৰাৰ সুবিধা উপলব্ধ নহয়।"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"ভাষাটো এপ্টোত উপলব্ধ ভাষাসমূহতকৈ পৃথক হ’ব পাৰে। কিছুমান এপে এই ছেটিংটো সমৰ্থন নকৰিব পাৰে।"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"কেৱল ভাষা বাছনি কৰাৰ সুবিধা থকা এপ্সমূহ ইয়াত দেখুওৱা হৈছে।"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">বাছনি কৰা ভাষাসমূহ আঁতৰাবনে?</item>
<item quantity="other">বাছনি কৰা ভাষাসমূহ আঁতৰাবনে?</item>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index f4821fe..bdffc5e 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Sistem defoltu"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Bu tətbiq üçün dil seçimini Ayarlardan etmək olmur."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Dil tətbiqdə əlçatan dillərdən fərqli ola bilər. Bəzi tətbiqlər bu ayarı dəstəkləməyə bilər."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Burada yalnız dil seçimini dəstəkləyən tətbiqlər göstərilir."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Seçilmiş dillər silinsin?</item>
<item quantity="one">Seçilmiş dil silinsin?</item>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 2713d6b..b17b156 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -229,6 +229,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Podrazumevani sistemski"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Izbor jezika za ovu aplikaciju nije dostupan iz Podešavanja."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Jezik može da se razlikuje od jezika dostupnih u aplikaciji. Neke aplikacije možda ne podržavaju ovo podešavanje."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Ovde se prikazuju samo aplikacije koje podržavaju izbor jezika."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Želite li da uklonite izabrane jezike?</item>
<item quantity="few">Želite li da uklonite izabrane jezike?</item>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index ccc6d75..fe9af98 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Стандартно за системата"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Избирането на език за това приложение не е налице от настройките."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Езикът може да се различава от езиците, налични в приложението. Възможно е някои приложения да не поддържат тази настройка."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Тук са показани само приложенията, които поддържат избиране на език."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Да се премахнат ли избраните езици?</item>
<item quantity="one">Да се премахне ли избраният език?</item>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 9ceb9c6..87cf387 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"সিস্টেম ডিফল্ট"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"এই অ্যাপের জন্য \'সেটিংস\' থেকে ভাষা বেছে নেওয়ার সুবিধা উপলভ্য নেই।"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"অ্যাপে উপলভ্য থাকা ভাষা আলাদা হতে পারে। কিছু অ্যাপে এই সেটিং কাজ নাও করতে পারে।"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"শুধুমাত্র সেইসব অ্যাপ দেখানো হয়েছে যার মধ্যে ভাষা বেছে নেওয়ার বিকল্প আছে।"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">নির্বাচিত ভাষা সরাবেন?</item>
<item quantity="other">নির্বাচিত ভাষা সরাবেন?</item>
diff --git a/res/values-bs/arrays.xml b/res/values-bs/arrays.xml
index 42dc013..3e1f8f3 100644
--- a/res/values-bs/arrays.xml
+++ b/res/values-bs/arrays.xml
@@ -387,11 +387,11 @@
<item msgid="5012882784126308133">"Mala početna slova"</item>
</string-array>
<string-array name="captioning_font_size_selector_titles">
- <item msgid="923916134548435468">"Vrlo mali"</item>
- <item msgid="5738147437573674872">"Mali"</item>
+ <item msgid="923916134548435468">"Vrlo malo"</item>
+ <item msgid="5738147437573674872">"Malo"</item>
<item msgid="4691660235626027304">"Srednje"</item>
- <item msgid="824386705928670045">"Veliki"</item>
- <item msgid="2790561781512874585">"Vrlo veliki"</item>
+ <item msgid="824386705928670045">"Veliko"</item>
+ <item msgid="2790561781512874585">"Vrlo veliko"</item>
</string-array>
<string-array name="captioning_edge_type_selector_titles">
<item msgid="70686029249840227">"Zadano"</item>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 63a8ddd..28ea355 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -229,6 +229,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Sistemski zadano"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Odabir jezika za ovu aplikaciju nije dostupan u Postavkama."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Jezik se može razlikovati od jezika dostupnih u aplikaciji. Neke aplikacije možda neće podržavati ovu postavku."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Ovdje su prikazane samo aplikacije koje podržavaju odabir jezika."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Ukloniti odabrane jezike?</item>
<item quantity="few">Ukloniti odabrane jezike?</item>
diff --git a/res/values-ca/arrays.xml b/res/values-ca/arrays.xml
index 68f7be9..0f94336 100644
--- a/res/values-ca/arrays.xml
+++ b/res/values-ca/arrays.xml
@@ -387,7 +387,7 @@
<item msgid="5012882784126308133">"Versaletes"</item>
</string-array>
<string-array name="captioning_font_size_selector_titles">
- <item msgid="923916134548435468">"Molt petit"</item>
+ <item msgid="923916134548435468">"Molt petita"</item>
<item msgid="5738147437573674872">"Petita"</item>
<item msgid="4691660235626027304">"Mitjana"</item>
<item msgid="824386705928670045">"Gran"</item>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 51a8a1b..96108b6 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Valor predeterminat del sistema"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"La selecció d\'idioma per a aquesta aplicació no està disponible des de Configuració."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"És possible que l\'idioma no coincideixi amb els que hi ha disponibles a l\'aplicació. Algunes aplicacions no admeten aquesta opció de configuració."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Aquí només es mostren les aplicacions que admeten la selecció d'idioma."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Vols suprimir els idiomes seleccionats?</item>
<item quantity="one">Vols suprimir l\'idioma seleccionat?</item>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index e90a20e..8058bac 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -230,6 +230,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Výchozí nastavení systému"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"V Nastavení nelze vybrat jazyk pro tuto aplikaci."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Jazyky nemusí odpovídat jazykům dostupným v aplikaci. Toto nastavení mohou podporovat jen některé aplikace."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Zobrazují se tu pouze aplikace, které podporují výběr jazyka."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="few">Odstranit vybrané jazyky?</item>
<item quantity="many">Odstranit vybrané jazyky?</item>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 1c46693..ca4351b 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Standardeinstellung des Systems"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Für diese App ist in den Einstellungen keine Sprachauswahl verfügbar."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Die Sprache kann von den in der App verfügbaren Sprachen abweichen. Einige Apps unterstützen diese Einstellung möglicherweise nicht."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Hier werden nur Apps angezeigt, die die Sprachauswahl unterstützen."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Ausgewählte Sprachen entfernen?</item>
<item quantity="one">Ausgewählte Sprache entfernen?</item>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 47745fd..4dba7f5 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Προεπιλογή συστήματος"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Η δυνατότητα επιλογής γλώσσας για αυτήν την εφαρμογή δεν είναι διαθέσιμη από τις Ρυθμίσεις."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Η γλώσσα μπορεί να διαφέρει από τις γλώσσες που είναι διαθέσιμες στην εφαρμογή. Ορισμένες εφαρμογές μπορεί να μην υποστηρίζουν αυτήν τη ρύθμιση."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Εδώ εμφανίζονται μόνο εφαρμογές που υποστηρίζουν την επιλογή γλώσσας."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Να αφαιρεθούν οι επιλεγμένες γλώσσες;</item>
<item quantity="one">Να αφαιρεθεί η επιλεγμένη γλώσσα;</item>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 4e2c331..b0d74f2 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"System default"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Language selection for this app isn’t available from Settings."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Language may differ from languages available in the app. Some apps may not support this setting."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Only apps that support language selection are shown here."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Remove selected languages?</item>
<item quantity="one">Remove selected language?</item>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 98c1a46..a30e3f4 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"System default"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Language selection for this app isn’t available from Settings."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Language may differ from languages available in the app. Some apps may not support this setting."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Only apps that support language selection are shown here."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Remove selected languages?</item>
<item quantity="one">Remove selected language?</item>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index d49243d..cdc2556 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"System default"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Language selection for this app isn’t available from Settings."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Language may differ from languages available in the app. Some apps may not support this setting."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Only apps that support language selection are shown here."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Remove selected languages?</item>
<item quantity="one">Remove selected language?</item>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index bb089bb..e5f065a 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"System default"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Language selection for this app isn’t available from Settings."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Language may differ from languages available in the app. Some apps may not support this setting."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Only apps that support language selection are shown here."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Remove selected languages?</item>
<item quantity="one">Remove selected language?</item>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 65414c8..0901515 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"System default"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Language selection for this app isn’t available from Settings."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Language may differ from languages available in the app. Some apps may not support this setting."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Only apps that support language selection are shown here."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Remove selected languages?</item>
<item quantity="one">Remove selected language?</item>
diff --git a/res/values-es/arrays.xml b/res/values-es/arrays.xml
index 7af2782..513f813 100644
--- a/res/values-es/arrays.xml
+++ b/res/values-es/arrays.xml
@@ -580,7 +580,7 @@
<!-- no translation found for rtt_setting_mode:3 (7725394146877517088) -->
<string-array name="nfc_payment_favor">
<item msgid="9104058551372383947">"Siempre"</item>
- <item msgid="5283665583617307336">"Excepto si hay otra aplicación de pago abierta"</item>
+ <item msgid="5283665583617307336">"Excepto si hay otra aplicación para pagos abierta"</item>
</string-array>
<string-array name="nfc_payment_favor_values">
<item msgid="2373999996715432397">"0"</item>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 7b8d2c9..3b6b76e 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Predeterminado del sistema"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"La selección de idioma para esta aplicación no está disponible en Ajustes."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Puede que el idioma no coincida con los que hay disponibles en la aplicación. Algunas aplicaciones no son compatibles con este ajuste."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Aquí solo se muestran las aplicaciones que admiten la selección de idioma."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">¿Quitar idiomas seleccionados?</item>
<item quantity="one">¿Quitar idioma seleccionado?</item>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index c8b4176..4a1073f 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Süsteemi vaikeseade"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Selle rakenduse jaoks pole seadetes keele valimine saadaval."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Keel võib rakenduses saadaolevatest keeltest erineda. Mõni rakendus ei pruugi seda seadet toetada."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Siin on kuvatud ainult rakendused, mis toetavad keele valimist."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Kas eemaldada valitud keeled?</item>
<item quantity="one">Kas eemaldada valitud keel?</item>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 96b8745..6009305 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"پیشفرض سیستم"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"انتخاب زبان از «تنظیمات» برای این برنامه دردسترس نیست."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"زبان ممکن است با زبانهای موجود در برنامه متفاوت باشد. ممکن است برخیاز برنامهها از این تنظیم پشتیبانی نکنند."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"فقط برنامههایی که از انتخاب زبان پشتیبانی میکنند اینجا نمایش داده میشود."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">زبانهای انتخابی حذف شوند؟</item>
<item quantity="other">زبانهای انتخابی حذف شوند؟</item>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index b9cca3c..468a633 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Järjestelmän oletusarvo"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Sovellukselle ei voi valita kieltä asetuksista."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Kieli saattaa erota sovelluksessa saatavilla olevista kielistä. Jotkin sovellukset eivät ehkä tue tätä asetusta."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Täällä näkyvät vain sovellukset, jotka tukevat kielen valitsemista."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Poistetaanko valitut kielet?</item>
<item quantity="one">Poistetaanko valittu kieli?</item>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index e59245e..d5ac122 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Paramètre système par défaut"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"La sélection de la langue pour cette application n\'est pas accessible à partir des paramètres."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"La langue peut différer des langues offertes dans l\'application. Certaines applications peuvent ne pas prendre en charge ce paramètre."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Seules les applications qui prennent en charge la sélection de la langue sont affichées ici."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Supprimer la langue sélectionnée?</item>
<item quantity="other">Supprimer les langues sélectionnées?</item>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 4a448c6..286997b 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Opción predeterminada do sistema"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"A opción de seleccionar un idioma para esta aplicación non está dispoñible en Configuración."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"É posible que o idioma non estea dispoñible na aplicación. Pode que algunhas aplicacións non sexan compatibles con esta opción de configuración."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Aquí só se mostran as aplicacións que admiten a selección de idioma."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Queres quitar os idiomas seleccionados?</item>
<item quantity="one">Queres quitar o idioma seleccionado?</item>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index eb50a6a..73bafa7 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"સિસ્ટમ ડિફૉલ્ટ"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"આ ઍપ માટે સેટિંગમાંથી ભાષા પસંદ કરી શકાતી નથી."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"આ ભાષા ઍપમાં ઉપલબ્ધ ભાષાઓથી અલગ હોઈ શકે છે. કેટલીક ઍપ આ સેટિંગને સપોર્ટ ન કરે એવું બની શકે છે."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"માત્ર ભાષાની પસંદગીને સપોર્ટ કરતી ઍપ જ અહીં બતાવવામાં આવી છે."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">પસંદ કરેલ ભાષાઓને કાઢી નાખીએ?</item>
<item quantity="other">પસંદ કરેલ ભાષાઓને કાઢી નાખીએ?</item>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index ec8b8a6..f5b63aa 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"सिस्टम डिफ़ॉल्ट"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"सेटिंग में, इस ऐप्लिकेशन की भाषा चुनने का विकल्प मौजूद नहीं है."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"भाषा, ऐप्लिकेशन में उपलब्ध भाषाओं से अलग हो सकती है. हो सकता है कि कुछ ऐप्लिकेशन के साथ, भाषा की यह सेटिंग काम न करे."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"यहां सिर्फ़ वे ऐप्लिकेशन दिखाए गए हैं जिनमें भाषा चुनने का विकल्प मौजूद है."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">क्या आप चुनी गई भाषा हटाना चाहते हैं?</item>
<item quantity="other">क्या आप चुनी गई भाषाएं हटाना चाहते हैं?</item>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 487a3a1..9cbc0fc 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -229,6 +229,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Zadane postavke sustava"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Odabir jezika za ovu aplikaciju nije dostupan u postavkama."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Jezik se može razlikovati od jezika dostupnih u aplikaciji. Neke aplikacije možda ne podržavaju tu postavku."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Ovdje se prikazuju samo aplikacije koje podržavaju odabir jezika."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Želite li ukloniti odabrane jezike?</item>
<item quantity="few">Želite li ukloniti odabrane jezike?</item>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 0bb827b..9dad46f 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Rendszerbeállítás"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"A Nyelvválasztás nem áll rendelkezésre ehhez az alkalmazáshoz a Beállításokban."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"A nyelv eltérhet az alkalmazásban rendelkezésre álló nyelvektől. Előfordulhat, hogy egyes alkalmazások nem támogatják ezt a beállítást."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Csak azok az alkalmazások láthatók itt, amelyek támogatják a nyelvválasztást."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Eltávolítja a kiválasztott nyelveket?</item>
<item quantity="one">Eltávolítja a kiválasztott nyelvet?</item>
diff --git a/res/values-hy/arrays.xml b/res/values-hy/arrays.xml
index 9681888..42043b3 100644
--- a/res/values-hy/arrays.xml
+++ b/res/values-hy/arrays.xml
@@ -409,9 +409,9 @@
</string-array>
<string-array name="captioning_preset_selector_titles">
<item msgid="3880932435325583041">"Կարգավորված է հավելվածով"</item>
- <item msgid="8719204526359229387">"Սպիտակը սևի վրա"</item>
- <item msgid="5410164687403735103">"Սևը սպիտակի վրա"</item>
- <item msgid="1119043472912497241">"Դեղինը սևի վրա"</item>
+ <item msgid="8719204526359229387">"Սպիտակ՝ սևի վրա"</item>
+ <item msgid="5410164687403735103">"Սև՝ սպիտակի վրա"</item>
+ <item msgid="1119043472912497241">"Դեղին՝ սևի վրա"</item>
<item msgid="2836895041823327816">"Դեղինը կապույտի վրա"</item>
<item msgid="747238414788976867">"Հատուկ"</item>
</string-array>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 797712f..e5e63e0 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Կանխադրված"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Լեզվի ընտրությունն այս հավելվածի համար հասանելի չէ Կարգավորումներում։"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Լեզուն կարող է հավելվածում հասանելի լեզուների ցանկում չլինել։ Որոշ հավելվածներ կարող են չաջակցել այս կարգավորումը։"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Այստեղ ցուցադրված են միայն այն հավելվածները, որոնցում աջակցվում է լեզվի ընտրությունը։"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Հեռացնե՞լ ընտրված լեզուն</item>
<item quantity="other">Հեռացնե՞լ ընտրված լեզուները</item>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 3bb1aca..73c6fc0 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Default sistem"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Pemilihan bahasa untuk aplikasi ini tidak tersedia dari Setelan."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Bahasa mungkin berbeda dari bahasa yang tersedia di aplikasi. Beberapa aplikasi mungkin tidak mendukung setelan ini."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Hanya aplikasi yang mendukung pilihan bahasa yang ditampilkan di sini."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Hapus bahasa yang dipilih?</item>
<item quantity="one">Hapus bahasa yang dipilih?</item>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 75792a5..d490ed3 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Sjálfgildi kerfis"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Ekki er hægt að velja tungumál fyrir þetta forrit í stillingum."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Tungumál kann að vera frábrugðið tiltækum tungumálum í forritinu. Tiltekin forrit styðja hugsanlega ekki þessa stillingu."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Hér eru aðeins birt forrit sem styðja val á tungumáli."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Fjarlægja valin tungumál?</item>
<item quantity="other">Fjarlægja valin tungumál?</item>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index cbcb0e1..21221fc 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Predefinita di sistema"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"La selezione della lingua per questa app non è disponibile nelle Impostazioni."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"La lingua potrebbe essere diversa dalle lingue disponibili nell\'app. Alcune app potrebbero non supportare questa impostazione."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Qui vengono mostrate soltanto le app che supportano la selezione della lingua."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Rimuovere le lingue selezionate?</item>
<item quantity="one">Rimuovere la lingua selezionata?</item>
diff --git a/res/values-iw/arrays.xml b/res/values-iw/arrays.xml
index df97f79..023aa01 100644
--- a/res/values-iw/arrays.xml
+++ b/res/values-iw/arrays.xml
@@ -417,7 +417,7 @@
</string-array>
<string-array name="accessibility_button_location_selector_titles">
<item msgid="6485511780196327736">"צף מעל אפליקציות אחרות"</item>
- <item msgid="3605616699204153590">"סרגל ניווט"</item>
+ <item msgid="3605616699204153590">"סרגל הניווט"</item>
</string-array>
<string-array name="accessibility_button_gesture_selector_titles">
<item msgid="2370918472773154939">"לחצן"</item>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 00222fe..33bf9ad 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -230,6 +230,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"ברירת המחדל של המערכת"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"בחירות השפה לאפליקציה הזו לא זמינה בהגדרות."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"השפה עשויה להיות שונה מהשפות הזמינות באפליקציה. יכול להיות שחלק מהאפליקציות לא תומכות בהגדרה הזו."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"מוצגות כאן רק אפליקציות התומכות בבחירת שפה."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="two">להסיר את השפות שנבחרו?</item>
<item quantity="many">להסיר את השפות שנבחרו?</item>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index c4b67ab..8f6f054 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"システムのデフォルト"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"このアプリの言語は [設定] から選択できません。"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"アプリで利用できない言語の可能性があります。一部のアプリはこの設定に対応していない可能性があります。"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"ここには、選択した言語に対応するアプリのみが表示されます。"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">選択した言語を削除しますか?</item>
<item quantity="one">選択した言語を削除しますか?</item>
diff --git a/res/values-kk/arrays.xml b/res/values-kk/arrays.xml
index 2d03d67..bbc2339 100644
--- a/res/values-kk/arrays.xml
+++ b/res/values-kk/arrays.xml
@@ -387,8 +387,8 @@
<item msgid="5012882784126308133">"Кішкене бас әріптер"</item>
</string-array>
<string-array name="captioning_font_size_selector_titles">
- <item msgid="923916134548435468">"Өте кішкене"</item>
- <item msgid="5738147437573674872">"Кішкене"</item>
+ <item msgid="923916134548435468">"Өте кіші"</item>
+ <item msgid="5738147437573674872">"Кіші"</item>
<item msgid="4691660235626027304">"Орташа"</item>
<item msgid="824386705928670045">"Үлкен"</item>
<item msgid="2790561781512874585">"Өте үлкен"</item>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index e52fa62..ecb56a7 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Жүйенің әдепкі параметрі"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Бұл қолданба үшін \"Параметрлер\" бөлімінен тіл таңдау мүмкіндігі қолжетімсіз."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Тілдер қолданбадағы тілдерден өзгеше болуы мүмкін. Кейбір қолданба бұл параметрді қолдамауы мүмкін."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Мұнда тіл таңдау мүмкіндігі бар қолданбалар ғана көрсетілген."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Таңдалған тілдерді жою керек пе?</item>
<item quantity="one">Таңдалған тілді жою керек пе?</item>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index d7c5041..524dfcf 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"លំនាំដើមប្រព័ន្ធ"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"មិនអាចជ្រើសរើសភាសាសម្រាប់កម្មវិធីនេះពីការកំណត់បានទេ។"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"ភាសាអាចមានភាពខុសគ្នាពីភាសាដែលមាននៅក្នុងកម្មវិធី។ កម្មវិធីមួយចំនួនប្រហែលជាមិនអាចប្រើការកំណត់នេះបានទេ។"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"មានតែកម្មវិធីដែលស្គាល់ការជ្រើសរើសភាសាប៉ុណ្ណោះដែលបង្ហាញនៅទីនេះ។"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">លុបភាសាដែលបានជ្រើសរើសឬ?</item>
<item quantity="one">លុបភាសាដែលបានជ្រើសរើសឬ?</item>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 99dce28..55ad7df 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"ಸಿಸ್ಟಂ ಡೀಫಾಲ್ಟ್"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"ಸೆಟ್ಟಿಂಗ್ಗಳ ಮೂಲಕ ಈ ಆ್ಯಪ್ಗಾಗಿ ಭಾಷೆಯ ಆಯ್ಕೆಯು ಲಭ್ಯವಿಲ್ಲ."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"ಆ್ಯಪ್ನಲ್ಲಿ ಲಭ್ಯವಿರುವ ಭಾಷೆಗಳಿಗಿಂತ ಭಾಷೆ ಭಿನ್ನವಾಗಿರಬಹುದು. ಕೆಲವು ಆ್ಯಪ್ಗಳು ಈ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬೆಂಬಲಿಸದಿರಬಹುದು."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"ಭಾಷೆಯ ಆಯ್ಕೆಯನ್ನು ಬೆಂಬಲಿಸುವ ಆ್ಯಪ್ಗಳನ್ನು ಮಾತ್ರ ಇಲ್ಲಿ ತೋರಿಸಲಾಗುತ್ತದೆ."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">ಆಯ್ಕೆಮಾಡಿದ ಭಾಷೆಗಳನ್ನು ತೆಗೆದುಹಾಕಬೇಕೇ?</item>
<item quantity="other">ಆಯ್ಕೆಮಾಡಿದ ಭಾಷೆಗಳನ್ನು ತೆಗೆದುಹಾಕಬೇಕೇ?</item>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 7ba3442..00c4ac4 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"시스템 기본값"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"설정에서 이 앱의 언어를 선택할 수 없습니다."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"언어가 앱에서 사용 가능한 언어와 다를 수 있습니다. 일부 앱에서는 이 설정을 지원하지 않을 수도 있습니다."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"언어 선택을 지원하는 앱만 여기에 표시됩니다."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">선택한 언어를 삭제하시겠습니까?</item>
<item quantity="one">선택한 언어를 삭제하시겠습니까?</item>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index e7bb0e3..872d5f4 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Системанын демейки параметрлери"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Бул колдонмонун тилин Жөндөөлөрдөн тандоого болбойт."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Тил колдонмодо жеткиликтүү тилдерден айырмаланышы мүмкүн. Бул жөндөө айрым колдонмолор тарабынан колдоого алынбайт болушу мүмкүн."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Бул жерде тил тандоого мүмкүн болгон колдонмолор гана көрсөтүлөт."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Тандалган тилдерди өчүрөсүзбү?</item>
<item quantity="one">Тандалган тилди өчүрөсүзбү?</item>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index f9efbf0..d770f56 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"ຄ່າເລີ່ມຕົ້ນຂອງລະບົບ"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"ບໍ່ສາມາດເລືອກພາສາສຳລັບແອັບນີ້ຈາກການຕັ້ງຄ່າໄດ້."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"ພາສາອາດແຕກຕ່າງໄປຈາກພາສາທີ່ສາມາດໃຊ້ໄດ້ໃນແອັບ. ບາງແອັບອາດບໍ່ຮອງຮັບການຕັ້ງຄ່ານີ້."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"ມີພຽງແອັບທີ່ຮອງຮັບການເລືອກພາສາທີ່ສະແດງຢູ່ບ່ອນນີ້."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">ລຶບພາສາທີ່ເລືອກບໍ?</item>
<item quantity="one">ລຶບພາສາທີ່ເລືອກບໍ?</item>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index d5abba9..b96e554 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -230,6 +230,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Numatytoji sistemos vertė"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Šios programos kalbos pasirinkimas nepasiekiamas iš skilties „Nustatymai“."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Kalba gali skirtis nuo programoje pasiekiamų kalbų. Kai kuriose programose šis nustatymas gali būti nepalaikomas."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Čia rodomos tik kalbos pasirinkimą palaikančios programos."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Pašalinti pasirinktas kalbas?</item>
<item quantity="few">Pašalinti pasirinktas kalbas?</item>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index f603fa8..6627b88 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Стандардно за системот"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Не може да се бира јазик за апликацијава од „Поставките“."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Јазикот може да се разликува од јазиците достапни во апликацијата. Некои апликации може да не ја поддржуваат оваа поставка."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Само апликациите што поддржуваат бирање јазик се прикажани овде."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Да се отстранат избраните јазици?</item>
<item quantity="other">Да се отстранат избраните јазици?</item>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index ffb5bec..33dbd7f 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"സിസ്റ്റം ഡിഫോൾട്ട്"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"ക്രമീകരണത്തിൽ നിന്ന് ഈ ആപ്പിനുള്ള ഭാഷ തിരഞ്ഞെടുക്കാനുള്ള ഓപ്ഷൻ ലഭ്യമല്ല."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"ആപ്പിൽ ലഭ്യമായ ഭാഷകളിൽ നിന്ന് ഭാഷ വ്യത്യാസപ്പെട്ടേക്കാം. ചില ആപ്പുകൾ ഈ ക്രമീകരണത്തെ പിന്തുണച്ചേക്കില്ല."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"ഭാഷാ സെലക്ഷൻ പിന്തുണയ്ക്കുന്ന ആപ്പുകൾ മാത്രമാണ് ഇവിടെ കാണിക്കുന്നത്."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">തിരഞ്ഞെടുത്ത ഭാഷകൾ നീക്കംചെയ്യണോ?</item>
<item quantity="one">തിരഞ്ഞെടുത്ത ഭാഷ നീക്കംചെയ്യണോ?</item>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index b93ea98..2f86f05 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Системийн өгөгдмөл"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Энэ аппын хэлийг Тохиргоо хэсгээс сонгох боломжгүй байна."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Хэл нь аппад боломжтой хэлээс шалтгаалан харилцан адилгүй байж болно. Зарим апп энэ тохиргоог дэмждэггүй байж магадгүй."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Зөвхөн хэлний сонголтыг дэмждэг аппуудыг энд харуулав."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Сонгосон хэлийг хасах уу?</item>
<item quantity="one">Сонгосон хэлийг хасах уу?</item>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 6ac9270..3b7ab98 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Lalai sistem"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Pemilihan bahasa untuk apl ini tidak tersedia daripada Tetapan."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Bahasa mungkin berbeza daripada bahasa yang tersedia dalam apl. Sesetengah apl mungkin tidak menyokong tetapan ini."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Hanya apl yang menyokong pemilihan bahasa dipaparkan di sini."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Alih keluar bahasa yang dipilih?</item>
<item quantity="one">Alih keluar bahasa yang dipilih?</item>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 7870be8..3dbb787 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"စနစ်မူရင်း"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"ဤအက်ပ်အတွက် ‘ဆက်တင်များ’ မှ ဘာသာစကား ရွေးချယ်မှု မရရှိနိုင်ပါ။"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"ဘာသာစကားသည် အက်ပ်တွင် ရရှိနိုင်သော ဘာသာစကားများမှ ကွဲပြားနိုင်သည်။ အချို့အက်ပ်များက ဤဆက်တင်ကို မပံ့ပိုးနိုင်ပါ။"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"ဘာသာစကားရွေးချယ်မှုကို ပံ့ပိုးသည့် အက်ပ်များကိုသာ ဤနေရာတွင် ပြထားသည်။"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">ရွေးထားသည့် ဘာသာစကားများကို ဖယ်ရှားမလား။</item>
<item quantity="one">ရွေးထားသည့် ဘာသာစကားကို ဖယ်ရှားမလား။</item>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 5060cc9..3929410 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Systeemstandaard"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Taalselectie voor deze app is niet beschikbaar via Instellingen."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"De taal kan verschillen van de beschikbare talen in de app. Sommige apps ondersteunen deze instelling mogelijk niet."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Hier zie je alleen apps die taalselectie ondersteunen."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Geselecteerde talen verwijderen?</item>
<item quantity="one">Geselecteerde taal verwijderen?</item>
diff --git a/res/values-or/arrays.xml b/res/values-or/arrays.xml
index 6ed8c8e..069eb48 100644
--- a/res/values-or/arrays.xml
+++ b/res/values-or/arrays.xml
@@ -485,7 +485,7 @@
<item msgid="8186970968968646288">"କ୍ୟାଶ୍ ହୋଇଥିବା (ଖାଲି)"</item>
</string-array>
<string-array name="color_picker">
- <item msgid="7216413848731287689">"ସାଇଆନ୍"</item>
+ <item msgid="7216413848731287689">"ସିଆନ୍"</item>
<item msgid="5661027589207588703">"ନୀଳ"</item>
<item msgid="1219738214736244749">"ସବୁଜ"</item>
<item msgid="6331809026622602308">"ବାଇଗଣୀ"</item>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 02389dc..ed5164d 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"ਸਿਸਟਮ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਸ ਐਪ ਲਈ ਭਾਸ਼ਾ ਦੀ ਚੋਣ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"ਭਾਸ਼ਾ ਐਪ ਵਿਚਲੀਆਂ ਉਪਲਬਧ ਭਾਸ਼ਾਵਾਂ ਨਾਲੋਂ ਵੱਖਰੀ ਹੋ ਸਕਦੀ ਹੈ। ਕੁਝ ਐਪਾਂ ਸ਼ਾਇਦ ਇਸ ਸੈਟਿੰਗਾਂ ਦਾ ਸਮਰਥਨ ਨਾ ਕਰਨ।"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"ਸਿਰਫ਼ ਉਹ ਐਪਾਂ ਹੀ ਇੱਥੇ ਦਿਖਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ ਜੋ ਭਾਸ਼ਾ ਦੀ ਚੋਣ ਦਾ ਸਮਰਥਨ ਕਰਦੀਆਂ ਹਨ।"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">ਕੀ ਚੁਣੀ ਗਈ ਭਾਸ਼ਾ ਨੂੰ ਹਟਾਉਣਾ ਹੈ?</item>
<item quantity="other">ਕੀ ਚੁਣੀਆਂ ਗਈਆਂ ਭਾਸ਼ਾਵਾਂ ਨੂੰ ਹਟਾਉਣਾ ਹੈ?</item>
diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml
index 494fae1..0f57759 100644
--- a/res/values-pt-rBR/strings.xml
+++ b/res/values-pt-rBR/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Padrão do sistema"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"A seleção de idioma para este app não está disponível nas configurações."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"O idioma pode ser diferente dos disponíveis no app. Alguns apps podem não ter suporte a essa configuração."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Apenas apps que têm suporte à seleção de idioma são mostrados aqui."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Remover o idioma selecionado?</item>
<item quantity="other">Remover idiomas selecionados?</item>
diff --git a/res/values-pt-rPT/arrays.xml b/res/values-pt-rPT/arrays.xml
index 1dbfaeb..c61e794 100644
--- a/res/values-pt-rPT/arrays.xml
+++ b/res/values-pt-rPT/arrays.xml
@@ -270,7 +270,7 @@
<item msgid="6485000384018554920">"volume do toque"</item>
<item msgid="3378000878531336372">"volume de multimédia"</item>
<item msgid="5272927168355895681">"volume de alarme"</item>
- <item msgid="4422070755065530548">"volume de notificação"</item>
+ <item msgid="4422070755065530548">"volume de notificações"</item>
<item msgid="3250654589277825306">"volume de Bluetooth"</item>
<item msgid="4212187233638382465">"Manter ativo"</item>
<item msgid="5099026183238335900">"monitorizar localização"</item>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 494fae1..0f57759 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Padrão do sistema"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"A seleção de idioma para este app não está disponível nas configurações."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"O idioma pode ser diferente dos disponíveis no app. Alguns apps podem não ter suporte a essa configuração."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Apenas apps que têm suporte à seleção de idioma são mostrados aqui."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Remover o idioma selecionado?</item>
<item quantity="other">Remover idiomas selecionados?</item>
diff --git a/res/values-ro/arrays.xml b/res/values-ro/arrays.xml
index e6409d7..cabcb09 100644
--- a/res/values-ro/arrays.xml
+++ b/res/values-ro/arrays.xml
@@ -387,8 +387,8 @@
<item msgid="5012882784126308133">"Majuscule mici"</item>
</string-array>
<string-array name="captioning_font_size_selector_titles">
- <item msgid="923916134548435468">"Foarte mic"</item>
- <item msgid="5738147437573674872">"Mic"</item>
+ <item msgid="923916134548435468">"Foarte mică"</item>
+ <item msgid="5738147437573674872">"Mică"</item>
<item msgid="4691660235626027304">"Medie"</item>
<item msgid="824386705928670045">"Mare"</item>
<item msgid="2790561781512874585">"Foarte mare"</item>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 69ad41e..1b3f615 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -229,6 +229,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Prestabilit de sistem"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Selectarea limbii pentru această aplicație din Setări nu este disponibilă."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Limba poate fi alta decât limbile disponibile în aplicație. Este posibil ca unele aplicații să nu accepte această setare."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Aici sunt afișate numai aplicațiile care acceptă selectarea limbii."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="few">Eliminați limbile selectate?</item>
<item quantity="other">Eliminați limbile selectate?</item>
diff --git a/res/values-si/arrays.xml b/res/values-si/arrays.xml
index 976b790..a8bf675 100644
--- a/res/values-si/arrays.xml
+++ b/res/values-si/arrays.xml
@@ -296,7 +296,7 @@
<item msgid="2504191192460059817">"තිරය ක්රියාත්මක කිරීම"</item>
<item msgid="7905819538788103556">"ගිණුම් ලබා ගැනීම"</item>
<item msgid="1675025662248079254">"පසුබිමෙහි ධාවනය"</item>
- <item msgid="2553974920157061225">"ප්රවේශ්යතා හඬ පරිමාව"</item>
+ <item msgid="2553974920157061225">"ප්රවේශ්යතා හඬ"</item>
</string-array>
<string-array name="app_ops_labels">
<item msgid="7780927354556651567">"ස්ථානය"</item>
@@ -363,7 +363,7 @@
<item msgid="4281352581602735717">"තිරය ක්රියාත්මක කිරීම"</item>
<item msgid="346122795998225472">"ගිණුම් ලබා ගැනීම"</item>
<item msgid="3756073389408535680">"පසුබිමෙහි ධාවනය"</item>
- <item msgid="2114661179947426734">"ප්රවේශ්යතා හඬ පරිමාව"</item>
+ <item msgid="2114661179947426734">"ප්රවේශ්යතා හඬ"</item>
</string-array>
<string-array name="long_press_timeout_selector_titles">
<item msgid="6926391290986427331">"කොට"</item>
diff --git a/res/values-sl/arrays.xml b/res/values-sl/arrays.xml
index c39a0bc..ca80126 100644
--- a/res/values-sl/arrays.xml
+++ b/res/values-sl/arrays.xml
@@ -424,7 +424,7 @@
<item msgid="6922258575853746220">"Poteza"</item>
</string-array>
<string-array name="accessibility_button_size_selector_titles">
- <item msgid="7482952318152486459">"Majhen"</item>
+ <item msgid="7482952318152486459">"Majhna"</item>
<item msgid="1666628329913333563">"Velik"</item>
</string-array>
<string-array name="vpn_types_long">
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index cd288a9..39f7092 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -230,6 +230,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Sistemsko privzeto"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"V nastavitvah ni na voljo izbire jezika za to aplikacijo."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Jezik se morda razlikuje od jezikov, ki so na voljo v aplikaciji. Nekatere aplikacije morda ne podpirajo te nastavitve."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Tukaj so prikazane samo aplikacije, ki podpirajo izbiro jezika."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Želite odstraniti izbrane jezike?</item>
<item quantity="two">Želite odstraniti izbrane jezike?</item>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index a6df705..cd5d70b 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Parazgjedhja e sistemit"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Zgjedhja e gjuhës për këtë aplikacion nuk ofrohet nga \"Cilësimet\"."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Gjuha mund të ndryshojë nga gjuhët që ofrohen në aplikacion. Disa aplikacione mund të mos e mbështetin këtë cilësim."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Vetëm aplikacionet që mbështetin zgjedhjen e gjuhës shfaqen këtu."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Të hiqet gjuha e zgjedhur?</item>
<item quantity="one">Të hiqet gjuha e zgjedhur?</item>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index b5805ae..adab5b5 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -229,6 +229,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Подразумевани системски"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Избор језика за ову апликацију није доступан из Подешавања."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Језик може да се разликује од језика доступних у апликацији. Неке апликације можда не подржавају ово подешавање."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Овде се приказују само апликације које подржавају избор језика."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Желите ли да уклоните изабране језике?</item>
<item quantity="few">Желите ли да уклоните изабране језике?</item>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 5e11d62..7db27e0 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Systemets standardinställning"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Det går inte att välja språk för den här appen i Inställningar."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Alla språk kanske inte är tillgängliga i appen. Vissa appar kanske inte har stöd för denna inställning."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Endast appar som har stöd för språkval visas här."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Vill du ta bort de valda språken?</item>
<item quantity="one">Vill du ta bort det valda språket?</item>
diff --git a/res/values-sw/arrays.xml b/res/values-sw/arrays.xml
index 366c8b6..e3434d0 100644
--- a/res/values-sw/arrays.xml
+++ b/res/values-sw/arrays.xml
@@ -288,7 +288,7 @@
<item msgid="1745447762712473288">"tumia sip"</item>
<item msgid="2986821801246709737">"chakata simu uliyopiga"</item>
<item msgid="2702338156976571452">"alama ya kidole"</item>
- <item msgid="7925495329948404955">"vitambua shughuli za mwili"</item>
+ <item msgid="7925495329948404955">"vitambuzi vya shughuli za mwili"</item>
<item msgid="8163066895749904470">"soma matangazo ya simu"</item>
<item msgid="7621394050624063528">"eneo la jaribio"</item>
<item msgid="37519917674959757">"soma hifadhi"</item>
@@ -355,7 +355,7 @@
<item msgid="9143978647977300187">"Tumia sip"</item>
<item msgid="3053060162752878562">"Chakata simu uliyopiga"</item>
<item msgid="4480721672278100858">"Alama ya kidole"</item>
- <item msgid="7883743426029759112">"Vitambua shughuli za mwili"</item>
+ <item msgid="7883743426029759112">"Vitambuzi vya shughuli za mwili"</item>
<item msgid="2546206711741159825">"Soma matangazo ya simu"</item>
<item msgid="2363460595607829243">"Eneo la jaribio"</item>
<item msgid="3778165903878569143">"Soma hifadhi"</item>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index a11af1e..01f5116 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Chaguomsingi la mfumo"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Chaguo la lugha kwa programu hii halipatikani kwenye Mipangilio."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Huenda lugha ikatofautiana na zinazopatikana katika programu. Huenda baadhi ya programu zisiwe na uwezo wa kutumia mipangilio hii."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Programu zinazotumia chaguo la lugha ndizo zinazoonyeshwa hapa."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Ungependa kuondoa lugha zilizochaguliwa?</item>
<item quantity="one">Ungependa kuondoa lugha iliyochaguliwa?</item>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 2f6c37a..8a24e7e 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"சிஸ்டத்தின் இயல்பு"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"அமைப்புகளில் இந்த ஆப்ஸுக்கான மொழித் தேர்வு கிடைக்கவில்லை."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"ஆப்ஸில் இருக்கும் மொழிகளிலிருந்து மொழி வேறுபடலாம். சில ஆப்ஸில் இந்த அமைப்பைப் பயன்படுத்த முடியாது."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"மொழித் தேர்வை ஆதரிக்கும் ஆப்ஸ் மட்டும் இங்கே காட்டப்படும்."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">தேர்ந்தெடுத்த மொழிகளை அகற்றவா?</item>
<item quantity="one">தேர்ந்தெடுத்த மொழியை அகற்றவா?</item>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 4168a67..7b3d21c 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"సిస్టమ్ ఆటోమేటిక్ సెట్టింగ్"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"ఈ యాప్ కోసం భాష ఎంపిక సెట్టింగ్లలో అందుబాటులో లేదు."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"యాప్లో అందుబాటులో ఉన్న భాషలకు భాష భిన్నంగా ఉండవచ్చు. కొన్ని యాప్లు ఈ సెట్టింగ్కు సపోర్ట్ చేయకపోవచ్చు."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"భాష ఎంపికను సపోర్ట్ చేసే యాప్లు మాత్రమే ఇక్కడ చూపబడతాయి."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">ఎంచుకున్న భాషలను తీసివేయాలా?</item>
<item quantity="one">ఎంచుకున్న భాషను తీసివేయాలా?</item>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 5acf18a..fde49f6 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"ค่าเริ่มต้นของระบบ"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"การเลือกภาษาสำหรับแอปนี้ไม่พร้อมให้ใช้งานจากการตั้งค่า"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"ภาษาอาจแตกต่างจากที่ให้บริการในแอป บางแอปอาจไม่รองรับการตั้งค่านี้"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"ส่วนนี้แสดงเฉพาะแอปที่รองรับการเลือกภาษา"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">นำภาษาที่เลือกออกไหม</item>
<item quantity="one">นำภาษาที่เลือกออกไหม</item>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index b944178..f031d15 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Default ng system"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Hindi available sa Mga Setting ang pagpili ng wika para sa app na ito."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Posibleng iba ang wika sa mga wikang available sa app. Posibleng hindi suportahan ng ilang app ang setting na ito."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Mga app lang na sumusuporta sa pagpili ng wika ang ipinapakita dito."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Alisin ang mga piniling wika?</item>
<item quantity="other">Alisin ang mga piniling wika?</item>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 530d5ca..8effefe 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Sistem varsayılanı"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Ayarlar\'da bu uygulama için dil seçimi mevcut değil."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Dil, uygulamada bulunan dillerden farklı olabilir. Bazı uygulamalar bu ayarı desteklemeyebilir."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Yalnızca dil seçimini destekleyen uygulamalar burada görünür."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Seçilen diller kaldırılsın mı?</item>
<item quantity="one">Seçilen dil kaldırılsın mı?</item>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 99ee7d4..c2ae814 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"سسٹم ڈیفالٹ"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"اس ایپ کے لیے زبان کا انتخاب ترتیبات سے دستیاب نہیں ہے۔"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"زبان ایپ میں دستیاب زبانوں سے مختلف ہو سکتی ہے۔ ہو سکتا ہے کچھ ایپس اس ترتیب کو سپورٹ نہ کریں۔"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"یہاں صرف ان ایپس کی فہرست دکھائی جاتی ہے جو زبان کے انتخاب کو سپورٹ کرتی ہیں۔"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">منتخب کردہ زبانیں ہٹائیں؟</item>
<item quantity="one">منتخب کردہ زبان ہٹائیں؟</item>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index ad34078..5616191 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Tizim standarti"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Bu ilova uchun Sozlamalardan tilni tanlash imkonsiz"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Bu til ilovadagi tillardan farq qilishi mumkin. Ayrim ilovalarda bu sozlama ishlamaydi."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Faqat til tanlash imkoni bor ilovalar shu yerda chiqadi."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Tanlangan tillar olib tashlansinmi?</item>
<item quantity="one">Tanlangan til olib tashlansinmi?</item>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index f09096b..6a69f4d 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Theo chế độ mặc định của hệ thống"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Bạn chưa thể chọn ngôn ngữ cho ứng dụng này trong phần Cài đặt."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Ngôn ngữ có thể khác với ngôn ngữ có sẵn trong ứng dụng. Một số ứng dụng có thể không hỗ trợ cài đặt này."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Chỉ những ứng dụng hỗ trợ lựa chọn ngôn ngữ mới được hiển thị."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">Xóa các ngôn ngữ đã chọn?</item>
<item quantity="one">Xóa ngôn ngữ đã chọn?</item>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 7a23a7d..068eb8b 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"系统默认设置"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"您无法从“设置”中选择此应用的语言。"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"语言可能与应用中可用的语言不同。部分应用可能不支持此设置。"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"此处仅显示支持选择语言的应用。"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">要移除所选语言吗?</item>
<item quantity="one">要移除所选语言吗?</item>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index dc2a11d..7de398d 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"系統預設"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"「設定」中不提供此應用程式的語言選擇。"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"可用的語言可能與應用程式支援的語言不同,部分應用程式可能不支援此設定。"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"這裡只會顯示支援語言選擇的應用程式。"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">要移除選取的語言嗎?</item>
<item quantity="one">要移除選取的語言嗎?</item>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 0e6a2d0..52fa6a9 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"系統預設"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"無法從「設定」選取這個應用程式的語言。"</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"可用的語言可能與應用程式支援的語言不同,某些應用程式可能不支援這項設定。"</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"只有可讓使用者選取語言的應用程式才會顯示在這裡。"</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="other">要移除所選語言嗎?</item>
<item quantity="one">要移除所選語言嗎?</item>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index e033103..d6a1480 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -228,6 +228,7 @@
<string name="preference_of_system_locale_summary" msgid="5612241394431188535">"Okuzenzakalelayo kwesistimu"</string>
<string name="desc_no_available_supported_locale" msgid="7883271726226947273">"Ukukhetha ulimi kwale app akutholakali Kumasethingi."</string>
<string name="desc_app_locale_disclaimer" msgid="5295933110644789052">"Ulimi lungahluka ezilimini ezitholakala ku-app. Amanye ama-app angase angalisekeli leli sethingi."</string>
+ <string name="desc_app_locale_selection_supported" msgid="6149467826636295127">"Ama-app asekela ukukhethwa kolimi kuphela aboniswa lapha."</string>
<plurals name="dlg_remove_locales_title" formatted="false" msgid="2845515796732609837">
<item quantity="one">Susa izilimi ezikhethiwe?</item>
<item quantity="other">Susa izilimi ezikhethiwe?</item>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 1582d21..b88d01d 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -152,6 +152,12 @@
<dimen name="homepage_preference_icon_padding_start_two_pane">8dp</dimen>
<dimen name="homepage_preference_text_padding_start">16dp</dimen>
<dimen name="homepage_preference_text_padding_start_two_pane">24dp</dimen>
+ <dimen name="homepage_app_bar_corner_radius">32dp</dimen>
+ <dimen name="homepage_app_bar_padding_two_pane">6dp</dimen>
+ <!-- bottom: search_bar_margin - homepage_app_bar_padding_two_pane -->
+ <dimen name="homepage_app_bar_margin_bottom_two_pane">10dp</dimen>
+ <!-- horizontal: homepage_padding_horizontal_two_pane - homepage_app_bar_padding_two_pane -->
+ <dimen name="homepage_app_bar_margin_horizontal_two_pane">18dp</dimen>
<!-- Dimensions for Wifi Assistant Card -->
<dimen name="wifi_assistant_padding_top_bottom">16dp</dimen>
@@ -485,4 +491,9 @@
<!-- Sims/Data mobile/Calls/SMS select dialog-->
<dimen name="sims_select_margin_bottom">24dp</dimen>
<dimen name="sims_select_margin_top">8dp</dimen>
+
+ <!-- QR code picture size -->
+ <dimen name="qrcode_preview_margin">40dp</dimen>
+ <dimen name="qrcode_preview_radius">30dp</dimen>
+ <dimen name="qrcode_icon_size">27dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9ab0cc2..6a0fad2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -518,6 +518,9 @@
<!-- Description for the disclaimer of per app language. [CHAR LIMIT=NONE]-->
<string name="desc_app_locale_disclaimer">Language may differ from languages available in the app. Some apps may not support this setting.</string>
+ <!-- Description for introduction of the locale selection supported of app list [CHAR LIMIT=NONE]-->
+ <string name="desc_app_locale_selection_supported">Only apps that support language selection are shown here.</string>
+
<!-- The title of the confirmation dialog shown when the user selects one / several languages and tries to remove them [CHAR LIMIT=60] -->
<plurals name="dlg_remove_locales_title">
<item quantity="one">Remove selected language?</item>
@@ -1297,7 +1300,10 @@
<string name="security_advanced_settings_no_work_profile_settings_summary">Encryption, credentials, and more</string>
<!-- Search keywords for the "More security settings" section in security settings. [CHAR_LIMIT=NONE] -->
<string name="security_advanced_settings_keywords">security, more security settings, more settings, advanced security settings</string>
-
+ <!-- Title for the section that has additional privacy settings. [CHAR LIMIT=60] -->
+ <string name="privacy_advanced_settings">More privacy settings</string>
+ <!-- Title for the section that has additional privacy settings. [CHAR LIMIT=60] -->
+ <string name="privacy_advanced_settings_summary">Autofill, activity controls, and more</string>
<!-- Text shown when "Add fingerprint" button is disabled -->
<string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
@@ -8610,7 +8616,7 @@
<string name="spatial_audio_wired_headphones">Wired headphones</string>
<!-- Sound: Summary for the spatializer effect. [CHAR LIMIT=NONE]-->
- <string name="spatial_audio_text">Spatial Audio creates immersive sound that seems like it’s coming from all around you. Only works with some media.</string>
+ <string name="spatial_audio_text">Audio from compatible media becomes more immersive</string>
<!-- Sound: Summary for the Spatial audio setting when it is off. [CHAR LIMIT=NONE]-->
<string name="spatial_summary_off">Off</string>
@@ -8621,6 +8627,12 @@
<!-- Sound: Summary for the Spatial audio setting when it is on with two output devices enabled. [CHAR LIMIT=NONE]-->
<string name="spatial_summary_on_two">On / <xliff:g id="output device" example="Phone speaker">%1$s</xliff:g> and <xliff:g id="output device" example="Wired headphones">%2$s</xliff:g></string>
+ <!-- Sound: Footer message for the Spatial audio setting. [CHAR LIMIT=NONE]-->
+ <string name="spatial_audio_footer_title">You can also turn on Spatial Audio for Bluetooth devices.</string>
+
+ <!-- Sound: Footer hyperlink text to launch the Connected devices settings page. [CHAR LIMIT=NONE]-->
+ <string name="spatial_audio_footer_learn_more_text">Connected devices settings</string>
+
<!-- Sound: Summary for the Do not Disturb option that describes how many automatic rules (schedules) are enabled [CHAR LIMIT=NONE]-->
<string name="zen_mode_settings_schedules_summary">
{count, plural,
@@ -8973,6 +8985,9 @@
<!-- Configure Notifications: Work profile section header [CHAR LIMIT=30] -->
<string name="profile_section_header">Work notifications</string>
+ <!-- Configure Notifications: Work profile section header [CHAR LIMIT=30] -->
+ <string name="profile_section_header_for_advanced_privacy">Work profile</string>
+
<!-- Configure Notifications: section header for prioritizer settings [CHAR LIMIT=80] -->
<string name="smart_notifications_title">Adaptive notifications</string>
@@ -13649,7 +13664,9 @@
<string name="default_active_sim_mobile_data">mobile data</string>
<!-- Provider Model: Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off and Wi-Fi
scanning is on. To mark a link to bring the user to "scanning settings" screen. [CHAR LIMIT=NONE]-->
- <string name="wifi_scan_notify_message">To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. This can be used, for example, to improve location-based features and services. You can change this in Wi\u2011Fi scanning settings. <annotation id="link">Change</annotation></string>
+ <string name="wifi_scan_notify_message">To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. This can be used, for example, to improve location-based features and services. You can change this in Wi\u2011Fi scanning settings.</string>
+ <!-- Provider Model: Link text to bring the user to "scanning settings" screen. [CHAR LIMIT=NONE]-->
+ <string name="wifi_scan_change">Change</string>
<!-- Summary text separator for preferences including a short description
(eg. "Connected / 5G"). [CHAR LIMIT=50] -->
@@ -14163,4 +14180,11 @@
<string name="find_broadcast_password_dialog_connection_error">Can\u2019t connect. Try again.</string>
<!-- The error message of enter password dialog in bluetooth find broadcast page [CHAR LIMIT=none] -->
<string name="find_broadcast_password_dialog_password_error">Wrong password</string>
+
+
+ <!-- [CHAR LIMIT=NONE] Le audio QR code scanner sub-title -->
+ <string name="bt_le_audio_scan_qr_code_scanner">To start listening, center the QR code below</string>
+ <!-- [CHAR LIMIT=NONE] Hint for QR code process failure -->
+ <string name="bt_le_audio_qr_code_is_not_valid_format">QR code isn\u0027t a valid format</string>
+
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 7a87993..f147ce9 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -962,4 +962,11 @@
<item name="android:minWidth">0dp</item>
<item name="android:textAllCaps">false</item>
</style>
+
+ <style name="QrCodeScanner">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textDirection">locale</item>
+ </style>
</resources>
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index f6c0af6..f330b19 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -47,6 +47,11 @@
settings:allowDividerBelow="true"/>
<com.android.settings.slices.SlicePreference
+ android:key="bt_extra_control"
+ settings:controller="com.android.settings.slices.SlicePreferenceController"
+ settings:allowDividerAbove="true"/>
+
+ <com.android.settings.slices.SlicePreference
android:key="bt_device_slice"
settings:controller="com.android.settings.slices.BlockingSlicePrefController"
settings:allowDividerBelow="true"
@@ -61,6 +66,18 @@
<PreferenceCategory
android:key="bluetooth_profiles"/>
+ <PreferenceCategory
+ android:key="bluetooth_related_tools"
+ android:title="@string/bluetooth_screen_related">
+ <Preference
+ android:key="live_caption"
+ android:icon="@drawable/ic_live_caption"
+ android:persistent="false"
+ android:summary="@string/live_caption_summary"
+ android:title="@string/live_caption_title"
+ settings:controller="com.android.settings.accessibility.LiveCaptionPreferenceController"/>
+ </PreferenceCategory>
+
<com.android.settingslib.widget.FooterPreference
android:key="device_details_footer"
android:selectable="false"
diff --git a/res/xml/privacy_advanced_settings.xml b/res/xml/privacy_advanced_settings.xml
new file mode 100644
index 0000000..9f465d4
--- /dev/null
+++ b/res/xml/privacy_advanced_settings.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:key="privacy_dashboard_page"
+ android:title="@string/privacy_advanced_settings">
+
+ <!-- Work Policy info -->
+ <Preference
+ android:key="work_policy_info"
+ android:title="@string/work_policy_privacy_settings"
+ android:summary="@string/work_policy_privacy_settings_summary"
+ settings:controller="com.android.settings.privacy.WorkPolicyInfoPreferenceController"/>
+
+ <!-- Connected work and personal apps -->
+ <Preference
+ android:key="interact_across_profiles_privacy"
+ android:title="@string/interact_across_profiles_title"
+ android:fragment="com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesSettings"
+ settings:searchable="false"
+ settings:controller="com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesController" />
+
+ <!-- Accessibility usage -->
+ <Preference
+ android:key="privacy_accessibility_usage"
+ android:title="@string/accessibility_usage_title"
+ settings:controller="com.android.settings.privacy.AccessibilityUsagePreferenceController">
+ <intent android:action="android.intent.action.REVIEW_ACCESSIBILITY_SERVICES"/>
+ </Preference>
+
+ <!-- On lock screen notifications -->
+ <com.android.settings.RestrictedListPreference
+ android:key="privacy_lock_screen_notifications"
+ android:title="@string/lock_screen_notifs_title"
+ android:summary="@string/summary_placeholder"
+ settings:searchable="false"/>
+
+ <!-- Privacy Service -->
+ <PreferenceCategory
+ android:key="privacy_services"
+ android:layout="@layout/preference_category_no_label"/>
+
+ <PreferenceCategory
+ android:key="dashboard_tile_placeholder"/>
+
+ <!-- Work profile settings are at the bottom with high order value to avoid users thinking that
+ any of the above settings (including dynamic) are specific to the work profile. -->
+ <PreferenceCategory
+ android:key="privacy_work_profile_notifications_category"
+ android:title="@string/profile_section_header_for_advanced_privacy"
+ android:order="998">
+
+ <com.android.settings.RestrictedListPreference
+ android:key="privacy_lock_screen_work_profile_notifications"
+ android:title="@string/locked_work_profile_notification_title"
+ android:summary="@string/summary_placeholder"
+ android:order="999"
+ settings:searchable="false"/>
+ </PreferenceCategory>
+
+ <!-- Content Capture -->
+
+ <!-- NOTE: content capture has a different preference, depending whether or not the
+ ContentCaptureService implementations defines a custom settings activitiy on its manifest.
+ Hence, we show both here, but the controller itself will decide if it's available or not.
+ -->
+
+ <SwitchPreference
+ android:key="content_capture"
+ android:title="@string/content_capture"
+ android:summary="@string/content_capture_summary"
+ settings:controller="com.android.settings.privacy.EnableContentCapturePreferenceController"/>
+
+ <com.android.settingslib.PrimarySwitchPreference
+ android:key="content_capture_custom_settings"
+ android:title="@string/content_capture"
+ android:summary="@string/content_capture_summary"
+ settings:controller="com.android.settings.privacy.EnableContentCaptureWithServiceSettingsPreferenceController"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/spatial_audio_settings.xml b/res/xml/spatial_audio_settings.xml
index da33986..13d3b25 100644
--- a/res/xml/spatial_audio_settings.xml
+++ b/res/xml/spatial_audio_settings.xml
@@ -34,4 +34,9 @@
android:title="@string/spatial_audio_wired_headphones"
settings:controller="com.android.settings.notification.SpatialAudioWiredHeadphonesController"/>
+ <com.android.settingslib.widget.FooterPreference
+ android:key="spatial_audio_footer"
+ android:title="@string/spatial_audio_footer_title"
+ android:selectable="false"
+ settings:searchable="false"/>
</PreferenceScreen>
diff --git a/res/xml/wifi_calling_settings.xml b/res/xml/wifi_calling_settings.xml
index 902ff1a..c45f702 100644
--- a/res/xml/wifi_calling_settings.xml
+++ b/res/xml/wifi_calling_settings.xml
@@ -19,6 +19,10 @@
android:key="wifi_calling_settings"
android:title="@string/wifi_calling_settings_title">
+ <com.android.settings.widget.SettingsMainSwitchPreference
+ android:key="wifi_calling_switch_bar"
+ android:title="@string/wifi_calling_main_switch_title" />
+
<com.android.settings.wifi.calling.ListWithEntrySummaryPreference
android:key="wifi_calling_mode"
isPreferenceVisible="false"
diff --git a/src/com/android/settings/DefaultRingtonePreference.java b/src/com/android/settings/DefaultRingtonePreference.java
index 914c4b2..824a5a0 100644
--- a/src/com/android/settings/DefaultRingtonePreference.java
+++ b/src/com/android/settings/DefaultRingtonePreference.java
@@ -46,6 +46,11 @@
@Override
protected void onSaveRingtone(Uri ringtoneUri) {
+ if (ringtoneUri == null) {
+ setActualDefaultRingtoneUri(ringtoneUri);
+ return;
+ }
+
String mimeType = getContext().getContentResolver().getType(ringtoneUri);
if (mimeType == null) {
Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 9f191f6..ee0743a 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -16,6 +16,8 @@
package com.android.settings;
+import static android.provider.Settings.ACTION_PRIVACY_SETTINGS;
+
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@@ -214,7 +216,8 @@
/** Redirects to SafetyCenter if enabled. */
@VisibleForTesting
public void handleSafetyCenterRedirection() {
- if (SafetyCenterManagerWrapper.get().isEnabled(this)) {
+ if (ACTION_PRIVACY_SETTINGS.equals(getIntent().getAction())
+ && SafetyCenterManagerWrapper.get().isEnabled(this)) {
try {
startActivity(new Intent(Intent.ACTION_SAFETY_CENTER));
finish();
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 4e2088e..f5fb26c 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -34,6 +34,7 @@
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.graphics.drawable.Icon;
@@ -152,6 +153,8 @@
*/
public static final String EXTRA_IS_FROM_SLICE = "is_from_slice";
+ public static final String EXTRA_USER_HANDLE = "user_handle";
+
/**
* Personal or Work profile tab of {@link ProfileSelectFragment}
* <p>0: Personal tab.
@@ -427,7 +430,14 @@
}
try {
- startActivity(trampolineIntent);
+ final UserManager um = getSystemService(UserManager.class);
+ final UserInfo userInfo = um.getUserInfo(getUser().getIdentifier());
+ if (userInfo.isManagedProfile()) {
+ trampolineIntent.putExtra(EXTRA_USER_HANDLE, getUser());
+ startActivityAsUser(trampolineIntent, um.getPrimaryUser().getUserHandle());
+ } else {
+ startActivity(trampolineIntent);
+ }
} catch (ActivityNotFoundException e) {
Log.e(LOG_TAG, "Deep link homepage is not available to show 2-pane UI");
return false;
diff --git a/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java
index 8f0ca3e..3dde687 100644
--- a/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java
+++ b/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java
@@ -38,13 +38,15 @@
import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SubSettingLauncher;
+import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
-import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
@@ -53,7 +55,7 @@
* Controller that shows and updates the bluetooth device name
*/
public class AccessibilityHearingAidPreferenceController extends BasePreferenceController
- implements LifecycleObserver, OnStart, OnStop {
+ implements LifecycleObserver, OnStart, OnStop, BluetoothCallback {
private static final String TAG = "AccessibilityHearingAidPreferenceController";
private Preference mHearingAidPreference;
@@ -82,15 +84,13 @@
private final LocalBluetoothManager mLocalBluetoothManager;
private final BluetoothAdapter mBluetoothAdapter;
- //cache value of supporting hearing aid or not
- private boolean mHearingAidProfileSupported;
+
private FragmentManager mFragmentManager;
public AccessibilityHearingAidPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mLocalBluetoothManager = getLocalBluetoothManager();
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- mHearingAidProfileSupported = isHearingAidProfileSupported();
}
@Override
@@ -101,29 +101,27 @@
@Override
public int getAvailabilityStatus() {
- return mHearingAidProfileSupported ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ return isHearingAidProfileSupported() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public void onStart() {
- if (mHearingAidProfileSupported) {
- IntentFilter filter = new IntentFilter();
- filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
- filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
- mContext.registerReceiver(mHearingAidChangedReceiver, filter);
- }
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+ filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ mContext.registerReceiver(mHearingAidChangedReceiver, filter);
+ mLocalBluetoothManager.getEventManager().registerCallback(this);
}
@Override
public void onStop() {
- if (mHearingAidProfileSupported) {
- mContext.unregisterReceiver(mHearingAidChangedReceiver);
- }
+ mContext.unregisterReceiver(mHearingAidChangedReceiver);
+ mLocalBluetoothManager.getEventManager().unregisterCallback(this);
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
- if (TextUtils.equals(preference.getKey(), getPreferenceKey())){
+ if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
final CachedBluetoothDevice device = getConnectedHearingAidDevice();
if (device == null) {
launchHearingAidInstructionDialog();
@@ -141,7 +139,38 @@
if (device == null) {
return mContext.getText(R.string.accessibility_hearingaid_not_connected_summary);
}
- return device.getName();
+
+ final int connectedNum = getConnectedHearingAidDeviceNum();
+ final CharSequence name = device.getName();
+ final int side = device.getDeviceSide();
+ final CachedBluetoothDevice subDevice = device.getSubDevice();
+ if (connectedNum > 1) {
+ return mContext.getString(R.string.accessibility_hearingaid_more_device_summary, name);
+ }
+ if (subDevice != null && subDevice.isConnected()) {
+ return mContext.getString(
+ R.string.accessibility_hearingaid_left_and_right_side_device_summary, name);
+ }
+ if (side == HearingAidProfile.DeviceSide.SIDE_INVALID) {
+ return mContext.getString(
+ R.string.accessibility_hearingaid_active_device_summary, name);
+ }
+ return (side == HearingAidProfile.DeviceSide.SIDE_LEFT)
+ ? mContext.getString(
+ R.string.accessibility_hearingaid_left_side_device_summary, name)
+ : mContext.getString(
+ R.string.accessibility_hearingaid_right_side_device_summary, name);
+ }
+
+ @Override
+ public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
+ if (activeDevice == null) {
+ return;
+ }
+
+ if (bluetoothProfile == BluetoothProfile.HEARING_AID) {
+ HearingAidUtils.launchHearingAidPairingDialog(mFragmentManager, activeDevice);
+ }
}
public void setFragmentManager(FragmentManager fragmentManager) {
@@ -150,33 +179,44 @@
@VisibleForTesting
CachedBluetoothDevice getConnectedHearingAidDevice() {
- if (!mHearingAidProfileSupported) {
+ if (!isHearingAidProfileSupported()) {
return null;
}
- if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
- return null;
- }
- final List<BluetoothDevice> deviceList = mLocalBluetoothManager.getProfileManager()
- .getHearingAidProfile().getConnectedDevices();
- final Iterator it = deviceList.iterator();
- while (it.hasNext()) {
- BluetoothDevice obj = (BluetoothDevice)it.next();
- if (!mLocalBluetoothManager.getCachedDeviceManager().isSubDevice(obj)) {
- return mLocalBluetoothManager.getCachedDeviceManager().findDevice(obj);
+
+ final CachedBluetoothDeviceManager deviceManager =
+ mLocalBluetoothManager.getCachedDeviceManager();
+ final HearingAidProfile hearingAidProfile =
+ mLocalBluetoothManager.getProfileManager().getHearingAidProfile();
+ final List<BluetoothDevice> deviceList = hearingAidProfile.getConnectedDevices();
+ for (BluetoothDevice obj : deviceList) {
+ if (!deviceManager.isSubDevice(obj)) {
+ return deviceManager.findDevice(obj);
}
}
return null;
}
+ private int getConnectedHearingAidDeviceNum() {
+ if (!isHearingAidProfileSupported()) {
+ return 0;
+ }
+
+ final CachedBluetoothDeviceManager deviceManager =
+ mLocalBluetoothManager.getCachedDeviceManager();
+ final HearingAidProfile hearingAidProfile =
+ mLocalBluetoothManager.getProfileManager().getHearingAidProfile();
+ final List<BluetoothDevice> deviceList = hearingAidProfile.getConnectedDevices();
+ return (int) deviceList.stream()
+ .filter(device -> !deviceManager.isSubDevice(device))
+ .count();
+ }
+
private boolean isHearingAidProfileSupported() {
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
return false;
}
final List<Integer> supportedList = mBluetoothAdapter.getSupportedProfiles();
- if (supportedList.contains(BluetoothProfile.HEARING_AID)) {
- return true;
- }
- return false;
+ return supportedList.contains(BluetoothProfile.HEARING_AID);
}
private LocalBluetoothManager getLocalBluetoothManager() {
diff --git a/src/com/android/settings/accessibility/HearingAidUtils.java b/src/com/android/settings/accessibility/HearingAidUtils.java
new file mode 100644
index 0000000..a3d2c93
--- /dev/null
+++ b/src/com/android/settings/accessibility/HearingAidUtils.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 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 android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.settings.bluetooth.HearingAidPairingDialogFragment;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+
+/** Provides utility methods related hearing aids. */
+public final class HearingAidUtils {
+ private static final String TAG = "HearingAidUtils";
+
+ private HearingAidUtils(){}
+
+ /**
+ * Launches pairing dialog when hearing aid device needs other side of hearing aid device to
+ * work.
+ *
+ * @param fragmentManager The {@link FragmentManager} used to show dialog fragment
+ * @param device The {@link CachedBluetoothDevice} need to be hearing aid device
+ */
+ public static void launchHearingAidPairingDialog(FragmentManager fragmentManager,
+ @NonNull CachedBluetoothDevice device) {
+ if (device.isConnectedHearingAidDevice()
+ && device.getDeviceMode() == HearingAidProfile.DeviceMode.MODE_BINAURAL
+ && device.getSubDevice() == null) {
+ launchHearingAidPairingDialogInternal(fragmentManager, device);
+ }
+ }
+
+ private static void launchHearingAidPairingDialogInternal(FragmentManager fragmentManager,
+ @NonNull CachedBluetoothDevice device) {
+ if (device.getDeviceSide() == HearingAidProfile.DeviceSide.SIDE_INVALID) {
+ Log.w(TAG, "Can not launch hearing aid pairing dialog for invalid side");
+ return;
+ }
+ HearingAidPairingDialogFragment.newInstance(device).show(fragmentManager,
+ HearingAidPairingDialogFragment.TAG);
+ }
+}
diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
index 930fbe4..6ead390 100644
--- a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
@@ -27,8 +27,11 @@
import com.android.settings.R;
import com.android.settingslib.Utils;
+import com.android.settingslib.widget.LayoutPreference;
import com.google.android.setupdesign.GlifPreferenceLayout;
+import com.google.android.setupdesign.util.LayoutStyler;
+
/**
* A {@link androidx.preference.PreferenceFragmentCompat} that displays the settings page related
@@ -47,6 +50,8 @@
icon.setTintList(Utils.getColorAttr(getContext(), android.R.attr.colorPrimary));
AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title,
/* description= */ null, icon);
+
+ updateResetButtonPadding();
}
@Override
@@ -66,4 +71,14 @@
// Hides help center in action bar and footer bar in SuW
return 0;
}
+
+ /**
+ * Updates the padding of the reset button to meet for SetupWizard style.
+ */
+ private void updateResetButtonPadding() {
+ final LayoutPreference resetPreference = (LayoutPreference) findPreference(RESET_KEY);
+ final ViewGroup parentView =
+ (ViewGroup) resetPreference.findViewById(R.id.reset_button).getParent();
+ LayoutStyler.applyPartnerCustomizationLayoutPaddingStyle(parentView);
+ }
}
diff --git a/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java
index f9a1113..0af8aa1 100644
--- a/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java
@@ -49,6 +49,8 @@
if (mTopIntroPreference != null) {
mTopIntroPreference.setVisible(false);
}
+
+ mToggleServiceSwitchPreference.applyPartnerCustomizationPaddingStyle();
}
@Override
diff --git a/src/com/android/settings/applications/AppStateBaseBridge.java b/src/com/android/settings/applications/AppStateBaseBridge.java
index d7f253b..a4bdabf 100644
--- a/src/com/android/settings/applications/AppStateBaseBridge.java
+++ b/src/com/android/settings/applications/AppStateBaseBridge.java
@@ -52,7 +52,6 @@
public void resume(boolean forceLoadAllApps) {
mForceLoadAllApps = forceLoadAllApps;
- mHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ALL);
if (mForceLoadAllApps) {
mAppSession.onResume();
} else {
diff --git a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
index ef5b029..d1d286d 100644
--- a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
+++ b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
@@ -85,12 +85,27 @@
return view;
}
+ static View newHeader(ViewGroup parent, int resText) {
+ ViewGroup view = (ViewGroup) LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.preference_app_header, parent, false);
+ TextView textView = view.findViewById(R.id.apps_top_intro_text);
+ textView.setText(resText);
+ return view;
+ }
+
void setSummary(CharSequence summary) {
mSummary.setText(summary);
+ updateSummaryVisibility();
}
void setSummary(@StringRes int summary) {
mSummary.setText(summary);
+ updateSummaryVisibility();
+ }
+
+ private void updateSummaryVisibility() {
+ // Hide an empty summary and then title will be vertically centered.
+ mSummary.setVisibility(TextUtils.isEmpty(mSummary.getText()) ? View.GONE : View.VISIBLE);
}
void setEnabled(boolean isEnabled) {
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index a6abd10..9796454 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -824,14 +824,16 @@
if (mApplications == null) {
return;
}
- final int position = mRecyclerView.getChildAdapterPosition(view);
+ final int applicationPosition =
+ ApplicationsAdapter.getApplicationPosition(
+ mListType, mRecyclerView.getChildAdapterPosition(view));
- if (position == RecyclerView.NO_POSITION) {
+ if (applicationPosition == RecyclerView.NO_POSITION) {
Log.w(TAG, "Cannot find position for child, skipping onClick handling");
return;
}
- if (mApplications.getApplicationCount() > position) {
- ApplicationsState.AppEntry entry = mApplications.getAppEntry(position);
+ if (mApplications.getApplicationCount() > applicationPosition) {
+ ApplicationsState.AppEntry entry = mApplications.getAppEntry(applicationPosition);
mCurrentPkgName = entry.info.packageName;
mCurrentUid = entry.info.uid;
startApplicationDetailsActivity();
@@ -1058,6 +1060,7 @@
private static final String STATE_LAST_SCROLL_INDEX = "state_last_scroll_index";
private static final int VIEW_TYPE_APP = 0;
private static final int VIEW_TYPE_EXTRA_VIEW = 1;
+ private static final int VIEW_TYPE_APP_HEADER = 2;
private final ApplicationsState mState;
private final ApplicationsState.Session mSession;
@@ -1229,7 +1232,11 @@
@Override
public ApplicationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view;
- if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
+ if (mManageApplications.mListType == LIST_TYPE_APPS_LOCALE
+ && viewType == VIEW_TYPE_APP_HEADER) {
+ view = ApplicationViewHolder.newHeader(parent,
+ R.string.desc_app_locale_selection_supported);
+ } else if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
view = ApplicationViewHolder.newView(parent, true /* twoTarget */);
} else {
view = ApplicationViewHolder.newView(parent, false /* twoTarget */);
@@ -1239,6 +1246,9 @@
@Override
public int getItemViewType(int position) {
+ if (position == 0 && mManageApplications.mListType == LIST_TYPE_APPS_LOCALE) {
+ return VIEW_TYPE_APP_HEADER;
+ }
return VIEW_TYPE_APP;
}
@@ -1470,36 +1480,59 @@
}
}
+ /**
+ * Item count include all items. If UI has a header on the app list, it shall shift 1 to
+ * application count for the total item count.
+ */
@Override
public int getItemCount() {
- if (mEntries == null) {
- return 0;
+ int count = getApplicationCount();
+ if (count != 0 && mManageApplications.mListType == LIST_TYPE_APPS_LOCALE) {
+ count++;
}
- return mEntries.size();
+ return count;
}
public int getApplicationCount() {
return mEntries != null ? mEntries.size() : 0;
}
- public AppEntry getAppEntry(int position) {
- return mEntries.get(position);
+ public AppEntry getAppEntry(int applicationPosition) {
+ return mEntries.get(applicationPosition);
}
+ /**
+ * Item Id follows all item on the app list. If UI has a header on the list, it shall
+ * shift 1 to the position for correct app entry.
+ */
@Override
public long getItemId(int position) {
- if (position == mEntries.size()) {
+ int applicationPosition =
+ getApplicationPosition(mManageApplications.mListType, position);
+ if (applicationPosition == mEntries.size()
+ || applicationPosition == RecyclerView.NO_POSITION) {
return -1;
}
- return mEntries.get(position).id;
+ return mEntries.get(applicationPosition).id;
}
+ /**
+ * Check item in the list shall enable or disable.
+ * @param position The item position in the list
+ */
public boolean isEnabled(int position) {
- if (getItemViewType(position) == VIEW_TYPE_EXTRA_VIEW
+ int itemViewType = getItemViewType(position);
+ if (itemViewType == VIEW_TYPE_EXTRA_VIEW || itemViewType == VIEW_TYPE_APP_HEADER
|| mManageApplications.mListType != LIST_TYPE_HIGH_POWER) {
return true;
}
- ApplicationsState.AppEntry entry = mEntries.get(position);
+
+ int applicationPosition =
+ getApplicationPosition(mManageApplications.mListType, position);
+ if (applicationPosition == RecyclerView.NO_POSITION) {
+ return true;
+ }
+ ApplicationsState.AppEntry entry = mEntries.get(applicationPosition);
return !mBackend.isSysAllowlisted(entry.info.packageName)
&& !mBackend.isDefaultActiveApp(entry.info.packageName);
@@ -1507,8 +1540,21 @@
@Override
public void onBindViewHolder(ApplicationViewHolder holder, int position) {
+ if (getItemViewType(position) == VIEW_TYPE_APP_HEADER) {
+ // It does not bind holder here, due to header view.
+ return;
+ }
+
+ int applicationPosition =
+ getApplicationPosition(mManageApplications.mListType, position);
+ if (applicationPosition == RecyclerView.NO_POSITION) {
+ return;
+ }
// Bind the data efficiently with the holder
- final ApplicationsState.AppEntry entry = mEntries.get(position);
+ // If there is a header on the list, the position shall be shifted. Thus, it shall use
+ // #getApplicationPosition to get real application position for the app entry.
+ final ApplicationsState.AppEntry entry = mEntries.get(applicationPosition);
+
synchronized (entry) {
mState.ensureLabelDescription(entry);
holder.setTitle(entry.label, entry.labelDescription);
@@ -1608,6 +1654,22 @@
}
}
+ /**
+ * Adjusts position if this list adds a header.
+ * TODO(b/232533002) Add a header view on adapter of RecyclerView may not a good idea since
+ * ManageApplication is a generic purpose. In the future, here shall look for
+ * a better way to add a header without using recyclerView or any other ways
+ * to achieve the goal.
+ */
+ public static int getApplicationPosition(int listType, int position) {
+ int applicationPosition = position;
+ // Adjust position due to header added.
+ if (listType == LIST_TYPE_APPS_LOCALE) {
+ applicationPosition = position > 0 ? position - 1 : RecyclerView.NO_POSITION;
+ }
+ return applicationPosition;
+ }
+
public static class OnScrollListener extends RecyclerView.OnScrollListener {
private int mScrollState = SCROLL_STATE_IDLE;
private boolean mDelayNotifyDataChange;
diff --git a/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java b/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java
index 17b604c..733a4a9 100644
--- a/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothBroadcastSourcePreference.java
@@ -16,7 +16,9 @@
package com.android.settings.bluetooth;
+import android.bluetooth.BluetoothLeAudioContentMetadata;
import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothLeBroadcastSubgroup;
import android.content.Context;
import android.graphics.drawable.Drawable;
@@ -43,16 +45,15 @@
private static final int RESOURCE_ID_ICON = R.drawable.settings_input_antenna;
private BluetoothLeBroadcastMetadata mBluetoothLeBroadcastMetadata;
+ private BluetoothLeBroadcastReceiveState mBluetoothLeBroadcastReceiveState;
private ImageView mFrictionImageView;
private String mTitle;
private boolean mStatus;
private boolean mIsEncrypted;
- BluetoothBroadcastSourcePreference(@NonNull Context context,
- @NonNull BluetoothLeBroadcastMetadata source) {
+ BluetoothBroadcastSourcePreference(@NonNull Context context) {
super(context);
initUi();
- updateMetadataAndRefreshUi(source, false);
}
@Override
@@ -68,7 +69,7 @@
private void initUi() {
setLayoutResource(R.layout.preference_access_point);
setWidgetLayoutResource(R.layout.access_point_friction_widget);
-
+ mTitle = getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO);
mStatus = false;
final Drawable drawable = getContext().getDrawable(RESOURCE_ID_ICON);
if (drawable != null) {
@@ -105,9 +106,20 @@
*/
public void updateMetadataAndRefreshUi(BluetoothLeBroadcastMetadata source, boolean status) {
mBluetoothLeBroadcastMetadata = source;
- mTitle = getBroadcastMetadataProgramInfo();
+ mTitle = getProgramInfo();
mIsEncrypted = mBluetoothLeBroadcastMetadata.isEncrypted();
- mStatus = status;
+ mStatus = status || mBluetoothLeBroadcastReceiveState != null;
+
+ refresh();
+ }
+
+ /**
+ * Updates the title and status from BluetoothLeBroadcastReceiveState.
+ */
+ public void updateReceiveStateAndRefreshUi(BluetoothLeBroadcastReceiveState receiveState) {
+ mBluetoothLeBroadcastReceiveState = receiveState;
+ mTitle = getProgramInfo();
+ mStatus = true;
refresh();
}
@@ -124,7 +136,17 @@
updateStatusButton();
}
- private String getBroadcastMetadataProgramInfo() {
+ private String getProgramInfo() {
+ if (mBluetoothLeBroadcastReceiveState != null) {
+ List<BluetoothLeAudioContentMetadata> bluetoothLeAudioContentMetadata =
+ mBluetoothLeBroadcastReceiveState.getSubgroupMetadata();
+ if (!bluetoothLeAudioContentMetadata.isEmpty()) {
+ return bluetoothLeAudioContentMetadata.stream()
+ .map(i -> i.getProgramInfo())
+ .findFirst().orElse(
+ getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO));
+ }
+ }
if (mBluetoothLeBroadcastMetadata == null) {
return getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO);
}
@@ -138,4 +160,24 @@
.filter(i -> !TextUtils.isEmpty(i))
.findFirst().orElse(getContext().getString(RESOURCE_ID_UNKNOWN_PROGRAM_INFO));
}
+
+ /**
+ * Whether the broadcast source is encrypted or not.
+ * @return If true, the broadcast source needs the broadcast code. If false, the broadcast
+ * source does not need the broadcast code.
+ */
+ public boolean isEncrypted() {
+ return mIsEncrypted;
+ }
+
+ /**
+ * Clear the BluetoothLeBroadcastReceiveState and reset the state when the user clicks the
+ * "leave broadcast" button.
+ */
+ public void clearReceiveState() {
+ mBluetoothLeBroadcastReceiveState = null;
+ mTitle = getProgramInfo();
+ mStatus = false;
+ refresh();
+ }
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsCompanionAppsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsCompanionAppsController.java
index 272d142..e3f0f09 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsCompanionAppsController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsCompanionAppsController.java
@@ -186,7 +186,7 @@
String address, PreferenceCategory container) {
// If the device is FastPair, remove CDM companion apps.
final BluetoothFeatureProvider bluetoothFeatureProvider = FeatureFactory.getFactory(context)
- .getBluetoothFeatureProvider(context);
+ .getBluetoothFeatureProvider();
final boolean sliceEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.BT_SLICE_SETTINGS_ENABLED, true);
final Uri settingsUri = bluetoothFeatureProvider.getBluetoothDeviceSettingsUri(
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
index 9c7aa58..06a71f0 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
@@ -75,10 +75,8 @@
if (TextUtils.isEmpty(summaryText)) {
// If first summary is unavailable, not to show second summary.
mHeaderController.setSecondSummary((CharSequence)null);
- } else {
- // If both the hearing aids are connected, two device status should be shown.
- mHeaderController.setSecondSummary(mDeviceManager.getSubDeviceSummary(mCachedDevice));
}
+
mHeaderController.setLabel(mCachedDevice.getName());
mHeaderController.setIcon(pair.first);
mHeaderController.setIconContentDescription(pair.second);
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsRelatedToolsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsRelatedToolsController.java
new file mode 100644
index 0000000..bfaea85
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsRelatedToolsController.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.AccessibilityShortcutInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.annotation.NonNull;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+import com.android.net.module.util.CollectionUtils;
+import com.android.settings.accessibility.RestrictedPreferenceHelper;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.RestrictedPreference;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * This class adds related tools preference.
+ */
+public class BluetoothDetailsRelatedToolsController extends BluetoothDetailsController{
+ private static final String KEY_RELATED_TOOLS_GROUP = "bluetooth_related_tools";
+ private static final String KEY_LIVE_CAPTION = "live_caption";
+ private static final int ORDINAL = 99;
+
+ private PreferenceCategory mPreferenceCategory;
+
+ public BluetoothDetailsRelatedToolsController(Context context,
+ PreferenceFragmentCompat fragment, CachedBluetoothDevice device, Lifecycle lifecycle) {
+ super(context, fragment, device, lifecycle);
+ lifecycle.addObserver(this);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mCachedDevice.isHearingAidDevice();
+ }
+
+ @Override
+ protected void init(PreferenceScreen screen) {
+ if (!mCachedDevice.isHearingAidDevice()) {
+ return;
+ }
+
+ mPreferenceCategory = screen.findPreference(getPreferenceKey());
+ final Preference liveCaptionPreference = screen.findPreference(KEY_LIVE_CAPTION);
+ if (!liveCaptionPreference.isVisible()) {
+ mPreferenceCategory.removePreference(liveCaptionPreference);
+ }
+
+ final List<ComponentName> relatedToolsList = FeatureFactory.getFactory(
+ mContext).getBluetoothFeatureProvider().getRelatedTools();
+ if (!CollectionUtils.isEmpty(relatedToolsList)) {
+ addAccessibilityInstalledRelatedPreference(relatedToolsList);
+ }
+
+ if (mPreferenceCategory.getPreferenceCount() == 0) {
+ screen.removePreference(mPreferenceCategory);
+ }
+ }
+
+ @Override
+ protected void refresh() {}
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_RELATED_TOOLS_GROUP;
+ }
+
+ private void addAccessibilityInstalledRelatedPreference(
+ @NonNull List<ComponentName> componentNameList) {
+ final AccessibilityManager a11yManager = AccessibilityManager.getInstance(mContext);
+ final RestrictedPreferenceHelper preferenceHelper = new RestrictedPreferenceHelper(
+ mContext);
+
+ final List<AccessibilityServiceInfo> a11yServiceInfoList =
+ a11yManager.getInstalledAccessibilityServiceList().stream()
+ .filter(info -> componentNameList.contains(info.getComponentName()))
+ .collect(Collectors.toList());
+ final List<AccessibilityShortcutInfo> a11yShortcutInfoList =
+ a11yManager.getInstalledAccessibilityShortcutListAsUser(mContext,
+ UserHandle.myUserId()).stream()
+ .filter(info -> componentNameList.contains(info.getComponentName()))
+ .collect(Collectors.toList());
+
+ final List<RestrictedPreference> preferences = Stream.of(
+ preferenceHelper.createAccessibilityServicePreferenceList(a11yServiceInfoList),
+ preferenceHelper.createAccessibilityActivityPreferenceList(a11yShortcutInfoList))
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList());
+
+ for (RestrictedPreference preference : preferences) {
+ preference.setOrder(ORDINAL);
+ mPreferenceCategory.addPreference(preference);
+ }
+ }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 6d443ee..a9ac286 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -22,12 +22,18 @@
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
+import android.net.Uri;
import android.os.Bundle;
import android.provider.DeviceConfig;
+import android.text.TextUtils;
import android.util.Log;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import androidx.annotation.VisibleForTesting;
@@ -36,12 +42,14 @@
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.slices.BlockingSlicePrefController;
+import com.android.settings.slices.SlicePreferenceController;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
+import java.util.IllegalFormatException;
import java.util.List;
public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment {
@@ -61,6 +69,7 @@
@VisibleForTesting
interface TestDataFactory {
CachedBluetoothDevice getDevice(String deviceAddress);
+
LocalBluetoothManager getManager(Context context);
}
@@ -120,13 +129,56 @@
use(LeAudioBluetoothDetailsHeaderController.class).init(mCachedDevice, mManager);
final BluetoothFeatureProvider featureProvider = FeatureFactory.getFactory(
- context).getBluetoothFeatureProvider(context);
+ context).getBluetoothFeatureProvider();
final boolean sliceEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.BT_SLICE_SETTINGS_ENABLED, true);
use(BlockingSlicePrefController.class).setSliceUri(sliceEnabled
? featureProvider.getBluetoothDeviceSettingsUri(mCachedDevice.getDevice())
: null);
+ updateExtraControlUri(/* viewWidth */ 0);
+ }
+
+ private void updateExtraControlUri(int viewWidth) {
+ BluetoothFeatureProvider featureProvider = FeatureFactory.getFactory(
+ getContext()).getBluetoothFeatureProvider();
+ boolean sliceEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
+ SettingsUIDeviceConfig.BT_SLICE_SETTINGS_ENABLED, true);
+ Uri controlUri = null;
+ String uri = featureProvider.getBluetoothDeviceControlUri(mCachedDevice.getDevice());
+ if (!TextUtils.isEmpty(uri)) {
+ try {
+ controlUri = Uri.parse(String.format(uri, viewWidth));
+ } catch (IllegalFormatException | NullPointerException exception) {
+ Log.d(TAG, "unable to parse uri");
+ controlUri = null;
+ }
+ }
+ use(SlicePreferenceController.class).setSliceUri(sliceEnabled ? controlUri : null);
+ }
+
+ private final ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener =
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ View view = getView();
+ if (view == null) {
+ return;
+ }
+ updateExtraControlUri(view.getWidth());
+ view.getViewTreeObserver().removeOnGlobalLayoutListener(
+ mOnGlobalLayoutListener);
+ }
+ };
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = super.onCreateView(inflater, container, savedInstanceState);
+ if (view != null) {
+ view.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
+ }
+ return view;
}
@Override
@@ -194,6 +246,8 @@
mCachedDevice, lifecycle));
controllers.add(new BluetoothDetailsMacAddressController(context, this, mCachedDevice,
lifecycle));
+ controllers.add(new BluetoothDetailsRelatedToolsController(context, this, mCachedDevice,
+ lifecycle));
}
return controllers;
}
diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
index 582a26c..648ca30 100644
--- a/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
+++ b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
@@ -17,17 +17,37 @@
package com.android.settings.bluetooth;
import android.bluetooth.BluetoothDevice;
+import android.content.ComponentName;
import android.net.Uri;
+import java.util.List;
+
/**
- * Provider for bluetooth related feature
+ * Provider for bluetooth related features.
*/
public interface BluetoothFeatureProvider {
/**
- * Get the {@link Uri} that represents extra settings for a specific bluetooth device
+ * Gets the {@link Uri} that represents extra settings for a specific bluetooth device
+ *
* @param bluetoothDevice bluetooth device
* @return {@link Uri} for extra settings
*/
Uri getBluetoothDeviceSettingsUri(BluetoothDevice bluetoothDevice);
+
+ /**
+ * Gets the {@link Uri} that represents extra control for a specific bluetooth device
+ *
+ * @param bluetoothDevice bluetooth device
+ * @return {@link String} uri string for extra control
+ */
+ String getBluetoothDeviceControlUri(BluetoothDevice bluetoothDevice);
+
+ /**
+ * Gets the {@link ComponentName} of services or activities that need to be shown in related
+ * tools.
+ *
+ * @return list of {@link ComponentName}
+ */
+ List<ComponentName> getRelatedTools();
}
diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java
index cd75951..5ddf062 100644
--- a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java
+++ b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java
@@ -17,19 +17,20 @@
package com.android.settings.bluetooth;
import android.bluetooth.BluetoothDevice;
+import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
+import com.android.settingslib.bluetooth.BluetoothUtils;
+
+import java.util.List;
+
/**
* Impl of {@link BluetoothFeatureProvider}
*/
public class BluetoothFeatureProviderImpl implements BluetoothFeatureProvider {
- private Context mContext;
-
- public BluetoothFeatureProviderImpl(Context context) {
- mContext = context;
- }
+ public BluetoothFeatureProviderImpl(Context context) {}
@Override
public Uri getBluetoothDeviceSettingsUri(BluetoothDevice bluetoothDevice) {
@@ -37,4 +38,14 @@
BluetoothDevice.METADATA_ENHANCED_SETTINGS_UI_URI);
return uriByte == null ? null : Uri.parse(new String(uriByte));
}
+
+ @Override
+ public String getBluetoothDeviceControlUri(BluetoothDevice bluetoothDevice) {
+ return BluetoothUtils.getControlUriMetaData(bluetoothDevice);
+ }
+
+ @Override
+ public List<ComponentName> getRelatedTools() {
+ return null;
+ }
}
diff --git a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
index 07a3156..13388b3 100644
--- a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
@@ -86,9 +86,7 @@
@Override
public void onSearchStarted(int reason) {
Log.d(TAG, "onSearchStarted: " + reason);
-
- getActivity().runOnUiThread(
- () -> cacheRemoveAllPrefs(mBroadcastSourceListCategory));
+ getActivity().runOnUiThread(() -> handleSearchStarted());
}
@Override
@@ -109,7 +107,8 @@
@Override
public void onSourceFound(@NonNull BluetoothLeBroadcastMetadata source) {
Log.d(TAG, "onSourceFound:");
- getActivity().runOnUiThread(() -> updateListCategory(source, false));
+ getActivity().runOnUiThread(
+ () -> updateListCategoryFromBroadcastMetadata(source, false));
}
@Override
@@ -119,7 +118,7 @@
Log.w(TAG, "onSourceAdded: mSelectedPreference == null!");
return;
}
- getActivity().runOnUiThread(() -> updateListCategory(
+ getActivity().runOnUiThread(() -> updateListCategoryFromBroadcastMetadata(
mSelectedPreference.getBluetoothLeBroadcastMetadata(), true));
}
@@ -144,6 +143,7 @@
public void onSourceRemoved(@NonNull BluetoothDevice sink, int sourceId,
int reason) {
Log.d(TAG, "onSourceRemoved:");
+ getActivity().runOnUiThread(() -> handleSourceRemoved());
}
@Override
@@ -215,6 +215,8 @@
//check assistant status. Start searching...
if (mLeBroadcastAssistant != null && !mLeBroadcastAssistant.isSearchInProgress()) {
mLeBroadcastAssistant.startSearchingForSources(getScanFilter());
+ } else {
+ addConnectedSourcePreference();
}
}
@@ -310,11 +312,13 @@
return Collections.emptyList();
}
- private void updateListCategory(BluetoothLeBroadcastMetadata source, boolean isConnected) {
+ private void updateListCategoryFromBroadcastMetadata(BluetoothLeBroadcastMetadata source,
+ boolean isConnected) {
BluetoothBroadcastSourcePreference item = mBroadcastSourceListCategory.findPreference(
Integer.toString(source.getBroadcastId()));
if (item == null) {
- item = createBluetoothBroadcastSourcePreference(source);
+ item = createBluetoothBroadcastSourcePreference();
+ item.setKey(Integer.toString(source.getBroadcastId()));
mBroadcastSourceListCategory.addPreference(item);
}
item.updateMetadataAndRefreshUi(source, isConnected);
@@ -326,13 +330,36 @@
}
}
- private BluetoothBroadcastSourcePreference createBluetoothBroadcastSourcePreference(
- BluetoothLeBroadcastMetadata source) {
+ private void updateListCategoryFromBroadcastReceiveState(
+ BluetoothLeBroadcastReceiveState receiveState) {
+ BluetoothBroadcastSourcePreference item = mBroadcastSourceListCategory.findPreference(
+ Integer.toString(receiveState.getBroadcastId()));
+ if (item == null) {
+ item = createBluetoothBroadcastSourcePreference();
+ item.setKey(Integer.toString(receiveState.getBroadcastId()));
+ mBroadcastSourceListCategory.addPreference(item);
+ }
+ item.updateReceiveStateAndRefreshUi(receiveState);
+ item.setOrder(0);
+
+ setSourceId(receiveState.getSourceId());
+ mSelectedPreference = item;
+
+ //refresh the header
+ if (mBluetoothFindBroadcastsHeaderController != null) {
+ mBluetoothFindBroadcastsHeaderController.refreshUi();
+ }
+ }
+
+ private BluetoothBroadcastSourcePreference createBluetoothBroadcastSourcePreference() {
BluetoothBroadcastSourcePreference pref = new BluetoothBroadcastSourcePreference(
- getContext(), source);
- pref.setKey(Integer.toString(source.getBroadcastId()));
+ getContext());
pref.setOnPreferenceClickListener(preference -> {
- if (source.isEncrypted()) {
+ if (pref.getBluetoothLeBroadcastMetadata() == null) {
+ Log.d(TAG, "BluetoothLeBroadcastMetadata is null, do nothing.");
+ return false;
+ }
+ if (pref.isEncrypted()) {
launchBroadcastCodeDialog(pref);
} else {
addSource(pref);
@@ -383,6 +410,10 @@
.setPositiveButton(R.string.bluetooth_connect_access_dialog_positive,
(d, w) -> {
Log.d(TAG, "setPositiveButton: clicked");
+ if (pref.getBluetoothLeBroadcastMetadata() == null) {
+ Log.d(TAG, "BluetoothLeBroadcastMetadata is null, do nothing.");
+ return;
+ }
addBroadcastCodeIntoPreference(pref, editText.getText().toString());
addSource(pref);
})
@@ -392,6 +423,30 @@
alertDialog.show();
}
+ private void handleSearchStarted() {
+ cacheRemoveAllPrefs(mBroadcastSourceListCategory);
+ addConnectedSourcePreference();
+ }
+
+ private void handleSourceRemoved() {
+ if (mSelectedPreference != null) {
+ if (mSelectedPreference.getBluetoothLeBroadcastMetadata() == null) {
+ mBroadcastSourceListCategory.removePreference(mSelectedPreference);
+ } else {
+ mSelectedPreference.clearReceiveState();
+ }
+ }
+ mSelectedPreference = null;
+ }
+
+ private void addConnectedSourcePreference() {
+ List<BluetoothLeBroadcastReceiveState> receiveStateList =
+ mLeBroadcastAssistant.getAllSources(mCachedDevice.getDevice());
+ if (!receiveStateList.isEmpty()) {
+ updateListCategoryFromBroadcastReceiveState(receiveStateList.get(0));
+ }
+ }
+
public int getSourceId() {
return mSourceId;
}
diff --git a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java
index 1527f21..1282abd 100644
--- a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java
+++ b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsHeaderController.java
@@ -33,7 +33,6 @@
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.qrcode.QrCodeScanModeActivity;
import com.android.settingslib.widget.LayoutPreference;
/**
@@ -135,7 +134,7 @@
private void launchQrCodeScanner() {
final Intent intent = new Intent(mContext, QrCodeScanModeActivity.class);
intent.setAction(BluetoothBroadcastUtils.ACTION_BLUETOOTH_LE_AUDIO_QR_CODE_SCANNER)
- .putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_SINK_IS_GROUP, false)
+ .putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_SINK_IS_GROUP, true)
.putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_DEVICE_SINK,
mCachedDevice.getDevice());
mContext.startActivity(intent);
diff --git a/src/com/android/settings/bluetooth/HearingAidPairingDialogFragment.java b/src/com/android/settings/bluetooth/HearingAidPairingDialogFragment.java
new file mode 100644
index 0000000..ac48217
--- /dev/null
+++ b/src/com/android/settings/bluetooth/HearingAidPairingDialogFragment.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+
+/**
+ * Provides a dialog to pair another side of hearing aid device.
+ */
+public class HearingAidPairingDialogFragment extends InstrumentedDialogFragment {
+ public static final String TAG = "HearingAidPairingDialogFragment";
+ private static final String KEY_CACHED_DEVICE_SIDE = "cached_device_side";
+
+ /**
+ * Creates a new {@link HearingAidPairingDialogFragment} and shows pair another side of hearing
+ * aid device according to {@code CachedBluetoothDevice} side.
+ *
+ * @param device The remote Bluetooth device, that needs to be hearing aid device.
+ * @return a DialogFragment
+ */
+ public static HearingAidPairingDialogFragment newInstance(CachedBluetoothDevice device) {
+ Bundle args = new Bundle(1);
+ args.putInt(KEY_CACHED_DEVICE_SIDE, device.getDeviceSide());
+ final HearingAidPairingDialogFragment fragment = new HearingAidPairingDialogFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ // TODO(b/225117454): Need to update SettingsEnums later
+ return SettingsEnums.ACCESSIBILITY;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ final int deviceSide = getArguments().getInt(KEY_CACHED_DEVICE_SIDE);
+ final int titleId = R.string.bluetooth_pair_other_ear_dialog_title;
+ final int messageId = (deviceSide == HearingAidProfile.DeviceSide.SIDE_LEFT)
+ ? R.string.bluetooth_pair_other_ear_dialog_left_ear_message
+ : R.string.bluetooth_pair_other_ear_dialog_right_ear_message;
+ final int pairBtnId = (deviceSide == HearingAidProfile.DeviceSide.SIDE_LEFT)
+ ? R.string.bluetooth_pair_other_ear_dialog_right_ear_positive_button
+ : R.string.bluetooth_pair_other_ear_dialog_left_ear_positive_button;
+
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(titleId)
+ .setMessage(messageId)
+ .setNegativeButton(
+ android.R.string.cancel, /* listener= */ null)
+ .setPositiveButton(pairBtnId, (dialog, which) -> positiveButtonListener())
+ .create();
+ }
+
+ private void positiveButtonListener() {
+ new SubSettingLauncher(getActivity())
+ .setDestination(BluetoothPairingDetail.class.getName())
+ .setSourceMetricsCategory(SettingsEnums.ACCESSIBILITY)
+ .launch();
+ }
+}
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeActivity.java b/src/com/android/settings/bluetooth/QrCodeScanModeActivity.java
new file mode 100644
index 0000000..5c5b61f
--- /dev/null
+++ b/src/com/android/settings/bluetooth/QrCodeScanModeActivity.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import static com.android.settingslib.bluetooth.BluetoothBroadcastUtils.EXTRA_BLUETOOTH_DEVICE_SINK;
+import static com.android.settingslib.bluetooth.BluetoothBroadcastUtils.EXTRA_BLUETOOTH_SINK_IS_GROUP;
+
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.fragment.app.FragmentTransaction;
+
+import com.android.settingslib.R;
+import com.android.settingslib.bluetooth.BluetoothBroadcastUtils;
+import com.android.settingslib.bluetooth.BluetoothUtils;
+
+//TODO (b/232365943): Add test case for tthe QrCode UI.
+public class QrCodeScanModeActivity extends QrCodeScanModeBaseActivity {
+ private static final boolean DEBUG = BluetoothUtils.D;
+ private static final String TAG = "QrCodeScanModeActivity";
+
+ private boolean mIsGroupOp;
+ private BluetoothDevice mSink;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void handleIntent(Intent intent) {
+ String action = intent != null ? intent.getAction() : null;
+ if (DEBUG) {
+ Log.d(TAG, "handleIntent(), action = " + action);
+ }
+
+ if (action == null) {
+ finish();
+ return;
+ }
+
+ switch (action) {
+ case BluetoothBroadcastUtils.ACTION_BLUETOOTH_LE_AUDIO_QR_CODE_SCANNER:
+ showQrCodeScannerFragment(intent);
+ break;
+ default:
+ if (DEBUG) {
+ Log.e(TAG, "Launch with an invalid action");
+ }
+ finish();
+ }
+ }
+
+ protected void showQrCodeScannerFragment(Intent intent) {
+ if (intent == null) {
+ if (DEBUG) {
+ Log.d(TAG, "intent is null, can not get bluetooth information from intent.");
+ }
+ return;
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "showQrCodeScannerFragment");
+ }
+
+ mSink = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE_SINK);
+ mIsGroupOp = intent.getBooleanExtra(EXTRA_BLUETOOTH_SINK_IS_GROUP, false);
+ if (DEBUG) {
+ Log.d(TAG, "get extra from intent");
+ }
+
+ QrCodeScanModeFragment fragment =
+ (QrCodeScanModeFragment) mFragmentManager.findFragmentByTag(
+ BluetoothBroadcastUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
+
+ if (fragment == null) {
+ fragment = new QrCodeScanModeFragment(mIsGroupOp, mSink);
+ } else {
+ if (fragment.isVisible()) {
+ return;
+ }
+
+ // When the fragment in back stack but not on top of the stack, we can simply pop
+ // stack because current fragment transactions are arranged in an order
+ mFragmentManager.popBackStackImmediate();
+ return;
+ }
+ final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
+
+ fragmentTransaction.replace(R.id.fragment_container, fragment,
+ BluetoothBroadcastUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
+ fragmentTransaction.commit();
+ }
+}
+
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeBaseActivity.java b/src/com/android/settings/bluetooth/QrCodeScanModeBaseActivity.java
new file mode 100644
index 0000000..af8a6e9
--- /dev/null
+++ b/src/com/android/settings/bluetooth/QrCodeScanModeBaseActivity.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.fragment.app.FragmentManager;
+
+import com.android.settingslib.R;
+import com.android.settingslib.core.lifecycle.ObservableActivity;
+
+public abstract class QrCodeScanModeBaseActivity extends ObservableActivity {
+
+ protected FragmentManager mFragmentManager;
+
+ protected abstract void handleIntent(Intent intent);
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setTheme(R.style.SudThemeGlifV3_DayNight);
+
+ setContentView(R.layout.qrcode_scan_mode_activity);
+ mFragmentManager = getSupportFragmentManager();
+
+ if (savedInstanceState == null) {
+ handleIntent(getIntent());
+ }
+ }
+}
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeController.java b/src/com/android/settings/bluetooth/QrCodeScanModeController.java
new file mode 100644
index 0000000..4504b4b
--- /dev/null
+++ b/src/com/android/settings/bluetooth/QrCodeScanModeController.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.bluetooth.BluetoothUtils;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
+import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastMetadata;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+
+public class QrCodeScanModeController {
+
+ private static final boolean DEBUG = BluetoothUtils.D;
+ private static final String TAG = "QrCodeScanModeController";
+
+ private LocalBluetoothLeBroadcastMetadata mLocalBroadcastMetadata;
+ private LocalBluetoothLeBroadcastAssistant mLocalBroadcastAssistant;
+ private LocalBluetoothManager mLocalBluetoothManager;
+ private LocalBluetoothProfileManager mProfileManager;
+
+ public QrCodeScanModeController(Context context) {
+ if (DEBUG) {
+ Log.d(TAG, "QrCodeScanModeController constructor.");
+ }
+ mLocalBluetoothManager = Utils.getLocalBtManager(context);
+ mProfileManager = mLocalBluetoothManager.getProfileManager();
+ mLocalBroadcastMetadata = new LocalBluetoothLeBroadcastMetadata();
+ CachedBluetoothDeviceManager cachedDeviceManager = new CachedBluetoothDeviceManager(context,
+ mLocalBluetoothManager);
+ mLocalBroadcastAssistant = new LocalBluetoothLeBroadcastAssistant(context,
+ cachedDeviceManager, mProfileManager);
+ }
+
+ private BluetoothLeBroadcastMetadata convertToBroadcastMetadata(String qrCodeString) {
+ return mLocalBroadcastMetadata.convertToBroadcastMetadata(qrCodeString);
+ }
+
+ public void addSource(BluetoothDevice sink, String sourceMetadata,
+ boolean isGroupOp) {
+ mLocalBroadcastAssistant.addSource(sink,
+ convertToBroadcastMetadata(sourceMetadata), isGroupOp);
+ }
+}
diff --git a/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java b/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
new file mode 100644
index 0000000..dcf89ca
--- /dev/null
+++ b/src/com/android/settings/bluetooth/QrCodeScanModeFragment.java
@@ -0,0 +1,243 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.app.settings.SettingsEnums;
+import android.bluetooth.BluetoothDevice;
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.graphics.SurfaceTexture;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.util.Size;
+import android.view.LayoutInflater;
+import android.view.TextureView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.TextView;
+
+import com.android.settings.core.InstrumentedFragment;
+import com.android.settingslib.R;
+import com.android.settingslib.bluetooth.BluetoothBroadcastUtils;
+import com.android.settingslib.bluetooth.BluetoothUtils;
+import com.android.settingslib.core.lifecycle.ObservableFragment;
+import com.android.settingslib.qrcode.QrCamera;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+
+public class QrCodeScanModeFragment extends InstrumentedFragment implements
+ TextureView.SurfaceTextureListener,
+ QrCamera.ScannerCallback {
+ private static final boolean DEBUG = BluetoothUtils.D;
+ private static final String TAG = "QrCodeScanModeFragment";
+
+ /** Message sent to hide error message */
+ private static final int MESSAGE_HIDE_ERROR_MESSAGE = 1;
+ /** Message sent to show error message */
+ private static final int MESSAGE_SHOW_ERROR_MESSAGE = 2;
+ /** Message sent to broadcast QR code */
+ private static final int MESSAGE_SCAN_BROADCAST_SUCCESS = 3;
+
+ private static final long SHOW_ERROR_MESSAGE_INTERVAL = 10000;
+ private static final long SHOW_SUCCESS_SQUARE_INTERVAL = 1000;
+
+ private boolean mIsGroupOp;
+ private int mCornerRadius;
+ private BluetoothDevice mSink;
+ private String mBroadcastMetadata;
+ private Context mContext;
+ private QrCamera mCamera;
+ private QrCodeScanModeController mController;
+ private TextureView mTextureView;
+ private TextView mSummary;
+ private TextView mErrorMessage;
+
+ public QrCodeScanModeFragment(boolean isGroupOp, BluetoothDevice sink) {
+ mIsGroupOp = isGroupOp;
+ mSink = sink;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mContext = getContext();
+ mController = new QrCodeScanModeController(mContext);
+ }
+
+ @Override
+ public final View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.qrcode_scanner_fragment, container,
+ /* attachToRoot */ false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ mTextureView = view.findViewById(R.id.preview_view);
+ mCornerRadius = mContext.getResources().getDimensionPixelSize(
+ R.dimen.qrcode_preview_radius);
+ mTextureView.setSurfaceTextureListener(this);
+ mTextureView.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(0,0, view.getWidth(), view.getHeight(), mCornerRadius);
+ }
+ });
+ mTextureView.setClipToOutline(true);
+ mErrorMessage = view.findViewById(R.id.error_message);
+ }
+
+ private void initCamera(SurfaceTexture surface) {
+ // Check if the camera has already created.
+ if (mCamera == null) {
+ mCamera = new QrCamera(mContext, this);
+ mCamera.start(surface);
+ }
+ }
+
+ private void destroyCamera() {
+ if (mCamera != null) {
+ mCamera.stop();
+ mCamera = null;
+ }
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
+ initCamera(surface);
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width,
+ int height) {
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
+ destroyCamera();
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
+ }
+
+ @Override
+ public void handleSuccessfulResult(String qrCode) {
+ if (DEBUG) {
+ Log.d(TAG, "handleSuccessfulResult(), get the qr code string.");
+ }
+ mBroadcastMetadata = qrCode;
+ handleBtLeAudioScanner();
+ }
+
+ @Override
+ public void handleCameraFailure() {
+ destroyCamera();
+ }
+
+ @Override
+ public Size getViewSize() {
+ return new Size(mTextureView.getWidth(), mTextureView.getHeight());
+ }
+
+ @Override
+ public Rect getFramePosition(Size previewSize, int cameraOrientation) {
+ return new Rect(0, 0, previewSize.getHeight(), previewSize.getHeight());
+ }
+
+ @Override
+ public void setTransform(Matrix transform) {
+ mTextureView.setTransform(transform);
+ }
+
+ @Override
+ public boolean isValid(String qrCode) {
+ if (qrCode.startsWith(BluetoothBroadcastUtils.SCHEME_BT_BROADCAST_METADATA)) {
+ return true;
+ } else {
+ showErrorMessage(R.string.bt_le_audio_qr_code_is_not_valid_format);
+ return false;
+ }
+ }
+
+ protected boolean isDecodeTaskAlive() {
+ return mCamera != null && mCamera.isDecodeTaskAlive();
+ }
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_HIDE_ERROR_MESSAGE:
+ mErrorMessage.setVisibility(View.INVISIBLE);
+ break;
+
+ case MESSAGE_SHOW_ERROR_MESSAGE:
+ final String errorMessage = (String) msg.obj;
+
+ mErrorMessage.setVisibility(View.VISIBLE);
+ mErrorMessage.setText(errorMessage);
+ mErrorMessage.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+
+ // Cancel any pending messages to hide error view and requeue the message so
+ // user has time to see error
+ removeMessages(MESSAGE_HIDE_ERROR_MESSAGE);
+ sendEmptyMessageDelayed(MESSAGE_HIDE_ERROR_MESSAGE,
+ SHOW_ERROR_MESSAGE_INTERVAL);
+ break;
+
+ case MESSAGE_SCAN_BROADCAST_SUCCESS:
+ mController.addSource(mSink, mBroadcastMetadata, mIsGroupOp);
+ updateSummary();
+ mSummary.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ break;
+ default:
+ }
+ }
+ };
+
+ private void showErrorMessage(@StringRes int messageResId) {
+ final Message message = mHandler.obtainMessage(MESSAGE_SHOW_ERROR_MESSAGE,
+ getString(messageResId));
+ message.sendToTarget();
+ }
+
+ private void handleBtLeAudioScanner() {
+ Message message = mHandler.obtainMessage(MESSAGE_SCAN_BROADCAST_SUCCESS);
+ mHandler.sendMessageDelayed(message, SHOW_SUCCESS_SQUARE_INTERVAL);
+ }
+
+ private void updateSummary() {
+ mSummary.setText(getString(R.string.bt_le_audio_scan_qr_code_scanner,
+ null /* broadcast_name*/));;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.LE_AUDIO_BROADCAST_SCAN_QR_CODE;
+ }
+}
diff --git a/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupController.java b/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupController.java
index ec122df..6623b97 100644
--- a/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupController.java
+++ b/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupController.java
@@ -17,22 +17,26 @@
import static com.android.settingslib.Utils.isAudioModeOngoingCall;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.pm.PackageManager;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
+import com.android.settings.accessibility.HearingAidUtils;
import com.android.settings.bluetooth.AvailableMediaBluetoothDeviceUpdater;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
@@ -54,6 +58,7 @@
@VisibleForTesting
LocalBluetoothManager mLocalBluetoothManager;
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
+ private FragmentManager mFragmentManager;
public AvailableMediaDeviceGroupController(Context context) {
super(context, KEY);
@@ -124,6 +129,7 @@
}
public void init(DashboardFragment fragment) {
+ mFragmentManager = fragment.getParentFragmentManager();
mBluetoothDeviceUpdater = new AvailableMediaBluetoothDeviceUpdater(fragment.getContext(),
fragment, AvailableMediaDeviceGroupController.this);
}
@@ -138,6 +144,18 @@
updateTitle();
}
+ @Override
+ public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
+ // exclude inactive device
+ if (activeDevice == null) {
+ return;
+ }
+
+ if (bluetoothProfile == BluetoothProfile.HEARING_AID) {
+ HearingAidUtils.launchHearingAidPairingDialog(mFragmentManager, activeDevice);
+ }
+ }
+
private void updateTitle() {
if (isAudioModeOngoingCall(mContext)) {
// in phone call
diff --git a/src/com/android/settings/core/SettingsBaseActivity.java b/src/com/android/settings/core/SettingsBaseActivity.java
index 7842459..322b971 100644
--- a/src/com/android/settings/core/SettingsBaseActivity.java
+++ b/src/com/android/settings/core/SettingsBaseActivity.java
@@ -260,6 +260,9 @@
}
private int getTransitionType(Intent intent) {
+ if (intent == null) {
+ return TransitionType.TRANSITION_NONE;
+ }
return intent.getIntExtra(EXTRA_PAGE_TRANSITION_TYPE, TransitionType.TRANSITION_NONE);
}
}
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 2ae2057..08692dd 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -422,6 +422,11 @@
private void setPreferenceIcon(Preference preference, Tile tile, boolean forceRoundedIcon,
String iconPackage, Icon icon) {
Drawable iconDrawable = icon.loadDrawable(preference.getContext());
+ if (iconDrawable == null) {
+ Log.w(TAG, "Set null preference icon for: " + iconPackage);
+ preference.setIcon(null);
+ return;
+ }
if (TextUtils.equals(tile.getCategory(), CategoryKey.CATEGORY_HOMEPAGE)) {
iconDrawable.setTint(Utils.getHomepageIconColor(preference.getContext()));
} else if (forceRoundedIcon && !TextUtils.equals(mContext.getPackageName(), iconPackage)) {
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
index 57988c5..1473dd1 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
@@ -84,10 +84,19 @@
}
final StorageEntry changedStorageEntry = new StorageEntry(getContext(), volumeInfo);
- switch (volumeInfo.getState()) {
+ final int volumeState = volumeInfo.getState();
+ switch (volumeState) {
+ case VolumeInfo.STATE_REMOVED:
+ case VolumeInfo.STATE_BAD_REMOVAL:
+ // Remove removed storage from list and don't show it on spinner.
+ if (!mStorageEntries.remove(changedStorageEntry)) {
+ break;
+ }
case VolumeInfo.STATE_MOUNTED:
case VolumeInfo.STATE_MOUNTED_READ_ONLY:
case VolumeInfo.STATE_UNMOUNTABLE:
+ case VolumeInfo.STATE_UNMOUNTED:
+ case VolumeInfo.STATE_EJECTING:
// Add mounted or unmountable storage in the list and show it on spinner.
// Unmountable storages are the storages which has a problem format and android
// is not able to mount it automatically.
@@ -95,25 +104,15 @@
mStorageEntries.removeIf(storageEntry -> {
return storageEntry.equals(changedStorageEntry);
});
- mStorageEntries.add(changedStorageEntry);
+ if (volumeState != VolumeInfo.STATE_REMOVED
+ && volumeState != VolumeInfo.STATE_BAD_REMOVAL) {
+ mStorageEntries.add(changedStorageEntry);
+ }
if (changedStorageEntry.equals(mSelectedStorageEntry)) {
mSelectedStorageEntry = changedStorageEntry;
}
refreshUi();
break;
- case VolumeInfo.STATE_REMOVED:
- case VolumeInfo.STATE_UNMOUNTED:
- case VolumeInfo.STATE_BAD_REMOVAL:
- case VolumeInfo.STATE_EJECTING:
- // Remove removed storage from list and don't show it on spinner.
- if (mStorageEntries.remove(changedStorageEntry)) {
- if (changedStorageEntry.equals(mSelectedStorageEntry)) {
- mSelectedStorageEntry =
- StorageEntry.getDefaultInternalStorageEntry(getContext());
- }
- refreshUi();
- }
- break;
default:
// Do nothing.
}
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 77d4072..a4809c9 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -115,10 +115,19 @@
}
final StorageEntry changedStorageEntry = new StorageEntry(getContext(), volumeInfo);
- switch (volumeInfo.getState()) {
+ final int volumeState = volumeInfo.getState();
+ switch (volumeState) {
+ case VolumeInfo.STATE_REMOVED:
+ case VolumeInfo.STATE_BAD_REMOVAL:
+ // Remove removed storage from list and don't show it on spinner.
+ if (!mStorageEntries.remove(changedStorageEntry)) {
+ break;
+ }
case VolumeInfo.STATE_MOUNTED:
case VolumeInfo.STATE_MOUNTED_READ_ONLY:
case VolumeInfo.STATE_UNMOUNTABLE:
+ case VolumeInfo.STATE_UNMOUNTED:
+ case VolumeInfo.STATE_EJECTING:
// Add mounted or unmountable storage in the list and show it on spinner.
// Unmountable storages are the storages which has a problem format and android
// is not able to mount it automatically.
@@ -126,25 +135,15 @@
mStorageEntries.removeIf(storageEntry -> {
return storageEntry.equals(changedStorageEntry);
});
- mStorageEntries.add(changedStorageEntry);
+ if (volumeState != VolumeInfo.STATE_REMOVED
+ && volumeState != VolumeInfo.STATE_BAD_REMOVAL) {
+ mStorageEntries.add(changedStorageEntry);
+ }
if (changedStorageEntry.equals(mSelectedStorageEntry)) {
mSelectedStorageEntry = changedStorageEntry;
}
refreshUi();
break;
- case VolumeInfo.STATE_REMOVED:
- case VolumeInfo.STATE_UNMOUNTED:
- case VolumeInfo.STATE_BAD_REMOVAL:
- case VolumeInfo.STATE_EJECTING:
- // Remove removed storage from list and don't show it on spinner.
- if (mStorageEntries.remove(changedStorageEntry)) {
- if (changedStorageEntry.equals(mSelectedStorageEntry)) {
- mSelectedStorageEntry =
- StorageEntry.getDefaultInternalStorageEntry(getContext());
- }
- refreshUi();
- }
- break;
default:
// Do nothing.
}
diff --git a/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java b/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java
index 42a3a16..4b87e42 100644
--- a/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java
+++ b/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java
@@ -26,6 +26,7 @@
import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -53,6 +54,8 @@
public class VolumeOptionMenuController implements LifecycleObserver, OnCreateOptionsMenu,
OnPrepareOptionsMenu, OnOptionsItemSelected {
+ private static final String TAG = "VolumeOptionMenuController";
+
@VisibleForTesting
MenuItem mRename;
@VisibleForTesting
@@ -103,6 +106,17 @@
mFree = menu.findItem(R.id.storage_free);
mForget = menu.findItem(R.id.storage_forget);
+ updateOptionsMenu();
+ }
+
+ private void updateOptionsMenu() {
+ if (mRename == null || mMount == null || mUnmount == null || mFormat == null
+ || mFormatAsPortable == null || mFormatAsInternal == null || mMigrate == null
+ || mFree == null || mForget == null) {
+ Log.d(TAG, "Menu items are not available");
+ return;
+ }
+
mRename.setVisible(false);
mMount.setVisible(false);
mUnmount.setVisible(false);
@@ -252,5 +266,7 @@
public void setSelectedStorageEntry(StorageEntry storageEntry) {
mStorageEntry = storageEntry;
+
+ updateOptionsMenu();
}
}
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index 0251687..c7bd3b5 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -20,6 +20,8 @@
import static android.provider.Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_HIGHLIGHT_MENU_KEY;
import static android.provider.Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI;
+import static com.android.settings.SettingsActivity.EXTRA_USER_HANDLE;
+
import android.animation.LayoutTransition;
import android.app.ActivityManager;
import android.app.settings.SettingsEnums;
@@ -27,6 +29,7 @@
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.FeatureFlagUtils;
@@ -86,7 +89,6 @@
private TopLevelSettings mMainFragment;
private View mHomepageView;
- private View mAppBar;
private View mSuggestionView;
private View mTwoPaneSuggestionView;
private CategoryMixin mCategoryMixin;
@@ -171,8 +173,7 @@
mSplitController = SplitController.getInstance();
mIsTwoPane = mSplitController.isActivityEmbedded(this);
- mAppBar = findViewById(R.id.app_bar_container);
- mAppBar.setMinimumHeight(getSearchBoxHeight());
+ updateAppBarMinHeight();
initHomepageContainer();
updateHomepageAppBar();
updateHomepageBackground();
@@ -449,7 +450,13 @@
SplitRule.FINISH_ALWAYS,
SplitRule.FINISH_ALWAYS,
true /* clearTop */);
- startActivity(targetIntent);
+
+ final UserHandle user = intent.getParcelableExtra(EXTRA_USER_HANDLE, UserHandle.class);
+ if (user != null) {
+ startActivityAsUser(targetIntent, user);
+ } else {
+ startActivity(targetIntent);
+ }
}
private String getHighlightMenuKey() {
@@ -482,12 +489,15 @@
if (!mIsEmbeddingActivityEnabled) {
return;
}
+ updateAppBarMinHeight();
if (mIsTwoPane) {
findViewById(R.id.homepage_app_bar_regular_phone_view).setVisibility(View.GONE);
findViewById(R.id.homepage_app_bar_two_pane_view).setVisibility(View.VISIBLE);
+ findViewById(R.id.suggestion_container_two_pane).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.homepage_app_bar_regular_phone_view).setVisibility(View.VISIBLE);
findViewById(R.id.homepage_app_bar_two_pane_view).setVisibility(View.GONE);
+ findViewById(R.id.suggestion_container_two_pane).setVisibility(View.GONE);
}
}
@@ -498,19 +508,20 @@
if (mIsTwoPane) {
int padding = getResources().getDimensionPixelSize(
R.dimen.homepage_padding_horizontal_two_pane);
- mAppBar.setPaddingRelative(padding, 0, padding, 0);
mMainFragment.setPaddingHorizontal(padding);
} else {
- mAppBar.setPaddingRelative(0, 0, 0, 0);
mMainFragment.setPaddingHorizontal(0);
}
mMainFragment.updatePreferencePadding(mIsTwoPane);
}
- private int getSearchBoxHeight() {
+ private void updateAppBarMinHeight() {
final int searchBarHeight = getResources().getDimensionPixelSize(R.dimen.search_bar_height);
- final int searchBarMargin = getResources().getDimensionPixelSize(R.dimen.search_bar_margin);
- return searchBarHeight + searchBarMargin * 2;
+ final int margin = getResources().getDimensionPixelSize(
+ mIsEmbeddingActivityEnabled && mIsTwoPane
+ ? R.dimen.homepage_app_bar_padding_two_pane
+ : R.dimen.search_bar_margin);
+ findViewById(R.id.app_bar_container).setMinimumHeight(searchBarHeight + margin * 2);
}
private static class SuggestionFragCreator implements FragmentCreator {
diff --git a/src/com/android/settings/localepicker/AppLocalePickerActivity.java b/src/com/android/settings/localepicker/AppLocalePickerActivity.java
index 791a4e8..377a076 100644
--- a/src/com/android/settings/localepicker/AppLocalePickerActivity.java
+++ b/src/com/android/settings/localepicker/AppLocalePickerActivity.java
@@ -118,6 +118,7 @@
/** Sets the app's locale to the supplied language tag */
private void setAppDefaultLocale(String languageTag) {
+ Log.d(TAG, "setAppDefaultLocale: " + languageTag);
LocaleManager localeManager = mContextAsUser.getSystemService(LocaleManager.class);
if (localeManager == null) {
Log.w(TAG, "LocaleManager is null, cannot set default app locale");
diff --git a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
index 35f6257..61682d0 100644
--- a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
@@ -20,6 +20,7 @@
import android.icu.text.RelativeDateTimeFormatter;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import androidx.annotation.VisibleForTesting;
@@ -27,6 +28,7 @@
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
@@ -82,14 +84,18 @@
RecentAppOpsAccess recentLocationApps) {
super(context, key);
mRecentLocationApps = recentLocationApps;
- mShowSystem = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1;
+ mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false)
+ ? Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1
+ : false;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mCategoryRecentLocationRequests = screen.findPreference(getPreferenceKey());
+ mLocationEnabler.refreshLocationMode();
loadRecentAccesses();
}
diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllButtonPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessSeeAllButtonPreferenceController.java
index 68cde63..2f1232b 100644
--- a/src/com/android/settings/location/RecentLocationAccessSeeAllButtonPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationAccessSeeAllButtonPreferenceController.java
@@ -39,6 +39,7 @@
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
+ mLocationEnabler.refreshLocationMode();
}
@Override
diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java b/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java
index f7bf31a..ecbcb30 100644
--- a/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java
+++ b/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java
@@ -17,11 +17,13 @@
import android.content.Context;
import android.os.Bundle;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
@@ -58,8 +60,11 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mShowSystem = Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1;
+ mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false)
+ ? Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1
+ : false;
}
@Override
diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java
index 75406f7..d658667 100644
--- a/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java
@@ -20,11 +20,13 @@
import android.content.Context;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.R;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.overlay.FeatureFactory;
@@ -48,8 +50,12 @@
public RecentLocationAccessSeeAllPreferenceController(Context context, String key) {
super(context, key);
- mShowSystem = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1;
+ mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false)
+ ? Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1
+ : false;
+
mRecentLocationAccesses = RecentAppOpsAccess.createForLocation(context);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
diff --git a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
index a14e047..39211ee 100644
--- a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
@@ -17,6 +17,7 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import androidx.annotation.VisibleForTesting;
@@ -24,6 +25,7 @@
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.R;
import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
import com.android.settings.core.SubSettingLauncher;
@@ -84,8 +86,11 @@
final Context prefContext = mCategoryRecentLocationRequests.getContext();
final List<RecentLocationApps.Request> recentLocationRequests = new ArrayList<>();
final UserManager userManager = UserManager.get(mContext);
- final boolean showSystem = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1;
+ final boolean showSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false)
+ ? Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1
+ : false;
for (RecentLocationApps.Request request : mRecentLocationApps.getAppListSorted(
showSystem)) {
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index de4d127..ec17dd3 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -67,7 +67,6 @@
import com.android.settings.datausage.DataUsageUtils;
import com.android.settings.location.WifiScanningFragment;
import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.utils.AnnotationSpan;
import com.android.settings.wifi.AddNetworkFragment;
import com.android.settings.wifi.AddWifiNetworkPreference;
import com.android.settings.wifi.ConfigureWifiEntryFragment;
@@ -829,12 +828,10 @@
return;
}
if (TextUtils.isEmpty(mWifiStatusMessagePreference.getTitle())) {
- AnnotationSpan.LinkInfo info = new AnnotationSpan.LinkInfo(
- AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION,
- v -> launchWifiScanningFragment());
- CharSequence text = AnnotationSpan.linkify(
- context.getText(R.string.wifi_scan_notify_message), info);
- mWifiStatusMessagePreference.setTitle(text);
+ mWifiStatusMessagePreference.setTitle(R.string.wifi_scan_notify_message);
+ mWifiStatusMessagePreference.setLearnMoreText(
+ context.getString(R.string.wifi_scan_change));
+ mWifiStatusMessagePreference.setLearnMoreAction(v -> launchWifiScanningFragment());
}
mWifiStatusMessagePreference.setVisible(true);
}
diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java
index 44ad411..7ba16e3 100644
--- a/src/com/android/settings/network/SubscriptionsPreferenceController.java
+++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java
@@ -456,7 +456,11 @@
}
@Override
- public void onTelephonyDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
+ public void onTelephonyDisplayInfoChanged(int subId,
+ TelephonyDisplayInfo telephonyDisplayInfo) {
+ if (subId != mSubsPrefCtrlInjector.getDefaultDataSubscriptionId()) {
+ return;
+ }
mTelephonyDisplayInfo = telephonyDisplayInfo;
update();
}
diff --git a/src/com/android/settings/network/telephony/TelephonyDisplayInfoListener.java b/src/com/android/settings/network/telephony/TelephonyDisplayInfoListener.java
index 334da3c..57a012c 100644
--- a/src/com/android/settings/network/telephony/TelephonyDisplayInfoListener.java
+++ b/src/com/android/settings/network/telephony/TelephonyDisplayInfoListener.java
@@ -37,8 +37,9 @@
private TelephonyManager mBaseTelephonyManager;
private Callback mCallback;
private Map<Integer, PhoneStateListener> mListeners;
+ private Map<Integer, TelephonyDisplayInfo> mDisplayInfos;
- private TelephonyDisplayInfo mTelephonyDisplayInfo =
+ private static final TelephonyDisplayInfo mDefaultTelephonyDisplayInfo =
new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
/**
@@ -48,19 +49,20 @@
/**
* Used to notify TelephonyDisplayInfo change.
*/
- void onTelephonyDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo);
+ void onTelephonyDisplayInfoChanged(int subId, TelephonyDisplayInfo telephonyDisplayInfo);
}
public TelephonyDisplayInfoListener(Context context, Callback callback) {
mBaseTelephonyManager = context.getSystemService(TelephonyManager.class);
mCallback = callback;
mListeners = new HashMap<>();
+ mDisplayInfos = new HashMap<>();
}
/**
* Get TelephonyDisplayInfo.
*/
- public TelephonyDisplayInfo getTelephonyDisplayInfo() {
- return mTelephonyDisplayInfo;
+ public TelephonyDisplayInfo getTelephonyDisplayInfo(int subId) {
+ return mDisplayInfos.get(subId);
}
/** Resumes listening telephony display info changes to the set of ids from the last call to
@@ -85,15 +87,17 @@
for (int idToRemove : Sets.difference(currentIds, ids)) {
stopListening(idToRemove);
mListeners.remove(idToRemove);
+ mDisplayInfos.remove(idToRemove);
}
for (int idToAdd : Sets.difference(ids, currentIds)) {
PhoneStateListener listener = new PhoneStateListener() {
@Override
public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
- mTelephonyDisplayInfo = telephonyDisplayInfo;
- mCallback.onTelephonyDisplayInfoChanged(telephonyDisplayInfo);
+ mDisplayInfos.put(idToAdd, telephonyDisplayInfo);
+ mCallback.onTelephonyDisplayInfoChanged(idToAdd, telephonyDisplayInfo);
}
};
+ mDisplayInfos.put(idToAdd, mDefaultTelephonyDisplayInfo);
mListeners.put(idToAdd, listener);
startListening(idToAdd);
}
diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
index 58afeb0..ed8dc24 100644
--- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
+++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
@@ -52,6 +52,8 @@
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
/**
* Preference controller for "Auto Select Network"
@@ -70,11 +72,17 @@
ProgressDialog mProgressDialog;
@VisibleForTesting
SwitchPreference mSwitchPreference;
+ private AtomicBoolean mUpdatingConfig;
+ private int mCacheOfModeStatus;
+ private AtomicLong mRecursiveUpdate;
public AutoSelectPreferenceController(Context context, String key) {
super(context, key);
mTelephonyManager = context.getSystemService(TelephonyManager.class);
mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ mRecursiveUpdate = new AtomicLong();
+ mUpdatingConfig = new AtomicBoolean();
+ mCacheOfModeStatus = TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
mListeners = new ArrayList<>();
mUiHandler = new Handler(Looper.getMainLooper());
mAllowedNetworkTypesListener = new AllowedNetworkTypesListener(
@@ -88,7 +96,9 @@
displayPreference(mPreferenceScreen);
}
if (mSwitchPreference != null) {
+ mRecursiveUpdate.getAndIncrement();
updateState(mSwitchPreference);
+ mRecursiveUpdate.decrementAndGet();
}
}
@@ -118,8 +128,13 @@
@Override
public boolean isChecked() {
- return mTelephonyManager.getNetworkSelectionMode()
- == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
+ if (!mUpdatingConfig.get()) {
+ mCacheOfModeStatus = mTelephonyManager.getNetworkSelectionMode();
+ for (OnNetworkSelectModeListener lsn : mListeners) {
+ lsn.onNetworkSelectModeUpdated(mCacheOfModeStatus);
+ }
+ }
+ return mCacheOfModeStatus == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
}
@Override
@@ -147,6 +162,10 @@
@Override
public boolean setChecked(boolean isChecked) {
+ if (mRecursiveUpdate.get() != 0) {
+ // Changing from software are allowed and changing presentation only.
+ return true;
+ }
if (isChecked) {
setAutomaticSelectionMode();
} else {
@@ -171,18 +190,17 @@
}
return ThreadUtils.postOnBackgroundThread(() -> {
// set network selection mode in background
+ mUpdatingConfig.set(true);
mTelephonyManager.setNetworkSelectionModeAutomatic();
- final int mode = mTelephonyManager.getNetworkSelectionMode();
+ mUpdatingConfig.set(false);
//Update UI in UI thread
final long durationMillis = SystemClock.elapsedRealtime() - startMillis;
mUiHandler.postDelayed(() -> {
+ mRecursiveUpdate.getAndIncrement();
mSwitchPreference.setEnabled(true);
- mSwitchPreference.setChecked(
- mode == TelephonyManager.NETWORK_SELECTION_MODE_AUTO);
- for (OnNetworkSelectModeListener lsn : mListeners) {
- lsn.onNetworkSelectModeChanged();
- }
+ mSwitchPreference.setChecked(isChecked());
+ mRecursiveUpdate.decrementAndGet();
dismissProgressBar();
}, Math.max(MINIMUM_DIALOG_TIME_MILLIS - durationMillis, 0));
});
@@ -232,11 +250,11 @@
}
/**
- * Callback when network select mode is changed
+ * Callback when network select mode might get updated
*
* @see TelephonyManager#getNetworkSelectionMode()
*/
public interface OnNetworkSelectModeListener {
- void onNetworkSelectModeChanged();
+ void onNetworkSelectModeUpdated(int mode);
}
}
diff --git a/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java b/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java
index 54f5ce1..4c5dd95 100644
--- a/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java
+++ b/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java
@@ -48,11 +48,13 @@
private Preference mPreference;
private PreferenceScreen mPreferenceScreen;
private AllowedNetworkTypesListener mAllowedNetworkTypesListener;
+ private int mCacheOfModeStatus;
public OpenNetworkSelectPagePreferenceController(Context context, String key) {
super(context, key);
mTelephonyManager = context.getSystemService(TelephonyManager.class);
mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ mCacheOfModeStatus = TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
mAllowedNetworkTypesListener = new AllowedNetworkTypesListener(
context.getMainExecutor());
mAllowedNetworkTypesListener.setAllowedNetworkTypesListener(
@@ -96,7 +98,7 @@
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- preference.setEnabled(mTelephonyManager.getNetworkSelectionMode()
+ preference.setEnabled(mCacheOfModeStatus
!= TelephonyManager.NETWORK_SELECTION_MODE_AUTO);
Intent intent = new Intent();
@@ -125,7 +127,10 @@
}
@Override
- public void onNetworkSelectModeChanged() {
- updateState(mPreference);
+ public void onNetworkSelectModeUpdated(int mode) {
+ mCacheOfModeStatus = mode;
+ if (mPreference != null) {
+ updateState(mPreference);
+ }
}
}
diff --git a/src/com/android/settings/notification/SpatialAudioSettings.java b/src/com/android/settings/notification/SpatialAudioSettings.java
index 001c617..3bdb524 100644
--- a/src/com/android/settings/notification/SpatialAudioSettings.java
+++ b/src/com/android/settings/notification/SpatialAudioSettings.java
@@ -17,11 +17,15 @@
package com.android.settings.notification;
import android.app.settings.SettingsEnums;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.FooterPreference;
/**
* Spatial audio settings located in the sound menu
@@ -30,6 +34,20 @@
public class SpatialAudioSettings extends DashboardFragment {
private static final String TAG = "SpatialAudioSettings";
+ private static final String KEY_FOOTER = "spatial_audio_footer";
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ super.onCreatePreferences(savedInstanceState, rootKey);
+
+ FooterPreference footerPreference = findPreference(KEY_FOOTER);
+ if (footerPreference != null) {
+ footerPreference.setLearnMoreText(
+ getString(R.string.spatial_audio_footer_learn_more_text));
+ footerPreference.setLearnMoreAction(
+ view -> startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS)));
+ }
+ }
@Override
public int getMetricsCategory() {
diff --git a/src/com/android/settings/notification/history/NotificationSbnViewHolder.java b/src/com/android/settings/notification/history/NotificationSbnViewHolder.java
index 166ee5d..1a703eb 100644
--- a/src/com/android/settings/notification/history/NotificationSbnViewHolder.java
+++ b/src/com/android/settings/notification/history/NotificationSbnViewHolder.java
@@ -98,9 +98,7 @@
boolean isSnoozed, UiEventLogger uiEventLogger) {
Intent appIntent = itemView.getContext().getPackageManager()
.getLaunchIntentForPackage(pkg);
- boolean isPendingIntentValid = pi != null && PendingIntent.getActivity(
- itemView.getContext(), 0, pi.getIntent(),
- PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_NO_CREATE) != null;
+ boolean isPendingIntentValid = pi != null && pi.isActivity();
if (isPendingIntentValid || appIntent != null) {
itemView.setOnClickListener(v -> {
uiEventLogger.logWithInstanceIdAndPosition(
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 8b78882..aff7197 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -148,7 +148,10 @@
public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider(Context context);
- public abstract BluetoothFeatureProvider getBluetoothFeatureProvider(Context context);
+ /**
+ * Retrieves implementation for Bluetooth feature.
+ */
+ public abstract BluetoothFeatureProvider getBluetoothFeatureProvider();
public abstract AwareFeatureProvider getAwareFeatureProvider();
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 4d8dad0..89f74de 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -280,10 +280,9 @@
}
@Override
- public BluetoothFeatureProvider getBluetoothFeatureProvider(Context context) {
+ public BluetoothFeatureProvider getBluetoothFeatureProvider() {
if (mBluetoothFeatureProvider == null) {
- mBluetoothFeatureProvider = new BluetoothFeatureProviderImpl(
- context.getApplicationContext());
+ mBluetoothFeatureProvider = new BluetoothFeatureProviderImpl(getAppContext());
}
return mBluetoothFeatureProvider;
}
diff --git a/src/com/android/settings/privacy/PrivacyDashboardFragment.java b/src/com/android/settings/privacy/PrivacyDashboardFragment.java
index df59bd5..75ed225 100644
--- a/src/com/android/settings/privacy/PrivacyDashboardFragment.java
+++ b/src/com/android/settings/privacy/PrivacyDashboardFragment.java
@@ -25,6 +25,7 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
+import android.provider.SearchIndexableResource;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
@@ -36,6 +37,7 @@
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
@SearchIndexable
@@ -72,12 +74,6 @@
replaceEnterpriseStringSummary("work_policy_info",
WORK_PROFILE_PRIVACY_POLICY_INFO_SUMMARY,
R.string.work_policy_privacy_settings_summary);
-
- }
-
- @Override
- protected int getPreferenceScreenResId() {
- return R.xml.privacy_dashboard_settings;
}
@Override
@@ -90,6 +86,19 @@
return buildPreferenceControllers(context, getSettingsLifecycle());
}
+ @Override
+ protected int getPreferenceScreenResId() {
+ return getPreferenceScreenResId(getContext());
+ }
+
+ private static int getPreferenceScreenResId(Context context) {
+ if (SafetyCenterManagerWrapper.get().isEnabled(context)) {
+ return R.xml.privacy_advanced_settings;
+ } else {
+ return R.xml.privacy_dashboard_settings;
+ }
+ }
+
private static List<AbstractPreferenceController> buildPreferenceControllers(
Context context, Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
@@ -108,17 +117,19 @@
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider(R.xml.privacy_dashboard_settings) {
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = getPreferenceScreenResId(context);
+ return Arrays.asList(sir);
+ }
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
return buildPreferenceControllers(context, null);
}
-
- @Override
- protected boolean isPageSearchEnabled(Context context) {
- return !SafetyCenterManagerWrapper.get().isEnabled(context);
- }
};
}
diff --git a/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java b/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java
index 3ea23f3..0b556e7 100644
--- a/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java
+++ b/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java
@@ -49,9 +49,9 @@
if (ACTION_REFRESH_SAFETY_SOURCES.equals(intent.getAction())) {
String[] sourceIdsExtra =
intent.getStringArrayExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS);
- if (sourceIdsExtra != null && sourceIdsExtra.length > 0) {
- final String refreshBroadcastId = intent.getStringExtra(
- SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID);
+ final String refreshBroadcastId = intent.getStringExtra(
+ SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID);
+ if (sourceIdsExtra != null && sourceIdsExtra.length > 0 && refreshBroadcastId != null) {
final SafetyEvent safetyEvent = new SafetyEvent.Builder(
SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
.setRefreshBroadcastId(refreshBroadcastId).build();
diff --git a/src/com/android/settings/widget/SettingsMainSwitchPreference.java b/src/com/android/settings/widget/SettingsMainSwitchPreference.java
index b7c6901..9264911 100644
--- a/src/com/android/settings/widget/SettingsMainSwitchPreference.java
+++ b/src/com/android/settings/widget/SettingsMainSwitchPreference.java
@@ -22,6 +22,7 @@
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.ViewGroup;
import android.widget.Switch;
import androidx.core.content.res.TypedArrayUtils;
@@ -33,6 +34,8 @@
import com.android.settingslib.RestrictedPreferenceHelper;
import com.android.settingslib.widget.OnMainSwitchChangeListener;
+import com.google.android.setupdesign.util.LayoutStyler;
+
import java.util.ArrayList;
import java.util.List;
@@ -48,6 +51,7 @@
new ArrayList<>();
private final List<OnMainSwitchChangeListener> mSwitchChangeListeners = new ArrayList<>();
+ private boolean mApplyPartnerCustomizationPaddingStyle;
private SettingsMainSwitchBar mMainSwitchBar;
private CharSequence mTitle;
private EnforcedAdmin mEnforcedAdmin;
@@ -95,6 +99,12 @@
} else {
mMainSwitchBar.hide();
}
+
+ if (mApplyPartnerCustomizationPaddingStyle) {
+ // TODO(b/232494666): Replace all margins of the root view with the padding
+ final ViewGroup parentView = (ViewGroup) mMainSwitchBar.getParent();
+ LayoutStyler.applyPartnerCustomizationLayoutPaddingStyle(parentView);
+ }
}
private void init(Context context, AttributeSet attrs) {
@@ -241,6 +251,14 @@
}
}
+ /**
+ * Apples the padding style of the partner's customization. It's used in the SetupWizard.
+ */
+ public void applyPartnerCustomizationPaddingStyle() {
+ mApplyPartnerCustomizationPaddingStyle = true;
+ notifyChanged();
+ }
+
private void initMainSwitchBar() {
if (mMainSwitchBar != null) {
mMainSwitchBar.setTitle(mTitle);
diff --git a/src/com/android/settings/wifi/WifiScanModeActivity.java b/src/com/android/settings/wifi/WifiScanModeActivity.java
index 9d50281..d372135 100644
--- a/src/com/android/settings/wifi/WifiScanModeActivity.java
+++ b/src/com/android/settings/wifi/WifiScanModeActivity.java
@@ -20,26 +20,30 @@
import android.app.settings.SettingsEnums;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.WindowManager;
+import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.R;
+import com.android.settings.Utils;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settingslib.wifi.WifiPermissionChecker;
/**
* This activity requests users permission to allow scanning even when Wi-Fi is turned off
*/
public class WifiScanModeActivity extends FragmentActivity {
private DialogFragment mDialog;
- private String mApp;
+ @VisibleForTesting
+ String mApp;
+ @VisibleForTesting
+ WifiPermissionChecker mWifiPermissionChecker;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -50,13 +54,7 @@
if (savedInstanceState == null) {
if (intent != null && WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE
.equals(intent.getAction())) {
- ApplicationInfo ai;
- mApp = getCallingPackage();
- try {
- PackageManager pm = getPackageManager();
- ai = pm.getApplicationInfo(mApp, 0);
- mApp = (String)pm.getApplicationLabel(ai);
- } catch (PackageManager.NameNotFoundException e) { }
+ refreshAppLabel();
} else {
finish();
return;
@@ -67,6 +65,19 @@
createDialog();
}
+ @VisibleForTesting
+ void refreshAppLabel() {
+ if (mWifiPermissionChecker == null) {
+ mWifiPermissionChecker = new WifiPermissionChecker(this);
+ }
+ String packageName = mWifiPermissionChecker.getLaunchedPackage();
+ if (TextUtils.isEmpty(packageName)) {
+ mApp = null;
+ return;
+ }
+ mApp = Utils.getApplicationLabel(getApplicationContext(), packageName).toString();
+ }
+
private void createDialog() {
if (mDialog == null) {
mDialog = AlertDialogFragment.newInstance(mApp);
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettings.java b/src/com/android/settings/wifi/calling/WifiCallingSettings.java
index 25508f7..b4951bf 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettings.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettings.java
@@ -30,13 +30,12 @@
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import com.android.internal.util.CollectionUtils;
import com.android.settings.R;
-import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.network.ActiveSubscriptionsListener;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.network.ims.WifiCallingQueryImsState;
@@ -54,7 +53,8 @@
* "Wi-Fi Calling settings" screen. This is the container fragment which holds
* {@link WifiCallingSettingsForSub} fragments.
*/
-public class WifiCallingSettings extends InstrumentedFragment implements HelpResourceProvider {
+public class WifiCallingSettings extends SettingsPreferenceFragment
+ implements HelpResourceProvider {
private static final String TAG = "WifiCallingSettings";
private int mConstructionSubId;
private List<SubscriptionInfo> mSil;
@@ -317,17 +317,7 @@
}
// close this fragment
- finish();
- }
-
- protected void finish() {
- FragmentActivity activity = getActivity();
- if (activity == null) return;
- if (getFragmentManager().getBackStackEntryCount() > 0) {
- getFragmentManager().popBackStack();
- } else {
- activity.finish();
- }
+ finishFragment();
}
protected int [] subscriptionIdList(List<SubscriptionInfo> subInfoList) {
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
index 749af3e..492a228 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
@@ -27,7 +27,6 @@
import android.os.Bundle;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
-import android.telephony.PhoneStateListener;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
@@ -40,7 +39,6 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
-import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
@@ -56,8 +54,7 @@
import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.network.ims.WifiCallingQueryImsState;
-import com.android.settings.widget.SettingsMainSwitchBar;
-import com.android.settings.wifi.calling.LinkifyDescriptionPreference;
+import com.android.settings.widget.SettingsMainSwitchPreference;
import com.android.settingslib.widget.OnMainSwitchChangeListener;
import java.util.List;
@@ -72,6 +69,7 @@
private static final String TAG = "WifiCallingForSub";
//String keys for preference lookup
+ private static final String SWITCH_BAR = "wifi_calling_switch_bar";
private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
private static final String PREFERENCE_EMERGENCY_ADDRESS = "emergency_address_key";
@@ -91,7 +89,7 @@
public static final int LAUCH_APP_UPDATE = 1;
//UI objects
- private SettingsMainSwitchBar mSwitchBar;
+ private SettingsMainSwitchPreference mSwitchBar;
private ListWithEntrySummaryPreference mButtonWfcMode;
private ListWithEntrySummaryPreference mButtonWfcRoamingMode;
private Preference mUpdateAddress;
@@ -119,41 +117,57 @@
@Override
public void onCallStateChanged(int state) {
final SettingsActivity activity = (SettingsActivity) getActivity();
- final boolean isNonTtyOrTtyOnVolteEnabled =
- queryImsState(WifiCallingSettingsForSub.this.mSubId).isAllowUserControl();
- final boolean isWfcEnabled = mSwitchBar.isChecked()
- && isNonTtyOrTtyOnVolteEnabled;
- boolean isCallStateIdle = getTelephonyManagerForSub(
- WifiCallingSettingsForSub.this.mSubId).getCallState()
- == TelephonyManager.CALL_STATE_IDLE;
- mSwitchBar.setEnabled(isCallStateIdle
- && isNonTtyOrTtyOnVolteEnabled);
+
+ boolean isWfcEnabled = false;
+ boolean isCallStateIdle = false;
+
+ final SettingsMainSwitchPreference prefSwitch = (SettingsMainSwitchPreference)
+ getPreferenceScreen().findPreference(SWITCH_BAR);
+ if (prefSwitch != null) {
+ isWfcEnabled = prefSwitch.isChecked();
+ isCallStateIdle = getTelephonyManagerForSub(
+ WifiCallingSettingsForSub.this.mSubId).getCallState()
+ == TelephonyManager.CALL_STATE_IDLE;
+
+ boolean isNonTtyOrTtyOnVolteEnabled = true;
+ if (isWfcEnabled || isCallStateIdle) {
+ isNonTtyOrTtyOnVolteEnabled =
+ queryImsState(WifiCallingSettingsForSub.this.mSubId)
+ .isAllowUserControl();
+ }
+
+ isWfcEnabled = isWfcEnabled && isNonTtyOrTtyOnVolteEnabled;
+ prefSwitch.setEnabled(isCallStateIdle && isNonTtyOrTtyOnVolteEnabled);
+ }
boolean isWfcModeEditable = true;
boolean isWfcRoamingModeEditable = false;
- final CarrierConfigManager configManager = (CarrierConfigManager)
- activity.getSystemService(Context.CARRIER_CONFIG_SERVICE);
- if (configManager != null) {
- PersistableBundle b =
- configManager.getConfigForSubId(WifiCallingSettingsForSub.this.mSubId);
- if (b != null) {
- isWfcModeEditable = b.getBoolean(
- CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
- isWfcRoamingModeEditable = b.getBoolean(
- CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
+ if (isWfcEnabled && isCallStateIdle) {
+ final CarrierConfigManager configManager = (CarrierConfigManager)
+ activity.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configManager != null) {
+ PersistableBundle b = configManager.getConfigForSubId(
+ WifiCallingSettingsForSub.this.mSubId);
+ if (b != null) {
+ isWfcModeEditable = b.getBoolean(
+ CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
+ isWfcRoamingModeEditable = b.getBoolean(
+ CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
+ }
}
+ } else {
+ isWfcModeEditable = false;
+ isWfcRoamingModeEditable = false;
}
final Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE);
if (pref != null) {
- pref.setEnabled(isWfcEnabled && isWfcModeEditable
- && isCallStateIdle);
+ pref.setEnabled(isWfcModeEditable);
}
final Preference pref_roam =
getPreferenceScreen().findPreference(BUTTON_WFC_ROAMING_MODE);
if (pref_roam != null) {
- pref_roam.setEnabled(isWfcEnabled && isWfcRoamingModeEditable
- && isCallStateIdle);
+ pref_roam.setEnabled(isWfcRoamingModeEditable);
}
}
}
@@ -184,20 +198,6 @@
}
};
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- mSwitchBar = getView().findViewById(R.id.switch_bar);
- mSwitchBar.show();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- mSwitchBar.hide();
- }
-
@VisibleForTesting
void showAlert(Intent intent) {
final Context context = getActivity();
@@ -292,6 +292,8 @@
mProvisioningManager = getImsProvisioningManager();
mImsMmTelManager = getImsMmTelManager();
+ mSwitchBar = (SettingsMainSwitchPreference) findPreference(SWITCH_BAR);
+
mButtonWfcMode = findPreference(BUTTON_WFC_MODE);
mButtonWfcMode.setOnPreferenceChangeListener(this);
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
index 5d28bcc..10ee241 100644
--- a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
+++ b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
@@ -522,7 +522,7 @@
final LayoutInflater layoutInflater = LayoutInflater.from(getPrefContext());
final View root = layoutInflater.inflate(R.layout.dialog_edittext, null /* root */);
mDeviceNameText = root.findViewById(R.id.edittext);
- mDeviceNameText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(30)});
+ mDeviceNameText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(22)});
if (mSavedDeviceName != null) {
mDeviceNameText.setText(mSavedDeviceName);
mDeviceNameText.setSelection(mSavedDeviceName.length());
diff --git a/src/com/android/settings/wifi/tether/TetherService.java b/src/com/android/settings/wifi/tether/TetherService.java
index 8a557ba..b0e8fd8 100644
--- a/src/com/android/settings/wifi/tether/TetherService.java
+++ b/src/com/android/settings/wifi/tether/TetherService.java
@@ -256,6 +256,7 @@
}
private void disableTethering(final int tetheringType) {
+ Log.w(TAG, "Disable tethering, type:" + tetheringType);
final TetheringManager tm = (TetheringManager) getSystemService(Context.TETHERING_SERVICE);
tm.stopTethering(tetheringType);
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
index 580bc39..e88931c 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
@@ -31,6 +31,7 @@
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Looper;
+import android.util.Log;
import android.widget.Switch;
import androidx.annotation.VisibleForTesting;
@@ -47,6 +48,8 @@
*/
public class WifiTetherSwitchBarController implements
LifecycleObserver, OnStart, OnStop, DataSaverBackend.Listener, OnMainSwitchChangeListener {
+
+ private static final String TAG = "WifiTetherSBC";
private static final IntentFilter WIFI_INTENT_FILTER;
private final Context mContext;
@@ -63,8 +66,8 @@
@Override
public void onTetheringFailed() {
super.onTetheringFailed();
- mSwitchBar.setChecked(false);
- updateWifiSwitch();
+ Log.e(TAG, "Failed to start Wi-Fi Tethering.");
+ handleWifiApStateChanged(mWifiManager.getWifiApState());
}
};
@@ -111,16 +114,28 @@
}
void stopTether() {
+ if (!isWifiApActivated()) return;
+
mSwitchBar.setEnabled(false);
mConnectivityManager.stopTethering(TETHERING_WIFI);
}
void startTether() {
+ if (isWifiApActivated()) return;
+
mSwitchBar.setEnabled(false);
mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
}
+ private boolean isWifiApActivated() {
+ final int wifiApState = mWifiManager.getWifiApState();
+ if (wifiApState == WIFI_AP_STATE_ENABLED || wifiApState == WIFI_AP_STATE_ENABLING) {
+ return true;
+ }
+ return false;
+ }
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceControllerTest.java
index a455648..affb28b 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceControllerTest.java
@@ -18,9 +18,8 @@
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.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -34,12 +33,16 @@
import android.content.BroadcastReceiver;
import android.content.Intent;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
+import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
+import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.HearingAidProfile;
@@ -48,7 +51,6 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -62,8 +64,8 @@
import java.util.ArrayList;
import java.util.List;
+/** Tests for {@link AccessibilityHearingAidPreferenceController}. */
@RunWith(RobolectricTestRunner.class)
-@Ignore
@Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class})
public class AccessibilityHearingAidPreferenceControllerTest {
private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
@@ -82,10 +84,14 @@
@Mock
private CachedBluetoothDevice mCachedBluetoothDevice;
@Mock
+ private CachedBluetoothDevice mCachedSubBluetoothDevice;
+ @Mock
private CachedBluetoothDeviceManager mCachedDeviceManager;
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
@Mock
+ private BluetoothEventManager mEventManager;
+ @Mock
private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
@Mock
private HearingAidProfile mHearingAidProfile;
@@ -111,18 +117,54 @@
}
@Test
- public void onHearingAidStateChanged_connected_updateHearingAidSummary() {
+ public void getSummary_connectedHearingAidRightSide_connectedRightSideSummary() {
+ when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
+ HearingAidProfile.DeviceSide.SIDE_RIGHT);
when(mHearingAidProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHearingAid.STATE_CONNECTED);
sendIntent(intent);
- assertThat(mHearingAidPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME);
+ assertThat(mHearingAidPreference.getSummary().toString().contentEquals(
+ "TEST_HEARING_AID_BT_DEVICE_NAME, right only")).isTrue();
}
@Test
- public void onHearingAidStateChanged_disconnected_updateHearingAidSummary() {
+ public void getSummary_connectedHearingAidBothSide_connectedBothSideSummary() {
+ when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
+ HearingAidProfile.DeviceSide.SIDE_LEFT);
+ when(mCachedSubBluetoothDevice.isConnected()).thenReturn(true);
+ when(mCachedBluetoothDevice.getSubDevice()).thenReturn(mCachedSubBluetoothDevice);
+ when(mHearingAidProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
+ mPreferenceController.onStart();
+ Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+ intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHearingAid.STATE_CONNECTED);
+ sendIntent(intent);
+
+ assertThat(mHearingAidPreference.getSummary().toString().contentEquals(
+ "TEST_HEARING_AID_BT_DEVICE_NAME, left and right")).isTrue();
+ }
+
+ @Test
+ public void getSummary_connectedMultipleHearingAids_connectedBothSideSummary() {
+ when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
+ HearingAidProfile.DeviceSide.SIDE_LEFT);
+ when(mCachedSubBluetoothDevice.isConnected()).thenReturn(true);
+ when(mCachedBluetoothDevice.getSubDevice()).thenReturn(mCachedSubBluetoothDevice);
+ when(mHearingAidProfile.getConnectedDevices()).thenReturn(
+ generateMultipleHearingAidDeviceList());
+ mPreferenceController.onStart();
+ Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+ intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHearingAid.STATE_CONNECTED);
+ sendIntent(intent);
+
+ assertThat(mHearingAidPreference.getSummary().toString().contentEquals(
+ "TEST_HEARING_AID_BT_DEVICE_NAME +1 more")).isTrue();
+ }
+
+ @Test
+ public void getSummary_disconnectedHearingAid_disconnectedSummary() {
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHearingAid.STATE_DISCONNECTED);
@@ -133,7 +175,7 @@
}
@Test
- public void onBluetoothStateChanged_bluetoothOff_updateHearingAidSummary() {
+ public void getSummary_bluetoothOff_disconnectedSummary() {
mPreferenceController.onStart();
Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
@@ -168,19 +210,14 @@
}
@Test
- public void onNotSupportHearingAidProfile_doNotDoReceiverOperation() {
+ public void onNotSupportHearingAidProfile_isNotAvailable() {
//clear bluetooth supported profile
mShadowBluetoothAdapter.clearSupportedProfiles();
mPreferenceController = new AccessibilityHearingAidPreferenceController(mContext,
HEARING_AID_PREFERENCE);
mPreferenceController.setPreference(mHearingAidPreference);
- //not call registerReceiver()
- mPreferenceController.onStart();
- verify(mContext, never()).registerReceiver(any(), any());
- //not call unregisterReceiver()
- mPreferenceController.onStop();
- verify(mContext, never()).unregisterReceiver(any());
+ assertThat(mPreferenceController.isAvailable()).isFalse();
}
@Test
@@ -192,6 +229,24 @@
assertThat(mPreferenceController.getConnectedHearingAidDevice()).isNull();
}
+ @Test
+ @Config(shadows = ShadowAlertDialogCompat.class)
+ public void onActiveDeviceChanged_hearingAidProfile_launchHearingAidPairingDialog() {
+ final FragmentActivity mActivity = Robolectric.setupActivity(FragmentActivity.class);
+ when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDeviceMode()).thenReturn(
+ HearingAidProfile.DeviceMode.MODE_BINAURAL);
+ when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
+ HearingAidProfile.DeviceSide.SIDE_LEFT);
+ mPreferenceController.setFragmentManager(mActivity.getSupportFragmentManager());
+
+ mPreferenceController.onActiveDeviceChanged(mCachedBluetoothDevice,
+ BluetoothProfile.HEARING_AID);
+
+ final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog.isShowing()).isTrue();
+ }
+
private void setupBluetoothEnvironment() {
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
@@ -200,6 +255,7 @@
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
+ doReturn(mEventManager).when(mLocalBluetoothManager).getEventManager();
}
private void setupHearingAidEnvironment() {
@@ -210,7 +266,6 @@
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HEARING_AID);
when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice);
when(mCachedBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME);
- when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
}
private void sendIntent(Intent intent) {
@@ -224,4 +279,11 @@
deviceList.add(mBluetoothDevice);
return deviceList;
}
+
+ private List<BluetoothDevice> generateMultipleHearingAidDeviceList() {
+ final List<BluetoothDevice> deviceList = new ArrayList<>(2);
+ deviceList.add(mBluetoothDevice);
+ deviceList.add(mBluetoothDevice);
+ return deviceList;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index 7c52754..891439e 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -58,6 +58,7 @@
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.RestrictedPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.search.SearchIndexableRaw;
import org.junit.Before;
@@ -93,6 +94,7 @@
private static final String DEFAULT_LABEL = "default label";
private static final Boolean SERVICE_ENABLED = true;
private static final Boolean SERVICE_DISABLED = false;
+
@Rule
public final MockitoRule mocks = MockitoJUnit.rule();
@Spy
@@ -114,6 +116,8 @@
@Mock
private AppOpsManager mAppOpsManager;
+ private Lifecycle mLifecycle;
+
@Before
public void setup() {
mShadowAccessibilityManager = Shadow.extract(AccessibilityManager.getInstance(mContext));
@@ -127,6 +131,8 @@
when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS),
anyInt(), anyString())).thenReturn(AppOpsManager.MODE_ALLOWED);
+ mLifecycle = new Lifecycle(() -> mLifecycle);
+ when(mFragment.getSettingsLifecycle()).thenReturn(mLifecycle);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/accessibility/HearingAidPairingDialogFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/HearingAidPairingDialogFragmentTest.java
new file mode 100644
index 0000000..5c440d2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/HearingAidPairingDialogFragmentTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2022 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.spy;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.settings.SettingsActivity;
+import com.android.settings.bluetooth.BluetoothPairingDetail;
+import com.android.settings.bluetooth.HearingAidPairingDialogFragment;
+import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+/** Tests for {@link HearingAidPairingDialogFragment}. */
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowAlertDialogCompat.class)
+public class HearingAidPairingDialogFragmentTest {
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ private static final String KEY_CACHED_DEVICE_SIDE = "cached_device_side";
+
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDevice;
+ private FragmentActivity mActivity;
+ private HearingAidPairingDialogFragment mFragment;
+
+ @Before
+ public void setUp() {
+ mFragment = spy(HearingAidPairingDialogFragment.newInstance(mCachedBluetoothDevice));
+ mActivity = Robolectric.setupActivity(FragmentActivity.class);
+ when(mFragment.getActivity()).thenReturn(mActivity);
+ }
+
+ @Test
+ public void newInstance_deviceSideRight_argumentSideRight() {
+ when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
+ HearingAidProfile.DeviceSide.SIDE_RIGHT);
+
+ mFragment = HearingAidPairingDialogFragment.newInstance(mCachedBluetoothDevice);
+
+ final Bundle bundle = mFragment.getArguments();
+ assertThat(bundle.getInt(KEY_CACHED_DEVICE_SIDE)).isEqualTo(
+ HearingAidProfile.DeviceSide.SIDE_RIGHT);
+ }
+
+ @Test
+ public void dialogPositiveButtonClick_intentToExpectedClass() {
+ final AlertDialog dialog = (AlertDialog) mFragment.onCreateDialog(Bundle.EMPTY);
+ dialog.show();
+
+ dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
+
+ final Intent intent = shadowOf(mActivity).getNextStartedActivity();
+ assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(BluetoothPairingDetail.class.getName());
+ }
+
+ @Test
+ public void dialogNegativeButtonClick_dismissDialog() {
+ final AlertDialog dialog = (AlertDialog) mFragment.onCreateDialog(Bundle.EMPTY);
+ dialog.show();
+
+ dialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick();
+
+ assertThat(dialog.isShowing()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/HearingAidUtilsTest.java b/tests/robotests/src/com/android/settings/accessibility/HearingAidUtilsTest.java
new file mode 100644
index 0000000..6918fb6
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/HearingAidUtilsTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2022 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.when;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+/** Tests for {@link HearingAidUtils}. */
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowAlertDialogCompat.class)
+public class HearingAidUtilsTest {
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDevice;
+ @Mock
+ private CachedBluetoothDevice mSubCachedBluetoothDevice;
+
+ private FragmentManager mFragmentManager;
+
+ @Before
+ public void setUp() {
+ final FragmentActivity mActivity = Robolectric.setupActivity(FragmentActivity.class);
+ mFragmentManager = mActivity.getSupportFragmentManager();
+ }
+
+ @After
+ public void tearDown() {
+ ShadowAlertDialogCompat.reset();
+ }
+ @Test
+ public void launchHearingAidPairingDialog_deviceNotConnectedHearingAid_noDialog() {
+ when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(false);
+
+ HearingAidUtils.launchHearingAidPairingDialog(mFragmentManager, mCachedBluetoothDevice);
+
+ final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog).isNull();
+ }
+
+ @Test
+ public void launchHearingAidPairingDialog_deviceIsModeMonaural_noDialog() {
+ when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDeviceMode()).thenReturn(
+ HearingAidProfile.DeviceMode.MODE_MONAURAL);
+
+ HearingAidUtils.launchHearingAidPairingDialog(mFragmentManager, mCachedBluetoothDevice);
+
+ final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog).isNull();
+ }
+
+ @Test
+ public void launchHearingAidPairingDialog_deviceHasSubDevice_noDialog() {
+ when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDeviceMode()).thenReturn(
+ HearingAidProfile.DeviceMode.MODE_BINAURAL);
+ when(mCachedBluetoothDevice.getSubDevice()).thenReturn(mSubCachedBluetoothDevice);
+
+ HearingAidUtils.launchHearingAidPairingDialog(mFragmentManager, mCachedBluetoothDevice);
+
+ final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog).isNull();
+ }
+
+ @Test
+ public void launchHearingAidPairingDialog_deviceIsInvalidSide_noDialog() {
+ when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDeviceMode()).thenReturn(
+ HearingAidProfile.DeviceMode.MODE_BINAURAL);
+ when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
+ HearingAidProfile.DeviceSide.SIDE_INVALID);
+
+ HearingAidUtils.launchHearingAidPairingDialog(mFragmentManager, mCachedBluetoothDevice);
+
+ final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog).isNull();
+ }
+
+ @Test
+ public void launchHearingAidPairingDialog_dialogShown() {
+ when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDeviceMode()).thenReturn(
+ HearingAidProfile.DeviceMode.MODE_BINAURAL);
+ when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
+ HearingAidProfile.DeviceSide.SIDE_LEFT);
+
+ HearingAidUtils.launchHearingAidPairingDialog(mFragmentManager, mCachedBluetoothDevice);
+
+ final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog.isShowing()).isTrue();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
index 0418906..bddaed5 100644
--- a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
+import static com.android.settings.accessibility.TextReadingPreferenceFragment.RESET_KEY;
+
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -25,6 +27,7 @@
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
+import com.android.settingslib.widget.LayoutPreference;
import com.google.android.setupdesign.GlifPreferenceLayout;
@@ -51,6 +54,9 @@
MockitoAnnotations.initMocks(this);
mFragment = spy(new TextReadingPreferenceFragmentForSetupWizard());
+ final LayoutPreference resetPreference =
+ new LayoutPreference(mContext, R.layout.accessibility_text_reading_reset_button);
+ doReturn(resetPreference).when(mFragment).findPreference(RESET_KEY);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsRelatedToolsControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsRelatedToolsControllerTest.java
new file mode 100644
index 0000000..31d6397
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsRelatedToolsControllerTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowAccessibilityManager;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.List;
+
+/** Tests for {@link BluetoothDetailsRelatedToolsController}. */
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothDetailsRelatedToolsControllerTest extends BluetoothDetailsControllerTestBase {
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ private static final String PACKAGE_NAME = "com.android.test";
+ private static final String PACKAGE_NAME2 = "com.android.test2";
+ private static final String CLASS_NAME = PACKAGE_NAME + ".test_a11y_service";
+ private static final String KEY_RELATED_TOOLS_GROUP = "bluetooth_related_tools";
+ private static final String KEY_LIVE_CAPTION = "live_caption";
+
+
+ private BluetoothDetailsRelatedToolsController mController;
+ private BluetoothFeatureProvider mFeatureProvider;
+ private ShadowAccessibilityManager mShadowAccessibilityManager;
+ private PreferenceCategory mPreferenceCategory;
+
+ @Override
+ public void setUp() {
+ super.setUp();
+ final FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
+ mFeatureProvider = fakeFeatureFactory.getBluetoothFeatureProvider();
+ mShadowAccessibilityManager = Shadow.extract(AccessibilityManager.getInstance(mContext));
+ final Preference preference = new Preference(mContext);
+ preference.setKey(KEY_LIVE_CAPTION);
+ mPreferenceCategory = new PreferenceCategory(mContext);
+ mPreferenceCategory.setKey(KEY_RELATED_TOOLS_GROUP);
+ mScreen.addPreference(mPreferenceCategory);
+ mScreen.addPreference(preference);
+
+ mController = new BluetoothDetailsRelatedToolsController(mContext, mFragment, mCachedDevice,
+ mLifecycle);
+ mController.init(mScreen);
+ }
+
+ @Test
+ public void isAvailable_isHearingAidDevice_available() {
+ when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_notHearingAidDevice_notAvailable() {
+ when(mCachedDevice.isHearingAidDevice()).thenReturn(false);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void displayPreference_oneRelatedToolsMatchA11yService_showOnePreference() {
+ when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
+ mShadowAccessibilityManager.setInstalledAccessibilityServiceList(
+ List.of(getMockAccessibilityServiceInfo(PACKAGE_NAME, CLASS_NAME)));
+ when(mFeatureProvider.getRelatedTools()).thenReturn(
+ List.of(new ComponentName(PACKAGE_NAME, CLASS_NAME)));
+
+ mController.displayPreference(mScreen);
+
+ assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void displayPreference_oneRelatedToolsNotMatchA11yService_showNoPreference() {
+ when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
+ mShadowAccessibilityManager.setInstalledAccessibilityServiceList(
+ List.of(getMockAccessibilityServiceInfo(PACKAGE_NAME, CLASS_NAME)));
+ when(mFeatureProvider.getRelatedTools()).thenReturn(
+ List.of(new ComponentName(PACKAGE_NAME2, CLASS_NAME)));
+
+ mController.displayPreference(mScreen);
+
+ assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void displayPreference_noRelatedTools_showNoPreference() {
+ when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
+ mShadowAccessibilityManager.setInstalledAccessibilityServiceList(
+ List.of(getMockAccessibilityServiceInfo(PACKAGE_NAME, CLASS_NAME)));
+ when(mFeatureProvider.getRelatedTools()).thenReturn(null);
+
+ mController.displayPreference(mScreen);
+
+ assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(0);
+ }
+
+ private AccessibilityServiceInfo getMockAccessibilityServiceInfo(String packageName,
+ String className) {
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ final ServiceInfo serviceInfo = new ServiceInfo();
+ applicationInfo.packageName = packageName;
+ serviceInfo.packageName = packageName;
+ serviceInfo.name = className;
+ serviceInfo.applicationInfo = applicationInfo;
+
+ final ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.serviceInfo = serviceInfo;
+
+ try {
+ final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo,
+ mContext);
+ ComponentName componentName = ComponentName.unflattenFromString(
+ packageName + "/" + className);
+ info.setComponentName(componentName);
+ return info;
+ } catch (XmlPullParserException | IOException e) {
+ // Do nothing
+ }
+
+ return null;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java
index 9ab1d87..3d40bfc 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java
@@ -33,6 +33,11 @@
@RunWith(RobolectricTestRunner.class)
public class BluetoothFeatureProviderImplTest {
private static final String SETTINGS_URI = "content://test.provider/settings_uri";
+ private static final String CONTROL_METADATA =
+ "<HEARABLE_CONTROL_SLICE_WITH_WIDTH>" + SETTINGS_URI
+ + "</HEARABLE_CONTROL_SLICE_WITH_WIDTH>";
+ private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
+
private BluetoothFeatureProvider mBluetoothFeatureProvider;
@Mock
@@ -54,4 +59,13 @@
final Uri uri = mBluetoothFeatureProvider.getBluetoothDeviceSettingsUri(mBluetoothDevice);
assertThat(uri.toString()).isEqualTo(SETTINGS_URI);
}
+
+ @Test
+ public void getBluetoothDeviceControlUri_returnsCorrectUri() {
+ when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)).thenReturn(
+ CONTROL_METADATA.getBytes());
+ assertThat(
+ mBluetoothFeatureProvider.getBluetoothDeviceControlUri(mBluetoothDevice)).isEqualTo(
+ SETTINGS_URI);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java
index da1c493..e1a3da6 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java
@@ -27,10 +27,13 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioManager;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
@@ -40,25 +43,31 @@
import com.android.settings.bluetooth.AvailableMediaBluetoothDeviceUpdater;
import com.android.settings.bluetooth.Utils;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowAudioManager;
+import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothEventManager;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+/** Tests for {@link AvailableMediaDeviceGroupController}. */
@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowAudioManager.class, ShadowBluetoothUtils.class})
+@Config(shadows = {ShadowAudioManager.class, ShadowBluetoothAdapter.class,
+ ShadowBluetoothUtils.class})
public class AvailableMediaDeviceGroupControllerTest {
private static final String PREFERENCE_KEY_1 = "pref_key_1";
@@ -77,6 +86,8 @@
private BluetoothEventManager mEventManager;
@Mock
private LocalBluetoothManager mLocalManager;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDevice;
private PreferenceGroup mPreferenceGroup;
private Context mContext;
@@ -93,27 +104,26 @@
mPreference = new Preference(mContext);
mPreference.setKey(PREFERENCE_KEY_1);
mPreferenceGroup = spy(new PreferenceScreen(mContext, null));
+ final FragmentActivity mActivity = Robolectric.setupActivity(FragmentActivity.class);
when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager);
doReturn(mContext).when(mDashboardFragment).getContext();
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
+ when(mDashboardFragment.getParentFragmentManager()).thenReturn(
+ mActivity.getSupportFragmentManager());
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager;
mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
mAudioManager = mContext.getSystemService(AudioManager.class);
doReturn(mEventManager).when(mLocalBluetoothManager).getEventManager();
- mAvailableMediaDeviceGroupController = new AvailableMediaDeviceGroupController(mContext);
+ mAvailableMediaDeviceGroupController = spy(
+ new AvailableMediaDeviceGroupController(mContext));
mAvailableMediaDeviceGroupController.
setBluetoothDeviceUpdater(mAvailableMediaBluetoothDeviceUpdater);
mAvailableMediaDeviceGroupController.mPreferenceGroup = mPreferenceGroup;
}
- @After
- public void tearDown() {
- ShadowBluetoothUtils.reset();
- }
-
@Test
public void onDeviceAdded_firstAdd_becomeVisibleAndPreferenceAdded() {
mAvailableMediaDeviceGroupController.onDeviceAdded(mPreference);
@@ -222,4 +232,21 @@
// Shouldn't crash
mAvailableMediaDeviceGroupController.onStop();
}
+
+ @Test
+ @Config(shadows = ShadowAlertDialogCompat.class)
+ public void onActiveDeviceChanged_hearingAidProfile_launchHearingAidPairingDialog() {
+ when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDeviceMode()).thenReturn(
+ HearingAidProfile.DeviceMode.MODE_BINAURAL);
+ when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
+ HearingAidProfile.DeviceSide.SIDE_LEFT);
+ mAvailableMediaDeviceGroupController.init(mDashboardFragment);
+
+ mAvailableMediaDeviceGroupController.onActiveDeviceChanged(mCachedBluetoothDevice,
+ BluetoothProfile.HEARING_AID);
+
+ final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog.isShowing()).isTrue();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java
index be778cb..9e0ce8c 100644
--- a/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java
@@ -26,15 +26,19 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
+import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.location.RecentLocationApps;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,7 +54,7 @@
import java.util.Set;
@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowUserManager.class})
+@Config(shadows = {ShadowDeviceConfig.class, ShadowUserManager.class})
public class RecentLocationRequestPreferenceControllerTest {
@Mock
private PreferenceScreen mScreen;
@@ -72,6 +76,11 @@
mController.mRecentLocationApps = spy(new RecentLocationApps(mContext));
}
+ @After
+ public void tearDown() {
+ ShadowDeviceConfig.reset();
+ }
+
@Test
public void updateState_whenAppListMoreThanThree_shouldDisplayTopThreeApps() {
final List<RecentLocationApps.Request> requests = createMockRequest(6);
@@ -84,6 +93,10 @@
@Test
public void updateState_whenAppListMoreThanThree_showSystem() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
+ SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED,
+ Boolean.toString(true),
+ true);
when(mController.mRecentLocationApps.getAppListSorted(false))
.thenReturn(createMockRequest(2));
when(mController.mRecentLocationApps.getAppListSorted(true))
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index d430232..518aee9 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -239,7 +239,7 @@
}
@Override
- public BluetoothFeatureProvider getBluetoothFeatureProvider(Context context) {
+ public BluetoothFeatureProvider getBluetoothFeatureProvider() {
return mBluetoothFeatureProvider;
}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiScanModeActivityTest.java b/tests/robotests/src/com/android/settings/wifi/WifiScanModeActivityTest.java
index 3e6ba00..1e3afdb 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiScanModeActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiScanModeActivityTest.java
@@ -16,16 +16,75 @@
package com.android.settings.wifi;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.text.TextUtils;
+
+import com.android.settings.testutils.shadow.ShadowUtils;
+import com.android.settingslib.wifi.WifiPermissionChecker;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowUtils.class})
public class WifiScanModeActivityTest {
+
+ static final String LAUNCHED_PACKAGE = "launched_package";
+ static final String APP_LABEL = "app_label";
+
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Mock
+ WifiPermissionChecker mWifiPermissionChecker;
+
+ WifiScanModeActivity mActivity;
+
+ @Before
+ public void setUp() {
+ mActivity = spy(Robolectric.setupActivity(WifiScanModeActivity.class));
+ mActivity.mWifiPermissionChecker = mWifiPermissionChecker;
+ }
+
+ @After
+ public void tearDown() {
+ ShadowUtils.reset();
+ }
+
@Test
public void launchActivity_noIntentAction_shouldNotFatalException() {
WifiScanModeActivity wifiScanModeActivity =
Robolectric.setupActivity(WifiScanModeActivity.class);
}
+
+ @Test
+ public void refreshAppLabel_noPackageName_shouldNotFatalException() {
+ when(mWifiPermissionChecker.getLaunchedPackage()).thenReturn(null);
+
+ mActivity.refreshAppLabel();
+
+ assertThat(TextUtils.isEmpty(mActivity.mApp)).isTrue();
+ }
+
+ @Test
+ public void refreshAppLabel_hasPackageName_shouldHasAppLabel() {
+ ShadowUtils.setApplicationLabel(LAUNCHED_PACKAGE, APP_LABEL);
+ when(mWifiPermissionChecker.getLaunchedPackage()).thenReturn(LAUNCHED_PACKAGE);
+
+ mActivity.refreshAppLabel();
+
+ assertThat(mActivity.mApp).isEqualTo(APP_LABEL);
+ }
}
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 74bddda..e2c5ca3 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSettingsForSubTest.java
@@ -55,6 +55,7 @@
import com.android.settings.network.ims.WifiCallingQueryImsState;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.widget.SettingsMainSwitchBar;
+import com.android.settings.widget.SettingsMainSwitchPreference;
import org.junit.Before;
import org.junit.Test;
@@ -72,6 +73,7 @@
public class WifiCallingSettingsForSubTest {
private static final int SUB_ID = 2;
+ private static final String SWITCH_BAR = "wifi_calling_switch_bar";
private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
private static final String PREFERENCE_NO_OPTIONS_DESC = "no_options_description";
@@ -100,6 +102,8 @@
@Mock
private View mView;
@Mock
+ private SettingsMainSwitchPreference mSwitchBarPreference;
+ @Mock
private LinkifyDescriptionPreference mDescriptionView;
@Mock
private ListWithEntrySummaryPreference mButtonWfcMode;
@@ -116,6 +120,7 @@
doReturn(mContext.getTheme()).when(mActivity).getTheme();
mFragment = spy(new TestFragment());
+ mFragment.setSwitchBar(mSwitchBarPreference);
doReturn(mActivity).when(mFragment).getActivity();
doReturn(mContext).when(mFragment).getContext();
doReturn(mock(Intent.class)).when(mActivity).getIntent();
@@ -125,10 +130,6 @@
final Bundle bundle = new Bundle();
when(mFragment.getArguments()).thenReturn(bundle);
doNothing().when(mFragment).addPreferencesFromResource(anyInt());
- 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);
- doReturn(mDescriptionView).when(mFragment).findPreference(PREFERENCE_NO_OPTIONS_DESC);
doNothing().when(mFragment).finish();
doReturn(mView).when(mFragment).getView();
@@ -344,6 +345,29 @@
}
protected class TestFragment extends WifiCallingSettingsForSub {
+ private SettingsMainSwitchPreference mSwitchPref;
+
+ protected void setSwitchBar(SettingsMainSwitchPreference switchPref) {
+ mSwitchPref = switchPref;
+ }
+
+ @Override
+ public <T extends Preference> T findPreference(CharSequence key) {
+ if (SWITCH_BAR.equals(key)) {
+ return (T) mSwitchPref;
+ }
+ if (BUTTON_WFC_MODE.equals(key)) {
+ return (T) mButtonWfcMode;
+ }
+ if (BUTTON_WFC_ROAMING_MODE.equals(key)) {
+ return (T) mButtonWfcRoamingMode;
+ }
+ if (PREFERENCE_NO_OPTIONS_DESC.equals(key)) {
+ return (T) mDescriptionView;
+ }
+ return (T) mock(ListWithEntrySummaryPreference.class);
+ }
+
@Override
protected Object getSystemService(final String name) {
switch (name) {
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 7c17c5f..ca0247f 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
@@ -84,7 +84,44 @@
}
@Test
+ public void startTether_wifiApIsActivated_doNothing() {
+ when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_ENABLED);
+
+ mController.startTether();
+
+ verify(mConnectivityManager, never()).startTethering(anyInt(), anyBoolean(), any(), any());
+ }
+
+ @Test
+ public void startTether_wifiApNotActivated_startTethering() {
+ when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_DISABLED);
+
+ mController.startTether();
+
+ verify(mConnectivityManager).startTethering(anyInt(), anyBoolean(), any(), any());
+ }
+
+ @Test
+ public void stopTether_wifiApIsActivated_stopTethering() {
+ when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_ENABLED);
+
+ mController.stopTether();
+
+ verify(mConnectivityManager).stopTethering(anyInt());
+ }
+
+ @Test
+ public void stopTether_wifiApNotActivated_doNothing() {
+ when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_DISABLED);
+
+ mController.stopTether();
+
+ verify(mConnectivityManager, never()).stopTethering(anyInt());
+ }
+
+ @Test
public void startTether_fail_resetSwitchBar() {
+ when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_DISABLED);
when(mDataSaverBackend.isDataSaverEnabled()).thenReturn(false);
mController.startTether();
@@ -130,6 +167,7 @@
@Test
public void onSwitchChanged_isNotChecked_stopTethering() {
+ when(mWifiManager.getWifiApState()).thenReturn(WIFI_AP_STATE_ENABLED);
when(mSwitch.isChecked()).thenReturn(false);
mController.onSwitchChanged(mSwitch, mSwitch.isChecked());
diff --git a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
index 3bcfcb4..8ebd2b5 100644
--- a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
@@ -364,7 +364,8 @@
mController.onResume();
mController.displayPreference(mPreferenceScreen);
- mController.onTelephonyDisplayInfoChanged(telephonyDisplayInfo);
+ mController.onTelephonyDisplayInfoChanged(sub.get(0).getSubscriptionId(),
+ telephonyDisplayInfo);
assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
}
@@ -388,7 +389,8 @@
mController.onResume();
mController.displayPreference(mPreferenceScreen);
- mController.onTelephonyDisplayInfoChanged(telephonyDisplayInfo);
+ mController.onTelephonyDisplayInfoChanged(sub.get(0).getSubscriptionId(),
+ telephonyDisplayInfo);
assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
}
@@ -414,7 +416,8 @@
mController.onResume();
mController.displayPreference(mPreferenceScreen);
- mController.onTelephonyDisplayInfoChanged(telephonyDisplayInfo);
+ mController.onTelephonyDisplayInfoChanged(sub.get(0).getSubscriptionId(),
+ telephonyDisplayInfo);
assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
}
diff --git a/tests/unit/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceControllerTest.java
index f7e3111..53ae1b9 100644
--- a/tests/unit/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceControllerTest.java
@@ -93,15 +93,18 @@
mPreference = new Preference(mContext);
mController = new OpenNetworkSelectPagePreferenceController(mContext,
- "open_network_select");
+ "open_network_select") {
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(mPreference);
+ }
+ };
mController.init(mLifecycle, SUB_ID);
}
@Test
public void updateState_modeAuto_disabled() {
- when(mTelephonyManager.getNetworkSelectionMode()).thenReturn(
- TelephonyManager.NETWORK_SELECTION_MODE_AUTO);
-
+ mController.onNetworkSelectModeUpdated(TelephonyManager.NETWORK_SELECTION_MODE_AUTO);
mController.updateState(mPreference);
assertThat(mPreference.isEnabled()).isFalse();
diff --git a/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java b/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java
index 1cfee0f..ae42c84 100644
--- a/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java
+++ b/tests/unit/src/com/android/settings/privacy/PrivacyDashboardActivityTest.java
@@ -44,54 +44,79 @@
@RunWith(AndroidJUnit4.class)
public class PrivacyDashboardActivityTest {
-
private static final String DEFAULT_FRAGMENT_CLASSNAME = "DefaultFragmentClassname";
-
@Mock
private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
private Settings.PrivacyDashboardActivity mActivity;
+ private static final String ACTION_PRIVACY_ADVANCED_SETTINGS =
+ "android.settings.PRIVACY_ADVANCED_SETTINGS";
@Before
- public void setUp() throws Exception {
+ public void setUp() {
MockitoAnnotations.initMocks(this);
-
SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper;
- final Intent intent = new Intent();
- intent.setAction(android.provider.Settings.ACTION_PRIVACY_SETTINGS);
- intent.setClass(InstrumentationRegistry.getInstrumentation().getTargetContext(),
- Settings.PrivacyDashboardActivity.class);
- intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, DEFAULT_FRAGMENT_CLASSNAME);
- InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- try {
- mActivity =
- spy((Settings.PrivacyDashboardActivity) InstrumentationRegistry
- .getInstrumentation().newActivity(
- getClass().getClassLoader(),
- Settings.PrivacyDashboardActivity.class.getName(),
- intent));
- } catch (Exception e) {
- throw new RuntimeException(e); // nothing to do
- }
- });
- doNothing().when(mActivity).startActivity(any(Intent.class));
}
@Test
- public void onCreate_whenSafetyCenterEnabled_redirectsToSafetyCenter() {
+ public void onCreate_whenSafetyCenterEnabled_redirectsToSafetyCenter() throws Exception {
+ startActivityUsingIntent(android.provider.Settings.ACTION_PRIVACY_SETTINGS);
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-
mActivity.handleSafetyCenterRedirection();
-
verify(mActivity).startActivity(intentCaptor.capture());
assertThat(intentCaptor.getValue().getAction()).isEqualTo(Intent.ACTION_SAFETY_CENTER);
}
@Test
- public void onCreate_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter() {
+ public void onCreateWithAdvancedIntent_whenSafetyCenterEnabled_doesntRedirectToSafetyCenter()
+ throws Exception {
+ startActivityUsingIntent(ACTION_PRIVACY_ADVANCED_SETTINGS);
+ when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ mActivity.handleSafetyCenterRedirection();
+ verify(mActivity, times(0)).startActivity(any());
+ }
+
+ @Test
+ public void onCreate_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter() throws Exception {
+ startActivityUsingIntent(android.provider.Settings.ACTION_PRIVACY_SETTINGS);
when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(false);
mActivity.handleSafetyCenterRedirection();
-
verify(mActivity, times(0)).startActivity(any());
}
+
+ @Test
+ public void onCreateWithAdvancedIntent_whenSafetyCenterDisabled_doesntRedirectToSafetyCenter()
+ throws Exception {
+ startActivityUsingIntent(ACTION_PRIVACY_ADVANCED_SETTINGS);
+ when(mSafetyCenterManagerWrapper.isEnabled(any(Context.class))).thenReturn(true);
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ mActivity.handleSafetyCenterRedirection();
+ verify(mActivity, times(0)).startActivity(any());
+ }
+
+ private void startActivityUsingIntent(String intentAction) throws Exception {
+ MockitoAnnotations.initMocks(this);
+ SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper;
+ final Intent intent = new Intent();
+ intent.setAction(intentAction);
+ intent.setClass(InstrumentationRegistry.getInstrumentation().getTargetContext(),
+ Settings.PrivacyDashboardActivity.class);
+ intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, DEFAULT_FRAGMENT_CLASSNAME);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ try {
+ Settings.PrivacyDashboardActivity activity =
+ (Settings.PrivacyDashboardActivity) InstrumentationRegistry
+ .getInstrumentation().newActivity(
+ getClass().getClassLoader(),
+ Settings.PrivacyDashboardActivity.class.getName(),
+ intent);
+ activity.setIntent(intent);
+ mActivity = spy(activity);
+ } catch (Exception e) {
+ throw new RuntimeException(e); // nothing to do
+ }
+ });
+ doNothing().when(mActivity).startActivity(any(Intent.class));
+ }
}
diff --git a/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java b/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java
index 8004d60..3ad1874 100644
--- a/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java
+++ b/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java
@@ -54,13 +54,13 @@
@RunWith(AndroidJUnit4.class)
public class SafetySourceBroadcastReceiverTest {
+ private static final String REFRESH_BROADCAST_ID = "REFRESH_BROADCAST_ID";
+
private Context mApplicationContext;
- @Mock
- private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
+ @Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
- @Mock
- private LockPatternUtils mLockPatternUtils;
+ @Mock private LockPatternUtils mLockPatternUtils;
@Before
public void setUp() {
@@ -78,17 +78,6 @@
}
@Test
- public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoIntentAction_doesNotSetData() {
- when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
- Intent intent = new Intent().putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, new String[]{});
-
- new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
-
- verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
- any(), any(), any(), any());
- }
-
- @Test
public void onReceive_onRefresh_whenSafetyCenterIsDisabled_doesNotSetData() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false);
Intent intent =
@@ -96,23 +85,43 @@
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
.putExtra(
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
- new String[]{ LockScreenSafetySource.SAFETY_SOURCE_ID });
+ new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
- verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
- any(), any(), any(), any());
+ verify(mSafetyCenterManagerWrapper, never())
+ .setSafetySourceData(any(), any(), any(), any());
+ }
+
+ @Test
+ public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoIntentAction_doesNotSetData() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
+ Intent intent =
+ new Intent()
+ .putExtra(
+ EXTRA_REFRESH_SAFETY_SOURCE_IDS,
+ new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
+
+ new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
+
+ verify(mSafetyCenterManagerWrapper, never())
+ .setSafetySourceData(any(), any(), any(), any());
}
@Test
public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNullSourceIds_doesNotSetData() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
- Intent intent = new Intent().setAction(ACTION_REFRESH_SAFETY_SOURCES);
+ Intent intent =
+ new Intent()
+ .setAction(ACTION_REFRESH_SAFETY_SOURCES)
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
- verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
- any(), any(), any(), any());
+ verify(mSafetyCenterManagerWrapper, never())
+ .setSafetySourceData(any(), any(), any(), any());
}
@Test
@@ -121,12 +130,29 @@
Intent intent =
new Intent()
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
- .putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, new String[]{});
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, new String[] {})
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
- verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
- any(), any(), any(), any());
+ verify(mSafetyCenterManagerWrapper, never())
+ .setSafetySourceData(any(), any(), any(), any());
+ }
+
+ @Test
+ public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoBroadcastId_doesNotSetData() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
+ Intent intent =
+ new Intent()
+ .setAction(ACTION_REFRESH_SAFETY_SOURCES)
+ .putExtra(
+ EXTRA_REFRESH_SAFETY_SOURCE_IDS,
+ new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID});
+
+ new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
+
+ verify(mSafetyCenterManagerWrapper, never())
+ .setSafetySourceData(any(), any(), any(), any());
}
@Test
@@ -137,38 +163,19 @@
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
.putExtra(
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
- new String[]{ LockScreenSafetySource.SAFETY_SOURCE_ID });
+ new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
ArgumentCaptor<SafetyEvent> captor = ArgumentCaptor.forClass(SafetyEvent.class);
verify(mSafetyCenterManagerWrapper, times(1))
.setSafetySourceData(any(), any(), any(), captor.capture());
- assertThat(captor.getValue()).isEqualTo(
- new SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED).build());
- }
-
- @Test
- public void onReceive_onRefreshWithBroadcastId_setsRefreshEventWithBroadcastId() {
- final String refreshBroadcastId = "REFRESH_BROADCAST_ID";
- when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
- Intent intent =
- new Intent()
- .setAction(ACTION_REFRESH_SAFETY_SOURCES)
- .putExtra(
- EXTRA_REFRESH_SAFETY_SOURCE_IDS,
- new String[]{ LockScreenSafetySource.SAFETY_SOURCE_ID })
- .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, refreshBroadcastId);
-
- new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
- ArgumentCaptor<SafetyEvent> captor = ArgumentCaptor.forClass(SafetyEvent.class);
- verify(mSafetyCenterManagerWrapper, times(1))
- .setSafetySourceData(any(), any(), any(), captor.capture());
-
- assertThat(captor.getValue().getRefreshBroadcastId()).isEqualTo(refreshBroadcastId);
- assertThat(captor.getValue()).isEqualTo(
- new SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
- .setRefreshBroadcastId(refreshBroadcastId).build());
+ assertThat(captor.getValue())
+ .isEqualTo(
+ new SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
+ .build());
}
@Test
@@ -179,7 +186,8 @@
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
.putExtra(
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
- new String[]{ LockScreenSafetySource.SAFETY_SOURCE_ID });
+ new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
@@ -197,7 +205,8 @@
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
.putExtra(
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
- new String[]{ BiometricsSafetySource.SAFETY_SOURCE_ID });
+ new String[] {BiometricsSafetySource.SAFETY_SOURCE_ID})
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
index e9764cb..717de79 100644
--- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -225,7 +225,7 @@
}
@Override
- public BluetoothFeatureProvider getBluetoothFeatureProvider(Context context) {
+ public BluetoothFeatureProvider getBluetoothFeatureProvider() {
return mBluetoothFeatureProvider;
}