Merge "Accessibility settings interaction controls category restructure, add tap assistance fragment for related accessibility services."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c946122..2eaebb1 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -174,7 +174,8 @@
</intent-filter>
</receiver>
- <activity android:name=".SubSettings"/>
+ <activity android:name=".SubSettings"
+ android:theme="@style/Theme.SubSettings" />
<activity android:name=".Settings$CreateShortcutActivity"
android:exported="true"
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 3ebe9b1..768929b 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -1033,11 +1033,27 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+ errorLine1=" <color name="homepage_wallpaper_background">#E51AD1</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="102"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="HardCodedColor"
+ severity="Error"
+ message="Avoid using hardcoded color"
+ category="Correctness"
+ priority="4"
+ summary="Using hardcoded color"
+ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" <color name="contextual_card_stroke_color">#1f000000</color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="103"
+ line="104"
column="5"/>
</issue>
@@ -1053,7 +1069,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="109"
+ line="110"
column="5"/>
</issue>
@@ -1069,7 +1085,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="112"
+ line="113"
column="5"/>
</issue>
@@ -1085,7 +1101,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="113"
+ line="114"
column="5"/>
</issue>
@@ -1101,7 +1117,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="114"
+ line="115"
column="5"/>
</issue>
@@ -1117,7 +1133,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="115"
+ line="116"
column="5"/>
</issue>
@@ -1133,7 +1149,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="116"
+ line="117"
column="5"/>
</issue>
@@ -1149,7 +1165,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="117"
+ line="118"
column="5"/>
</issue>
@@ -1165,7 +1181,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="120"
+ line="121"
column="5"/>
</issue>
@@ -1181,7 +1197,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="121"
+ line="122"
column="5"/>
</issue>
@@ -1197,7 +1213,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="122"
+ line="123"
column="5"/>
</issue>
@@ -1213,7 +1229,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="123"
+ line="124"
column="5"/>
</issue>
@@ -1229,7 +1245,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="124"
+ line="125"
column="5"/>
</issue>
@@ -1245,7 +1261,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="127"
+ line="128"
column="5"/>
</issue>
@@ -1261,7 +1277,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="128"
+ line="129"
column="5"/>
</issue>
@@ -1277,7 +1293,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="129"
+ line="130"
column="5"/>
</issue>
@@ -1293,7 +1309,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="130"
+ line="131"
column="5"/>
</issue>
@@ -1309,7 +1325,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="131"
+ line="132"
column="5"/>
</issue>
@@ -1325,7 +1341,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="132"
+ line="133"
column="5"/>
</issue>
@@ -1341,7 +1357,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="139"
+ line="140"
column="5"/>
</issue>
@@ -1357,7 +1373,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="140"
+ line="141"
column="5"/>
</issue>
@@ -1373,7 +1389,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="141"
+ line="142"
column="5"/>
</issue>
@@ -1389,7 +1405,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="150"
+ line="151"
column="5"/>
</issue>
@@ -1405,7 +1421,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="152"
+ line="153"
column="5"/>
</issue>
@@ -1421,7 +1437,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="156"
+ line="157"
column="5"/>
</issue>
@@ -1437,7 +1453,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="157"
+ line="158"
column="5"/>
</issue>
@@ -1453,7 +1469,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="158"
+ line="159"
column="5"/>
</issue>
@@ -1469,7 +1485,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="159"
+ line="160"
column="5"/>
</issue>
@@ -1485,7 +1501,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="160"
+ line="161"
column="5"/>
</issue>
@@ -1501,7 +1517,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="161"
+ line="162"
column="5"/>
</issue>
@@ -1517,7 +1533,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="162"
+ line="163"
column="5"/>
</issue>
@@ -1533,7 +1549,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="163"
+ line="164"
column="5"/>
</issue>
@@ -1549,7 +1565,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="166"
+ line="167"
column="5"/>
</issue>
@@ -1565,7 +1581,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="167"
+ line="168"
column="5"/>
</issue>
@@ -1581,7 +1597,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="168"
+ line="169"
column="5"/>
</issue>
@@ -1597,7 +1613,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="169"
+ line="170"
column="5"/>
</issue>
@@ -1613,7 +1629,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="170"
+ line="171"
column="5"/>
</issue>
@@ -1629,7 +1645,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="171"
+ line="172"
column="5"/>
</issue>
@@ -1645,7 +1661,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="172"
+ line="173"
column="5"/>
</issue>
@@ -1661,7 +1677,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="173"
+ line="174"
column="5"/>
</issue>
@@ -1677,7 +1693,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="176"
+ line="177"
column="5"/>
</issue>
@@ -1693,7 +1709,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="177"
+ line="178"
column="5"/>
</issue>
@@ -1709,7 +1725,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="178"
+ line="179"
column="5"/>
</issue>
@@ -1725,7 +1741,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="179"
+ line="180"
column="5"/>
</issue>
@@ -1741,7 +1757,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="180"
+ line="181"
column="5"/>
</issue>
@@ -1757,7 +1773,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="181"
+ line="182"
column="5"/>
</issue>
@@ -1773,7 +1789,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="184"
+ line="185"
column="5"/>
</issue>
@@ -1789,7 +1805,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="185"
+ line="186"
column="5"/>
</issue>
@@ -1805,7 +1821,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="186"
+ line="187"
column="5"/>
</issue>
@@ -1821,7 +1837,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="187"
+ line="188"
column="5"/>
</issue>
@@ -1837,7 +1853,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="188"
+ line="189"
column="5"/>
</issue>
@@ -1853,7 +1869,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="189"
+ line="190"
column="5"/>
</issue>
@@ -2569,6 +2585,22 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+ errorLine1=" android:color="@color/homepage_wallpaper_background" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/drawable/ic_homepage_wallpaper.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="HardCodedColor"
+ severity="Error"
+ message="Avoid using hardcoded color"
+ category="Correctness"
+ priority="4"
+ summary="Using hardcoded color"
+ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color="@color/notification_block_color"/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -3181,7 +3213,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/strings.xml"
- line="6537"
+ line="6533"
column="36"/>
</issue>
diff --git a/res/drawable/ic_homepage_wallpaper.xml b/res/drawable/ic_homepage_wallpaper.xml
new file mode 100644
index 0000000..0f91465
--- /dev/null
+++ b/res/drawable/ic_homepage_wallpaper.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item>
+ <com.android.settingslib.widget.AdaptiveIconShapeDrawable
+ android:width="@dimen/dashboard_tile_image_size"
+ android:height="@dimen/dashboard_tile_image_size"
+ android:color="@color/homepage_wallpaper_background" />
+ </item>
+
+ <item
+ android:width="@dimen/dashboard_tile_foreground_image_size"
+ android:height="@dimen/dashboard_tile_foreground_image_size"
+ android:start="@dimen/dashboard_tile_foreground_image_inset"
+ android:top="@dimen/dashboard_tile_foreground_image_inset"
+ android:drawable="@drawable/ic_settings_wallpaper_white" />
+</layer-list>
diff --git a/res/drawable/ic_settings_wallpaper_white.xml b/res/drawable/ic_settings_wallpaper_white.xml
new file mode 100644
index 0000000..8591fb5
--- /dev/null
+++ b/res/drawable/ic_settings_wallpaper_white.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2021 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="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="?android:attr/colorPrimary"
+ android:fillType="evenOdd"
+ android:pathData="M11,5H5V11H3V5C3,3.9 3.9,3 5,3H11V5ZM11.14,15.29L9,12.71L6,16.57H18L14.14,11.42L11.14,15.29ZM19,13V19H13V21H19C20.1,21 21,20.1 21,19V13H19ZM5,13V19H11V21H5C3.9,21 3,20.1 3,19V13H5ZM19,5V11H21V5C21,3.9 20.1,3 19,3H13V5H19ZM17,8C17,8.55 16.55,9 16,9C15.45,9 15,8.55 15,8C15,7.45 15.45,7 16,7C16.55,7 17,7.45 17,8Z"/>
+</vector>
diff --git a/res/layout-sw300dp-land/font_size_activity.xml b/res/layout-sw300dp-land/font_size_activity.xml
index 6664704..7703eb2 100644
--- a/res/layout-sw300dp-land/font_size_activity.xml
+++ b/res/layout-sw300dp-land/font_size_activity.xml
@@ -36,7 +36,7 @@
android:padding="6dp" />
</LinearLayout>
- <ScrollView
+ <androidx.core.widget.NestedScrollView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
@@ -104,5 +104,5 @@
android:layout_marginBottom="16dp"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" />
</LinearLayout>
- </ScrollView>
+ </androidx.core.widget.NestedScrollView>
</LinearLayout>
diff --git a/res/layout-sw300dp-land/screen_zoom_activity.xml b/res/layout-sw300dp-land/screen_zoom_activity.xml
index 0f1c000..1cdb5b4 100644
--- a/res/layout-sw300dp-land/screen_zoom_activity.xml
+++ b/res/layout-sw300dp-land/screen_zoom_activity.xml
@@ -38,7 +38,7 @@
android:padding="6dp" />
</LinearLayout>
- <ScrollView
+ <androidx.core.widget.NestedScrollView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
@@ -106,5 +106,5 @@
android:layout_marginBottom="16dp"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" />
</LinearLayout>
- </ScrollView>
+ </androidx.core.widget.NestedScrollView>
</LinearLayout>
diff --git a/res/layout/font_size_activity.xml b/res/layout/font_size_activity.xml
index 32de37d..c3b26ae 100644
--- a/res/layout/font_size_activity.xml
+++ b/res/layout/font_size_activity.xml
@@ -14,17 +14,18 @@
limitations under the License.
-->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fillViewport="true">
+<androidx.core.widget.NestedScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="wrap_content" >
+ android:layout_height="wrap_content">
- <include layout="@layout/preview_seek_bar_view_pager" />
+ <include layout="@layout/preview_seek_bar_view_pager"/>
<LinearLayout
android:orientation="vertical"
@@ -40,7 +41,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
- android:padding="6dp" />
+ android:padding="6dp"/>
<TextView
android:id="@+id/current_label"
@@ -49,7 +50,7 @@
android:layout_gravity="center_horizontal"
android:padding="6dp"
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.TextView"
- android:elevation="2dp" />
+ android:elevation="2dp"/>
<LinearLayout
android:layout_width="match_parent"
@@ -68,7 +69,7 @@
android:tintMode="src_in"
android:scaleType="center"
android:focusable="true"
- android:contentDescription="@string/font_size_make_smaller_desc" />
+ android:contentDescription="@string/font_size_make_smaller_desc"/>
<com.android.settings.widget.LabeledSeekBar
android:id="@+id/seek_bar"
@@ -87,7 +88,7 @@
android:tintMode="src_in"
android:scaleType="center"
android:focusable="true"
- android:contentDescription="@string/font_size_make_larger_desc" />
+ android:contentDescription="@string/font_size_make_larger_desc"/>
</LinearLayout>
<TextView
@@ -95,7 +96,7 @@
android:layout_height="wrap_content"
android:text="@string/font_size_summary"
android:layout_marginBottom="16dp"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" />
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"/>
</LinearLayout>
</LinearLayout>
-</ScrollView>
+</androidx.core.widget.NestedScrollView>
diff --git a/res/layout/font_size_preview.xml b/res/layout/font_size_preview.xml
index 669ece0..2b1773b 100644
--- a/res/layout/font_size_preview.xml
+++ b/res/layout/font_size_preview.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.core.widget.NestedScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
@@ -57,4 +58,4 @@
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"/>
</LinearLayout>
</view>
-</ScrollView>
+</androidx.core.widget.NestedScrollView>
diff --git a/res/layout/preview_seek_bar_view_pager.xml b/res/layout/preview_seek_bar_view_pager.xml
index 12f2611..6ddff13 100644
--- a/res/layout/preview_seek_bar_view_pager.xml
+++ b/res/layout/preview_seek_bar_view_pager.xml
@@ -25,7 +25,7 @@
<androidx.viewpager.widget.ViewPager
android:id="@+id/preview_pager"
android:layout_width="match_parent"
- android:layout_height="100dp"
+ android:layout_height="400dp"
android:layout_weight="1"
android:background="?android:attr/colorBackgroundFloating"
android:contentDescription="@string/preview_pager_content_description" />
diff --git a/res/layout/screen_zoom_activity.xml b/res/layout/screen_zoom_activity.xml
index 4cfa7b6..00831fb 100644
--- a/res/layout/screen_zoom_activity.xml
+++ b/res/layout/screen_zoom_activity.xml
@@ -14,17 +14,18 @@
limitations under the License.
-->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fillViewport="true">
+<androidx.core.widget.NestedScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="wrap_content" >
+ android:layout_height="wrap_content">
- <include layout="@layout/preview_seek_bar_view_pager" />
+ <include layout="@layout/preview_seek_bar_view_pager"/>
<LinearLayout
android:orientation="vertical"
@@ -40,7 +41,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
- android:padding="6dp" />
+ android:padding="6dp"/>
<TextView
android:id="@+id/current_label"
@@ -49,7 +50,7 @@
android:layout_gravity="center_horizontal"
android:padding="6dp"
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.TextView"
- android:elevation="2dp" />
+ android:elevation="2dp"/>
<LinearLayout
android:layout_width="match_parent"
@@ -66,7 +67,7 @@
android:tintMode="src_in"
android:scaleType="center"
android:focusable="true"
- android:contentDescription="@string/screen_zoom_make_smaller_desc" />
+ android:contentDescription="@string/screen_zoom_make_smaller_desc"/>
<com.android.settings.widget.LabeledSeekBar
android:id="@+id/seek_bar"
@@ -85,7 +86,7 @@
android:tintMode="src_in"
android:scaleType="center"
android:focusable="true"
- android:contentDescription="@string/screen_zoom_make_larger_desc" />
+ android:contentDescription="@string/screen_zoom_make_larger_desc"/>
</LinearLayout>
<TextView
@@ -93,7 +94,7 @@
android:layout_height="wrap_content"
android:text="@string/screen_zoom_summary"
android:layout_marginBottom="16dp"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" />
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"/>
</LinearLayout>
</LinearLayout>
-</ScrollView>
+</androidx.core.widget.NestedScrollView>
diff --git a/res/layout/screen_zoom_preview_1.xml b/res/layout/screen_zoom_preview_1.xml
index 65d27ee..9290df9 100644
--- a/res/layout/screen_zoom_preview_1.xml
+++ b/res/layout/screen_zoom_preview_1.xml
@@ -13,7 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.core.widget.NestedScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -75,4 +76,4 @@
app:iconBackgroundColor="@color/message_icon_background_incoming" />
</LinearLayout>
</view>
-</ScrollView>
+</androidx.core.widget.NestedScrollView>
diff --git a/res/layout/screen_zoom_preview_settings.xml b/res/layout/screen_zoom_preview_settings.xml
index 3401fcf..de16392 100644
--- a/res/layout/screen_zoom_preview_settings.xml
+++ b/res/layout/screen_zoom_preview_settings.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.core.widget.NestedScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
@@ -223,4 +224,4 @@
</LinearLayout>
</LinearLayout>
</view>
-</ScrollView>
+</androidx.core.widget.NestedScrollView>
diff --git a/res/layout/settings_collapsing_base_layout.xml b/res/layout/settings_collapsing_base_layout.xml
new file mode 100644
index 0000000..5858fc1
--- /dev/null
+++ b/res/layout/settings_collapsing_base_layout.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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.
+-->
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/content_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.google.android.material.appbar.AppBarLayout
+ android:id="@+id/appbar_layout"
+ android:layout_width="match_parent"
+ android:layout_height="160dp"
+ android:theme="@style/Theme.CollapsingToolbar.Settings">
+
+ <com.google.android.material.appbar.CollapsingToolbarLayout
+ android:id="@+id/collapsing_toolbar"
+ android:background="?android:attr/colorPrimary"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:maxLines="3"
+ app:contentScrim="?android:attr/colorPrimary"
+ app:collapsedTitleTextAppearance="@style/ToolbarText.Collapsed"
+ app:statusBarScrim="?android:attr/colorPrimary"
+ app:layout_scrollFlags="scroll|exitUntilCollapsed"
+ app:toolbarId="@id/tool_bar">
+
+ <androidx.appcompat.widget.Toolbar
+ android:id="@+id/tool_bar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ app:layout_collapseMode="pin"
+ app:contentInsetStart="68dp"/>
+
+ <Toolbar
+ android:id="@+id/action_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:layout_collapseMode="pin"
+ android:theme="?android:attr/actionBarTheme"/>
+
+ </com.google.android.material.appbar.CollapsingToolbarLayout>
+ </com.google.android.material.appbar.AppBarLayout>
+
+ <FrameLayout
+ android:id="@+id/content_frame"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/res/values-night/themes.xml b/res/values-night/themes.xml
index c5f67fe..a4f495a 100644
--- a/res/values-night/themes.xml
+++ b/res/values-night/themes.xml
@@ -44,4 +44,10 @@
<style name="Theme.TabTheme" parent="@style/Theme.MaterialComponents.DayNight">
<item name="colorPrimary">@*android:color/edge_effect_device_default_dark</item>
</style>
+
+ <style name="Theme.CollapsingToolbar.Settings"
+ parent="@style/Theme.MaterialComponents.DayNight">
+ <item name="colorPrimary">@*android:color/primary_dark_device_default_settings</item>
+ <item name="colorAccent">@*android:color/accent_device_default_dark</item>
+ </style>
</resources>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 3528f9f..183dd1e 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -223,6 +223,10 @@
<!-- Security types for wireless tether -->
<string-array name="wifi_tether_security">
<!-- Do not translate. -->
+ <item>@string/wifi_security_sae</item>
+ <!-- Do not translate. -->
+ <item>@string/wifi_security_psk_sae</item>
+ <!-- Do not translate. -->
<item>@string/wifi_security_wpa2</item>
<!-- Do not translate. -->
<item>@string/wifi_security_none</item>
@@ -231,6 +235,10 @@
<!-- Values for security type for wireless tether -->
<string-array name="wifi_tether_security_values" translatable="false">
<!-- Do not translate. -->
+ <item>3</item>
+ <!-- Do not translate. -->
+ <item>2</item>
+ <!-- Do not translate. -->
<item>1</item>
<!-- Do not translate. -->
<item>0</item>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 2ce3949..c858cb3 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -99,6 +99,7 @@
<color name="homepage_location_background">#2EC7DC</color>
<color name="homepage_about_background">#6F86DA</color>
<color name="homepage_privacy_background">#5E97F6</color>
+ <color name="homepage_wallpaper_background">#E51AD1</color>
<color name="contextual_card_stroke_color">#1f000000</color>
<color name="contextual_card_dismissal_background">@*android:color/material_grey_100</color>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index ce6b095..4ab1e6c 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -874,4 +874,17 @@
<item name="android:textSize">16sp</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
+
+ <style name="ToolbarText.Collapsed"
+ parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
+ </style>
+
+ <style name="ToolbarText"
+ parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title" >
+ <item name="android:textSize">32sp</item>
+ </style>
+
+ <style name="ToolbarText.MoreThanTwoLines">
+ <item name="android:textSize">24sp</item>
+ </style>
</resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 01ea103..fc69246 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -72,7 +72,7 @@
<item name="android:windowNoTitle">true</item>
</style>
- <style name="Theme.SubSettings.Base" parent="Theme.Settings">
+ <style name="Theme.SubSettings.Base" parent="Theme.Settings.NoActionBar">
<!-- Redefine the ActionBar style for contentInsetStart -->
<item name="android:actionBarStyle">@style/Widget.ActionBar.SubSettings</item>
@@ -276,4 +276,10 @@
<style name="Theme.TabTheme" parent="@style/Theme.MaterialComponents.DayNight">
<item name="colorPrimary">@*android:color/edge_effect_device_default_light</item>
</style>
+
+ <style name="Theme.CollapsingToolbar.Settings"
+ parent="@style/Theme.MaterialComponents.DayNight">
+ <item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
+ <item name="colorAccent">@*android:color/accent_device_default_light</item>
+ </style>
</resources>
diff --git a/res/xml/emergency_settings.xml b/res/xml/emergency_settings.xml
index 41b503e..31c209b 100644
--- a/res/xml/emergency_settings.xml
+++ b/res/xml/emergency_settings.xml
@@ -23,15 +23,18 @@
android:key="emergency_info"
android:title="@string/emergency_info_title"
android:summary="@string/summary_placeholder"
+ android:order="0"
settings:controller="com.android.settings.accounts.EmergencyInfoPreferenceController"/>
<Preference
android:key="gesture_emergency_summary"
android:title="@string/emergency_gesture_screen_title"
+ android:order="100"
android:fragment="com.android.settings.gestures.EmergencyGestureSettings"
settings:controller="com.android.settings.gestures.EmergencyGestureEntrypointPreferenceController" />
<com.android.settingslib.RestrictedPreference
android:key="app_and_notif_cell_broadcast_settings"
android:title="@string/cell_broadcast_settings"
+ android:order="200"
settings:useAdminDisabledSummary="true">
<intent
android:action="android.intent.action.MAIN"
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index 32dad20..970ad21 100644
--- a/res/xml/gestures.xml
+++ b/res/xml/gestures.xml
@@ -21,12 +21,6 @@
android:title="@string/gesture_preference_title">
<Preference
- android:key="gesture_emergency_summary"
- android:title="@string/emergency_gesture_screen_title"
- android:fragment="com.android.settings.gestures.EmergencyGestureSettings"
- settings:controller="com.android.settings.gestures.EmergencyGestureEntrypointPreferenceController" />
-
- <Preference
android:key="gesture_assist_input_summary"
android:title="@string/assist_gesture_title"
android:fragment="com.android.settings.gestures.AssistGestureSettings"
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index eb9ceb4..5077f77 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -56,13 +56,6 @@
settings:controller="com.android.settings.deviceinfo.PhoneNumberPreferenceController"
settings:enableCopying="true"/>
- <Preference
- android:key="emergency_info"
- android:order="14"
- android:title="@string/emergency_info_title"
- android:summary="@string/summary_placeholder"
- settings:controller="com.android.settings.accounts.EmergencyInfoPreferenceController"/>
-
<!-- Legal information -->
<Preference
android:key="legal_container"
diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml
index 3c65f7b..78dfe9b 100644
--- a/res/xml/top_level_settings.xml
+++ b/res/xml/top_level_settings.xml
@@ -125,13 +125,12 @@
android:fragment="com.android.settings.accessibility.AccessibilitySettings"
settings:controller="com.android.settings.accessibility.TopLevelAccessibilityPreferenceController"/>
- <!-- TODO(b/175158310): Enable this tile when the setting content is more flushed out-->
- <!-- <Preference-->
- <!-- android:key="top_level_emergency"-->
- <!-- android:title="@string/emergency_settings_preference_title"-->
- <!-- android:icon="@drawable/ic_homepage_emergency"-->
- <!-- android:order="-10"-->
- <!-- android:fragment="com.android.settings.emergency.EmergencyDashboardFragment"/>-->
+ <Preference
+ android:key="top_level_emergency"
+ android:title="@string/emergency_settings_preference_title"
+ android:icon="@drawable/ic_homepage_emergency"
+ android:order="-10"
+ android:fragment="com.android.settings.emergency.EmergencyDashboardFragment"/>
<Preference
android:key="top_level_system"
diff --git a/res/xml/top_level_settings_grouped.xml b/res/xml/top_level_settings_grouped.xml
index 1ae6131..1a82e2d 100644
--- a/res/xml/top_level_settings_grouped.xml
+++ b/res/xml/top_level_settings_grouped.xml
@@ -93,7 +93,7 @@
settings:controller="com.android.settings.display.TopLevelDisplayPreferenceController"/>
<com.android.settingslib.RestrictedTopLevelPreference
- android:icon="@drawable/ic_homepage_display"
+ android:icon="@drawable/ic_homepage_wallpaper"
android:key="top_level_wallpaper"
android:order="-60"
android:title="@string/wallpaper_settings_title"
@@ -134,13 +134,14 @@
android:order="-20"
android:title="@string/security_settings_title"
settings:controller="com.android.settings.security.TopLevelSecurityEntryPreferenceController"/>
- <!-- TODO(b/175158310): Enable this tile when the setting content is more flushed out-->
- <!-- <Preference-->
- <!-- android:key="top_level_emergency"-->
- <!-- android:title="@string/emergency_settings_preference_title"-->
- <!-- android:icon="@drawable/ic_homepage_emergency"-->
- <!-- android:order="-10"-->
- <!-- android:fragment="com.android.settings.emergency.EmergencyDashboardFragment"/>-->
+
+ <Preference
+ android:key="top_level_emergency"
+ android:title="@string/emergency_settings_preference_title"
+ android:icon="@drawable/ic_homepage_emergency"
+ android:order="-10"
+ android:fragment="com.android.settings.emergency.EmergencyDashboardFragment"/>
+
</PreferenceCategory>
<PreferenceCategory
diff --git a/src/com/android/settings/AllInOneTetherSettings.java b/src/com/android/settings/AllInOneTetherSettings.java
index 82e3206..5442ed7 100644
--- a/src/com/android/settings/AllInOneTetherSettings.java
+++ b/src/com/android/settings/AllInOneTetherSettings.java
@@ -355,7 +355,7 @@
@Override
public void onTetherConfigUpdated(AbstractPreferenceController controller) {
final SoftApConfiguration config = buildNewConfig();
- mPasswordPreferenceController.updateVisibility(config.getSecurityType());
+ mPasswordPreferenceController.setSecurityType(config.getSecurityType());
mWifiManager.setSoftApConfiguration(config);
if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 1c2952a..7f214f6 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -288,7 +288,9 @@
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(!isInSetupWizard);
actionBar.setHomeButtonEnabled(!isInSetupWizard);
- actionBar.setDisplayShowTitleEnabled(true);
+ // TODO(b/176882938): Enable title after material component updated
+ // If CollapsingToolbarLayout is applied, the old action bar won't show title.
+ actionBar.setDisplayShowTitleEnabled(mCollapsingToolbarLayout == null);
}
mSwitchBar = findViewById(R.id.switch_bar);
if (mSwitchBar != null) {
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 659ada4..2c628f6 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -26,6 +26,7 @@
import android.os.Bundle;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -42,6 +43,7 @@
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import com.android.settings.core.FeatureFlags;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.search.actionbar.SearchMenuController;
@@ -126,8 +128,11 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- SearchMenuController.init(this /* host */);
- HelpMenuController.init(this /* host */);
+ // TODO(b/176883483): Remove both search and help menu if this feature rolled out
+ if (!FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.SILKY_HOME)) {
+ SearchMenuController.init(this /* host */);
+ HelpMenuController.init(this /* host */);
+ }
if (icicle != null) {
mPreferenceHighlighted = icicle.getBoolean(SAVE_HIGHLIGHTED_KEY);
diff --git a/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java b/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java
index 5a1883b..5df30c2 100644
--- a/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java
+++ b/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBase.java
@@ -14,7 +14,9 @@
package com.android.settings.applications.appinfo;
+import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
+import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.os.UserManager;
@@ -56,12 +58,14 @@
mRoleManager = context.getSystemService(RoleManager.class);
+ final RoleControllerManager roleControllerManager =
+ mContext.getSystemService(RoleControllerManager.class);
final Executor executor = mContext.getMainExecutor();
- mRoleManager.isRoleVisible(mRoleName, executor, visible -> {
+ roleControllerManager.isRoleVisible(mRoleName, executor, visible -> {
mRoleVisible = visible;
refreshAvailability();
});
- mRoleManager.isApplicationVisibleForRole(mRoleName, mPackageName, executor,
+ roleControllerManager.isApplicationVisibleForRole(mRoleName, mPackageName, executor,
visible -> {
mAppVisible = visible;
refreshAvailability();
diff --git a/src/com/android/settings/core/SettingsBaseActivity.java b/src/com/android/settings/core/SettingsBaseActivity.java
index d160dc5..4704702 100644
--- a/src/com/android/settings/core/SettingsBaseActivity.java
+++ b/src/com/android/settings/core/SettingsBaseActivity.java
@@ -29,6 +29,7 @@
import android.os.Bundle;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -43,8 +44,11 @@
import com.android.settings.dashboard.CategoryManager;
import com.android.settingslib.drawer.Tile;
+import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.setupcompat.util.WizardManagerHelper;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -55,6 +59,7 @@
protected static final boolean DEBUG_TIMING = false;
private static final String TAG = "SettingsBaseActivity";
private static final String DATA_SCHEME_PKG = "package";
+ private static final int TOOLBAR_MAX_LINE_NUMBER = 2;
// Serves as a temporary list of tiles to ignore until we heard back from the PM that they
// are disabled.
@@ -62,6 +67,8 @@
private final PackageReceiver mPackageReceiver = new PackageReceiver();
private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
+
+ protected CollapsingToolbarLayout mCollapsingToolbarLayout;
private int mCategoriesUpdateTaskCount;
@Override
@@ -79,21 +86,30 @@
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
// Apply SetupWizard light theme during setup flow. This is for SubSettings pages.
- if (WizardManagerHelper.isAnySetupWizard(getIntent()) && this instanceof SubSettings) {
+ final boolean isAnySetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
+ if (isAnySetupWizard && this instanceof SubSettings) {
setTheme(R.style.LightTheme_SubSettings_SetupWizard);
}
- super.setContentView(R.layout.settings_base_layout);
+ if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SILKY_HOME)
+ && isToolbarEnabled() && !isAnySetupWizard) {
+ super.setContentView(R.layout.settings_collapsing_base_layout);
+ mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
+ } else {
+ super.setContentView(R.layout.settings_base_layout);
+ }
+
+ // This is to hide the toolbar from those pages which don't need a toolbar originally.
final Toolbar toolbar = findViewById(R.id.action_bar);
- if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
+ if (!isToolbarEnabled() || isAnySetupWizard) {
toolbar.setVisibility(View.GONE);
return;
}
setActionBar(toolbar);
+ initCollapsingToolbar();
if (DEBUG_TIMING) {
- Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
- + " ms");
+ Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) + " ms");
}
}
@@ -151,6 +167,70 @@
((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
}
+ @Override
+ public void setTitle(CharSequence title) {
+ if (mCollapsingToolbarLayout != null) {
+ mCollapsingToolbarLayout.setTitle(title);
+ }
+ super.setTitle(title);
+ }
+
+ @Override
+ public void setTitle(int titleId) {
+ if (mCollapsingToolbarLayout != null) {
+ mCollapsingToolbarLayout.setTitle(getText(titleId));
+ }
+ super.setTitle(titleId);
+ }
+
+ /**
+ * SubSetting page should show a toolbar by default. If the page wouldn't show a toolbar,
+ * override this method and return false value.
+ * @return ture by default
+ */
+ protected boolean isToolbarEnabled() {
+ return true;
+ }
+
+ private void initCollapsingToolbar() {
+ if (mCollapsingToolbarLayout == null) {
+ return;
+ }
+ mCollapsingToolbarLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ v.removeOnLayoutChangeListener(this);
+ final int count = getLineCount();
+ if (count > TOOLBAR_MAX_LINE_NUMBER) {
+ mCollapsingToolbarLayout
+ .setExpandedTitleTextAppearance(R.style.ToolbarText_MoreThanTwoLines);
+ } else {
+ mCollapsingToolbarLayout.setExpandedTitleTextAppearance(R.style.ToolbarText);
+ }
+ }
+ });
+ }
+
+ private int getLineCount() {
+ try {
+ final Class<?> toolbarClazz = mCollapsingToolbarLayout.getClass();
+ final Field textHelperField = toolbarClazz.getDeclaredField("collapsingTextHelper");
+ textHelperField.setAccessible(true);
+ final Object textHelperObj = textHelperField.get(mCollapsingToolbarLayout);
+
+ final Field layoutField = textHelperObj.getClass().getDeclaredField("textLayout");
+ layoutField.setAccessible(true);
+ final Object layoutObj = layoutField.get(textHelperObj);
+
+ final Method method = layoutObj.getClass().getDeclaredMethod("getLineCount");
+ return (int) method.invoke(layoutObj);
+ } catch (Exception e) {
+ return 0;
+ }
+ }
+
+
private void onCategoriesChanged(Set<String> categories) {
final int N = mCategoryListeners.size();
for (int i = 0; i < N; i++) {
diff --git a/src/com/android/settings/emergency/EmergencyDashboardFragment.java b/src/com/android/settings/emergency/EmergencyDashboardFragment.java
index c786767..1983430 100644
--- a/src/com/android/settings/emergency/EmergencyDashboardFragment.java
+++ b/src/com/android/settings/emergency/EmergencyDashboardFragment.java
@@ -44,7 +44,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.EMERGENCY_SOS_GESTURE_SETTINGS;
+ return SettingsEnums.EMERGENCY_SETTINGS;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
diff --git a/src/com/android/settings/homepage/contextualcards/slices/FaceSetupSlice.java b/src/com/android/settings/homepage/contextualcards/slices/FaceSetupSlice.java
index 2e34824..0ad241e 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/FaceSetupSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/FaceSetupSlice.java
@@ -143,7 +143,7 @@
private static RowBuilder buildRowBuilder(CharSequence title, CharSequence subTitle,
IconCompat icon, Context context, Intent intent) {
final SliceAction primarySliceAction = SliceAction.createDeeplink(
- PendingIntent.getActivity(context, 0, intent, 0), icon, ListBuilder.ICON_IMAGE,
+ PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED), icon, ListBuilder.ICON_IMAGE,
title);
return new RowBuilder()
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
diff --git a/src/com/android/settings/inputmethod/UserDictionarySettings.java b/src/com/android/settings/inputmethod/UserDictionarySettings.java
index 67420a2..5e3e749 100644
--- a/src/com/android/settings/inputmethod/UserDictionarySettings.java
+++ b/src/com/android/settings/inputmethod/UserDictionarySettings.java
@@ -26,6 +26,7 @@
import android.os.Bundle;
import android.provider.UserDictionary;
import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -44,6 +45,7 @@
import androidx.loader.content.Loader;
import com.android.settings.R;
+import com.android.settings.core.FeatureFlags;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.Instrumentable;
@@ -104,6 +106,10 @@
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ // TODO(b/176883483): Remove the title after material component updated
+ if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.SILKY_HOME)) {
+ getActivity().setTitle(R.string.user_dict_settings_title);
+ }
// Show the language as a subtitle of the action bar
final ActionBar actionBar = getActivity().getActionBar();
if (actionBar != null) {
diff --git a/src/com/android/settings/network/telephony/EuiccOperationSidecar.java b/src/com/android/settings/network/telephony/EuiccOperationSidecar.java
index c82220e..a637cc2 100644
--- a/src/com/android/settings/network/telephony/EuiccOperationSidecar.java
+++ b/src/com/android/settings/network/telephony/EuiccOperationSidecar.java
@@ -99,7 +99,7 @@
Intent intent = new Intent(getReceiverAction());
intent.putExtra(EXTRA_OP_ID, mOpId);
return PendingIntent.getBroadcast(
- getContext(), REQUEST_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+ getContext(), REQUEST_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
}
@Override
diff --git a/src/com/android/settings/network/telephony/MobileDataSlice.java b/src/com/android/settings/network/telephony/MobileDataSlice.java
index c3b08d3..7c9bac0 100644
--- a/src/com/android/settings/network/telephony/MobileDataSlice.java
+++ b/src/com/android/settings/network/telephony/MobileDataSlice.java
@@ -173,7 +173,7 @@
private PendingIntent getPrimaryAction() {
final Intent intent = getIntent();
return PendingIntent.getActivity(mContext, 0 /* requestCode */,
- intent, 0 /* flags */);
+ intent, PendingIntent.FLAG_MUTABLE_UNAUDITED /* flags */);
}
/**
diff --git a/src/com/android/settings/network/telephony/MobileNetworkActivity.java b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
index b179770..92f0054 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkActivity.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
@@ -115,6 +115,9 @@
final ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
+ // TODO(b/176882938): Enable title after material component updated
+ // If CollapsingToolbarLayout is applied, the old action bar won't show title.
+ actionBar.setDisplayShowTitleEnabled(mCollapsingToolbarLayout == null);
}
getProxySubscriptionManager().setLifecycle(getLifecycle());
diff --git a/src/com/android/settings/notification/RedactionInterstitial.java b/src/com/android/settings/notification/RedactionInterstitial.java
index a17298f..27e2b72 100644
--- a/src/com/android/settings/notification/RedactionInterstitial.java
+++ b/src/com/android/settings/notification/RedactionInterstitial.java
@@ -77,6 +77,11 @@
findViewById(R.id.content_parent).setFitsSystemWindows(false);
}
+ @Override
+ protected boolean isToolbarEnabled() {
+ return false;
+ }
+
/**
* Create an intent for launching RedactionInterstitial.
*
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index 0c84ba9..f5e23fa 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -184,6 +184,11 @@
return false;
}
+ @Override
+ protected boolean isToolbarEnabled() {
+ return false;
+ }
+
/* package */ Class<? extends Fragment> getFragmentClass() {
return ChooseLockPasswordFragment.class;
}
diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java
index 6e9cf98..c52b410 100644
--- a/src/com/android/settings/password/ChooseLockPattern.java
+++ b/src/com/android/settings/password/ChooseLockPattern.java
@@ -194,6 +194,11 @@
return super.onKeyDown(keyCode, event);
}
+ @Override
+ protected boolean isToolbarEnabled() {
+ return false;
+ }
+
public static class ChooseLockPatternFragment extends InstrumentedFragment
implements SaveAndFinishWorker.Listener {
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
index 3ecff58..f0b50a1 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
@@ -176,6 +176,11 @@
}
}
+ @Override
+ protected boolean isToolbarEnabled() {
+ return false;
+ }
+
public void prepareEnterAnimation() {
getFragment().prepareEnterAnimation();
}
diff --git a/src/com/android/settings/password/SetupChooseLockPassword.java b/src/com/android/settings/password/SetupChooseLockPassword.java
index e82dc94..25f5a34 100644
--- a/src/com/android/settings/password/SetupChooseLockPassword.java
+++ b/src/com/android/settings/password/SetupChooseLockPassword.java
@@ -24,7 +24,6 @@
import android.util.Log;
import android.view.View;
import android.widget.Button;
-import android.widget.LinearLayout;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
@@ -65,8 +64,7 @@
@Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
- LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
- layout.setFitsSystemWindows(false);
+ findViewById(R.id.content_parent).setFitsSystemWindows(false);
}
public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment
diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java
index 8d5a3e0..b4bd409 100644
--- a/src/com/android/settings/sim/SimSelectNotification.java
+++ b/src/com/android/settings/sim/SimSelectNotification.java
@@ -226,7 +226,7 @@
resultIntent.setPackage(SETTINGS_PACKAGE_NAME);
resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -264,7 +264,7 @@
resultIntent.putExtra(Settings.EXTRA_SUB_ID, subId);
resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
builder.setContentIntent(resultPendingIntent);
// Notify the notification.
@@ -312,7 +312,7 @@
resultIntent.putExtra(Intent.EXTRA_TEXT, "help_uri_sim_combination_warning");
PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java
index 06f74d5..d05260a 100644
--- a/src/com/android/settings/wifi/WifiUtils.java
+++ b/src/com/android/settings/wifi/WifiUtils.java
@@ -56,12 +56,12 @@
}
/**
- * Check if the WPA2-PSK hotspot password is valid.
+ * Check if the hotspot password is valid.
*/
- public static boolean isHotspotWpa2PasswordValid(String password) {
+ public static boolean isHotspotPasswordValid(String password, int securityType) {
final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
try {
- configBuilder.setPassphrase(password, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ configBuilder.setPassphrase(password, securityType);
} catch (IllegalArgumentException e) {
return false;
}
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
index 26d742d..afab8c3 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
@@ -539,7 +539,7 @@
*/
public static PendingIntent getSettingsIntent(Context context) {
final Intent intent = new Intent(Settings.ACTION_SETTINGS);
- return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
+ return PendingIntent.getActivity(context, 0 /* requestCode */, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED /* flags */);
}
private PendingIntent getBroadcastIntent(String action) {
@@ -547,7 +547,7 @@
intent.setClass(mContext, SliceBroadcastReceiver.class);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
}
/**
@@ -557,7 +557,7 @@
final Intent intent = new Intent(action);
intent.setPackage(SETTINGS_PACKAGE_NAME);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
+ return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED /* flags */);
}
private Resources getResourcesForSubId(int subId) {
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 2957e1f..abf5bec 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -301,7 +301,11 @@
final String ssid = removeFirstAndLastDoubleQuotes(softApConfiguration.getSsid());
String security;
- if (softApConfiguration.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) {
+ final int securityType = softApConfiguration.getSecurityType();
+ if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE) {
+ security = WifiQrCode.SECURITY_SAE;
+ } else if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK
+ || securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) {
security = WifiQrCode.SECURITY_WPA_PSK;
} else {
security = WifiQrCode.SECURITY_NO_PASSWORD;
@@ -431,11 +435,11 @@
private static boolean isSupportHotspotConfiguratorQrCodeGenerator(
SoftApConfiguration softApConfiguration) {
- // QR code generator produces QR code with ZXing's Wi-Fi network config format,
- // it supports PSK and WEP and non security
- // KeyMgmt.NONE is for WEP or non security
- return softApConfiguration.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK
- || softApConfiguration.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_OPEN;
+ final int securityType = softApConfiguration.getSecurityType();
+ return securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE
+ || securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION
+ || securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK
+ || securityType == SoftApConfiguration.SECURITY_TYPE_OPEN;
}
private static boolean isSupportWifiDpp(Context context, int wifiEntrySecurity) {
diff --git a/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java
index be67d22..14766f9 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java
@@ -37,12 +37,16 @@
import java.util.UUID;
+/**
+ * Controller for logic pertaining to the password of Wi-Fi tethering.
+ */
public class WifiTetherPasswordPreferenceController extends WifiTetherBasePreferenceController
implements ValidatedEditTextPreference.Validator {
private static final String PREF_KEY = "wifi_tether_network_password";
private String mPassword;
+ private int mSecurityType;
private final MetricsFeatureProvider mMetricsFeatureProvider;
@@ -68,13 +72,13 @@
@Override
public void updateDisplay() {
final SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
- if (config == null
- || (config.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK
- && TextUtils.isEmpty(config.getPassphrase()))) {
+ if (config.getSecurityType() != SoftApConfiguration.SECURITY_TYPE_OPEN
+ && TextUtils.isEmpty(config.getPassphrase())) {
mPassword = generateRandomPassword();
} else {
mPassword = config.getPassphrase();
}
+ mSecurityType = config.getSecurityType();
((ValidatedEditTextPreference) mPreference).setValidator(this);
((ValidatedEditTextPreference) mPreference).setIsPassword(true);
((ValidatedEditTextPreference) mPreference).setIsSummaryPassword(true);
@@ -105,20 +109,27 @@
// don't actually overwrite unless we get a new config in case it was accidentally toggled.
if (securityType == SoftApConfiguration.SECURITY_TYPE_OPEN) {
return "";
- } else if (!isTextValid(mPassword)) {
+ } else if (!WifiUtils.isHotspotPasswordValid(mPassword, securityType)) {
mPassword = generateRandomPassword();
updatePasswordDisplay((EditTextPreference) mPreference);
}
return mPassword;
}
- public void updateVisibility(int securityType) {
+ /**
+ * This method set the security type of user selection. Then the controller will based on the
+ * security type changed to update the password changed on the preference.
+ *
+ * @param securityType The security type of SoftApConfiguration.
+ */
+ public void setSecurityType(int securityType) {
+ mSecurityType = securityType;
mPreference.setVisible(securityType != SoftApConfiguration.SECURITY_TYPE_OPEN);
}
@Override
public boolean isTextValid(String value) {
- return WifiUtils.isHotspotWpa2PasswordValid(value);
+ return WifiUtils.isHotspotPasswordValid(value, mSecurityType);
}
private static String generateRandomPassword() {
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceController.java
index 56b5031..acb8206 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceController.java
@@ -1,28 +1,65 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.settings.wifi.tether;
import static com.android.settings.AllInOneTetherSettings.DEDUP_POSTFIX;
+import android.annotation.NonNull;
import android.content.Context;
+import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApConfiguration;
+import android.net.wifi.WifiManager;
import android.util.FeatureFlagUtils;
+import android.util.Log;
+import androidx.annotation.VisibleForTesting;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.FeatureFlags;
-public class WifiTetherSecurityPreferenceController extends WifiTetherBasePreferenceController {
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Controller for logic pertaining to the security type of Wi-Fi tethering.
+ */
+public class WifiTetherSecurityPreferenceController extends WifiTetherBasePreferenceController
+ implements WifiManager.SoftApCallback {
private static final String PREF_KEY = "wifi_tether_security";
- private final String[] mSecurityEntries;
+ private Map<Integer, String> mSecurityMap = new LinkedHashMap<Integer, String>();
private int mSecurityValue;
+ @VisibleForTesting
+ boolean mIsWpa3Supported = true;
public WifiTetherSecurityPreferenceController(Context context,
OnTetherConfigUpdateListener listener) {
super(context, listener);
- mSecurityEntries = mContext.getResources().getStringArray(R.array.wifi_tether_security);
+ final String[] securityNames = mContext.getResources().getStringArray(
+ R.array.wifi_tether_security);
+ final String[] securityValues = mContext.getResources().getStringArray(
+ R.array.wifi_tether_security_values);
+ for (int i = 0; i < securityNames.length; i++) {
+ mSecurityMap.put(Integer.parseInt(securityValues[i]), securityNames[i]);
+ }
+ mWifiManager.registerSoftApCallback(context.getMainExecutor(), this);
}
@Override
@@ -33,35 +70,55 @@
@Override
public void updateDisplay() {
- final SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
- if (config != null && config.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_OPEN) {
- mSecurityValue = SoftApConfiguration.SECURITY_TYPE_OPEN;
- } else {
- mSecurityValue = SoftApConfiguration.SECURITY_TYPE_WPA2_PSK;
+ // The mPreference will be ready when the fragment calls displayPreference(). Since the
+ // capability of WPA3 hotspot callback will update the preference list here, add null point
+ // checking to avoid the mPreference is not ready when the fragment is loading for settings
+ // keyword searching only.
+ if (mPreference == null) {
+ return;
+ }
+ final ListPreference preference = (ListPreference) mPreference;
+ // If the device is not support WPA3 then remove the WPA3 options.
+ if (!mIsWpa3Supported && mSecurityMap.keySet()
+ .removeIf(key -> key > SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)) {
+ preference.setEntries(mSecurityMap.values().stream().toArray(CharSequence[]::new));
+ preference.setEntryValues(mSecurityMap.keySet().stream().map(Integer::toBinaryString)
+ .toArray(CharSequence[]::new));
}
- final ListPreference preference = (ListPreference) mPreference;
- preference.setSummary(getSummaryForSecurityType(mSecurityValue));
+ final int securityType = mWifiManager.getSoftApConfiguration().getSecurityType();
+ mSecurityValue = mSecurityMap.get(securityType) != null
+ ? securityType : SoftApConfiguration.SECURITY_TYPE_WPA2_PSK;
+
+ preference.setSummary(mSecurityMap.get(mSecurityValue));
preference.setValue(String.valueOf(mSecurityValue));
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mSecurityValue = Integer.parseInt((String) newValue);
- preference.setSummary(getSummaryForSecurityType(mSecurityValue));
- mListener.onTetherConfigUpdated(this);
+ preference.setSummary(mSecurityMap.get(mSecurityValue));
+ if (mListener != null) {
+ mListener.onTetherConfigUpdated(this);
+ }
return true;
}
+ @Override
+ public void onCapabilityChanged(@NonNull SoftApCapability softApCapability) {
+ final boolean isWpa3Supported =
+ softApCapability.areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_WPA3_SAE);
+ if (!isWpa3Supported) {
+ Log.i(PREF_KEY, "WPA3 SAE is not supported on this device");
+ }
+ if (mIsWpa3Supported != isWpa3Supported) {
+ mIsWpa3Supported = isWpa3Supported;
+ updateDisplay();
+ }
+ mWifiManager.unregisterSoftApCallback(this);
+ }
+
public int getSecurityType() {
return mSecurityValue;
}
-
- private String getSummaryForSecurityType(int securityType) {
- if (securityType == SoftApConfiguration.SECURITY_TYPE_OPEN) {
- return mSecurityEntries[1];
- }
- // WPA2 PSK
- return mSecurityEntries[0];
- }
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
index d6c49bc..f260298 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@@ -192,7 +192,7 @@
@Override
public void onTetherConfigUpdated(AbstractPreferenceController context) {
final SoftApConfiguration config = buildNewConfig();
- mPasswordPreferenceController.updateVisibility(config.getSecurityType());
+ mPasswordPreferenceController.setSecurityType(config.getSecurityType());
/**
* if soft AP is stopped, bring up
@@ -216,10 +216,10 @@
final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
final int securityType = mSecurityPreferenceController.getSecurityType();
configBuilder.setSsid(mSSIDPreferenceController.getSSID());
- if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) {
+ if (securityType != SoftApConfiguration.SECURITY_TYPE_OPEN) {
configBuilder.setPassphrase(
mPasswordPreferenceController.getPasswordValidated(securityType),
- SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ securityType);
}
configBuilder.setBand(mApBandPreferenceController.getBandIndex());
return configBuilder.build();
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java
index 74c0bb5..7a4c610 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultAppShortcutPreferenceControllerBaseTest.java
@@ -25,6 +25,7 @@
import static org.robolectric.Shadows.shadowOf;
import android.app.Activity;
+import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.Intent;
@@ -62,6 +63,8 @@
@Mock
private RoleManager mRoleManager;
@Mock
+ private RoleControllerManager mRoleControllerManager;
+ @Mock
private Preference mPreference;
private Activity mActivity;
@@ -74,6 +77,7 @@
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
shadowApplication.setSystemService(Context.ROLE_SERVICE, mRoleManager);
+ shadowApplication.setSystemService(Context.ROLE_CONTROLLER_SERVICE, mRoleControllerManager);
mActivity = Robolectric.setupActivity(Activity.class);
mShadowUserManager = shadowOf(mActivity.getSystemService(UserManager.class));
mController = new TestRolePreferenceController(mActivity);
@@ -82,7 +86,7 @@
@Test
public void constructor_callsIsApplicationVisibleForRole() {
- verify(mRoleManager).isApplicationVisibleForRole(eq(TEST_ROLE_NAME), eq(
+ verify(mRoleControllerManager).isApplicationVisibleForRole(eq(TEST_ROLE_NAME), eq(
TEST_PACKAGE_NAME), any(Executor.class), any(Consumer.class));
}
@@ -149,7 +153,7 @@
private void setRoleIsVisible(boolean visible) {
final ArgumentCaptor<Consumer<Boolean>> callbackCaptor = ArgumentCaptor.forClass(
Consumer.class);
- verify(mRoleManager).isRoleVisible(eq(TEST_ROLE_NAME), any(Executor.class),
+ verify(mRoleControllerManager).isRoleVisible(eq(TEST_ROLE_NAME), any(Executor.class),
callbackCaptor.capture());
final Consumer<Boolean> callback = callbackCaptor.getValue();
callback.accept(visible);
@@ -158,7 +162,7 @@
private void setApplicationIsVisibleForRole(boolean visible) {
final ArgumentCaptor<Consumer<Boolean>> callbackCaptor = ArgumentCaptor.forClass(
Consumer.class);
- verify(mRoleManager).isApplicationVisibleForRole(eq(TEST_ROLE_NAME), eq(
+ verify(mRoleControllerManager).isApplicationVisibleForRole(eq(TEST_ROLE_NAME), eq(
TEST_PACKAGE_NAME), any(Executor.class), callbackCaptor.capture());
final Consumer<Boolean> callback = callbackCaptor.getValue();
callback.accept(visible);
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java
index 6d4186c..5940d72 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultBrowserShortcutPreferenceControllerTest.java
@@ -18,7 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
-import android.app.role.RoleManager;
+import android.app.role.RoleControllerManager;
import android.content.Context;
import org.junit.Before;
@@ -34,14 +34,15 @@
public class DefaultBrowserShortcutPreferenceControllerTest {
@Mock
- private RoleManager mRoleManager;
+ private RoleControllerManager mRoleControllerManager;
private DefaultBrowserShortcutPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- ShadowApplication.getInstance().setSystemService(Context.ROLE_SERVICE, mRoleManager);
+ ShadowApplication.getInstance().setSystemService(Context.ROLE_CONTROLLER_SERVICE,
+ mRoleControllerManager);
mController = new DefaultBrowserShortcutPreferenceController(RuntimeEnvironment.application,
"Package1");
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultEmergencyShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultEmergencyShortcutPreferenceControllerTest.java
index 0acd7bd..8dcf530 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultEmergencyShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultEmergencyShortcutPreferenceControllerTest.java
@@ -18,7 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
-import android.app.role.RoleManager;
+import android.app.role.RoleControllerManager;
import android.content.Context;
import org.junit.Before;
@@ -34,14 +34,15 @@
public class DefaultEmergencyShortcutPreferenceControllerTest {
@Mock
- private RoleManager mRoleManager;
+ private RoleControllerManager mRoleControllerManager;
private DefaultEmergencyShortcutPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- ShadowApplication.getInstance().setSystemService(Context.ROLE_SERVICE, mRoleManager);
+ ShadowApplication.getInstance().setSystemService(Context.ROLE_CONTROLLER_SERVICE,
+ mRoleControllerManager);
mController = new DefaultEmergencyShortcutPreferenceController(
RuntimeEnvironment.application, "Package1");
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultHomeShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultHomeShortcutPreferenceControllerTest.java
index 1f0023a..7071fec 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultHomeShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultHomeShortcutPreferenceControllerTest.java
@@ -18,7 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
-import android.app.role.RoleManager;
+import android.app.role.RoleControllerManager;
import android.content.Context;
import org.junit.Before;
@@ -34,14 +34,15 @@
public class DefaultHomeShortcutPreferenceControllerTest {
@Mock
- private RoleManager mRoleManager;
+ private RoleControllerManager mRoleControllerManager;
private DefaultHomeShortcutPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- ShadowApplication.getInstance().setSystemService(Context.ROLE_SERVICE, mRoleManager);
+ ShadowApplication.getInstance().setSystemService(Context.ROLE_CONTROLLER_SERVICE,
+ mRoleControllerManager);
mController = new DefaultHomeShortcutPreferenceController(RuntimeEnvironment.application,
"Package1");
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java
index c130665..d1b6aeb 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java
@@ -18,7 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
-import android.app.role.RoleManager;
+import android.app.role.RoleControllerManager;
import android.content.Context;
import org.junit.Before;
@@ -37,14 +37,15 @@
private static final String PREFERENCE_KEY = "default_phone_app";
@Mock
- private RoleManager mRoleManager;
+ private RoleControllerManager mRoleControllerManager;
private DefaultPhoneShortcutPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- ShadowApplication.getInstance().setSystemService(Context.ROLE_SERVICE, mRoleManager);
+ ShadowApplication.getInstance().setSystemService(Context.ROLE_CONTROLLER_SERVICE,
+ mRoleControllerManager);
mController = new DefaultPhoneShortcutPreferenceController(RuntimeEnvironment.application,
TEST_PACKAGE_NAME);
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java
index e9c238d..691ce5e 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultSmsShortcutPreferenceControllerTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.content.Context;
@@ -38,6 +39,8 @@
@Mock
private RoleManager mRoleManager;
+ @Mock
+ private RoleControllerManager mRoleControllerManager;
private DefaultSmsShortcutPreferenceController mController;
@@ -46,6 +49,7 @@
MockitoAnnotations.initMocks(this);
final ShadowApplication shadowApplication = ShadowApplication.getInstance();
shadowApplication.setSystemService(Context.ROLE_SERVICE, mRoleManager);
+ shadowApplication.setSystemService(Context.ROLE_CONTROLLER_SERVICE, mRoleControllerManager);
mController = new DefaultSmsShortcutPreferenceController(RuntimeEnvironment.application,
TEST_PACKAGE_NAME);
}
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
index 03a63b0..0dcf685 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
@@ -397,14 +397,14 @@
final Intent intent = new Intent(action);
intent.setClass(mContext, SliceBroadcastReceiver.class);
return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
}
private PendingIntent getActivityIntent(String action) {
final Intent intent = new Intent(action);
intent.setPackage(SETTINGS_PACKAGE_NAME);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
+ return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED /* flags */);
}
private void assertTitle(List<SliceItem> sliceItems, String title) {
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java
deleted file mode 100644
index c7d0695..0000000
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.android.settings.wifi.tether;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.wifi.SoftApConfiguration;
-import android.net.wifi.WifiManager;
-
-import androidx.preference.ListPreference;
-import androidx.preference.PreferenceScreen;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class WifiTetherSecurityPreferenceControllerTest {
-
- private static final String WPA2_PSK =
- String.valueOf(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
- private static final String NONE = String.valueOf(SoftApConfiguration.SECURITY_TYPE_OPEN);
- @Mock
- private WifiTetherBasePreferenceController.OnTetherConfigUpdateListener mListener;
- private Context mContext;
- @Mock
- private ConnectivityManager mConnectivityManager;
- @Mock
- private WifiManager mWifiManager;
- @Mock
- private PreferenceScreen mScreen;
- private WifiTetherSecurityPreferenceController mController;
- private ListPreference mPreference;
- private SoftApConfiguration mConfig;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mConfig = new SoftApConfiguration.Builder().setSsid("test_1234")
- .setPassphrase("test_password",
- SoftApConfiguration.SECURITY_TYPE_WPA2_PSK).build();
- mContext = spy(RuntimeEnvironment.application);
-
- when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
- when(mWifiManager.getSoftApConfiguration()).thenReturn(mConfig);
- when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
- .thenReturn(mConnectivityManager);
- when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"1", "2"});
- when(mScreen.findPreference(anyString())).thenReturn(mPreference);
-
- mController = new WifiTetherSecurityPreferenceController(mContext, mListener);
- mPreference = new ListPreference(RuntimeEnvironment.application);
- mController.mPreference = mPreference;
- }
-
- @Test
- public void onPreferenceChange_securityValueUpdated() {
- mController.onPreferenceChange(mPreference, WPA2_PSK);
- assertThat(mController.getSecurityType()).isEqualTo(
- SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
- assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal");
-
- mController.onPreferenceChange(mPreference, NONE);
- assertThat(mController.getSecurityType()).isEqualTo(
- SoftApConfiguration.SECURITY_TYPE_OPEN);
- assertThat(mPreference.getSummary().toString()).isEqualTo("None");
- }
-
- @Test
- public void updateDisplay_preferenceUpdated() {
- // test defaulting to WPA2-Personal on new config
- when(mWifiManager.getSoftApConfiguration()).thenReturn(null);
- mController.updateDisplay();
- assertThat(mController.getSecurityType()).isEqualTo(
- SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
- assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal");
-
- // test open tether network
- SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig)
- .setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN).build();
- when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
- mController.updateDisplay();
- assertThat(mController.getSecurityType()).isEqualTo(
- SoftApConfiguration.SECURITY_TYPE_OPEN);
- assertThat(mPreference.getSummary().toString()).isEqualTo("None");
-
- // test WPA2-Personal tether network
- SoftApConfiguration config2 = new SoftApConfiguration.Builder(mConfig)
- .setPassphrase("test_password",
- SoftApConfiguration.SECURITY_TYPE_WPA2_PSK).build();
- when(mWifiManager.getSoftApConfiguration()).thenReturn(config2);
- mController.updateDisplay();
- assertThat(mController.getSecurityType()).isEqualTo(
- SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
- assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal");
- }
-}
diff --git a/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java b/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java
index 7a75443..1a5e852 100644
--- a/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java
+++ b/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiConfiguration;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -46,12 +47,48 @@
public void testPassword() {
final String longPassword = "123456789012345678901234567890"
+ "1234567890123456789012345678901234567890";
- assertThat(WifiUtils.isHotspotWpa2PasswordValid("123")).isFalse();
- assertThat(WifiUtils.isHotspotWpa2PasswordValid("12345678")).isTrue();
- assertThat(WifiUtils.isHotspotWpa2PasswordValid("1234567890")).isTrue();
- assertThat(WifiUtils.isHotspotWpa2PasswordValid(longPassword)).isFalse();
- assertThat(WifiUtils.isHotspotWpa2PasswordValid("")).isFalse();
- assertThat(WifiUtils.isHotspotWpa2PasswordValid("€¥£")).isFalse();
+ assertThat(WifiUtils.isHotspotPasswordValid("123",
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isFalse();
+ assertThat(WifiUtils.isHotspotPasswordValid("12345678",
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isTrue();
+ assertThat(WifiUtils.isHotspotPasswordValid("1234567890",
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isTrue();
+ assertThat(WifiUtils.isHotspotPasswordValid(longPassword,
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isFalse();
+ assertThat(WifiUtils.isHotspotPasswordValid("",
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isFalse();
+ assertThat(WifiUtils.isHotspotPasswordValid("€¥£",
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isFalse();
+
+ // The WPA3_SAE_TRANSITION password limitation should be same as WPA2_PSK
+ assertThat(WifiUtils.isHotspotPasswordValid("123",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isFalse();
+ assertThat(WifiUtils.isHotspotPasswordValid("12345678",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isTrue();
+ assertThat(WifiUtils.isHotspotPasswordValid("1234567890",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isTrue();
+ assertThat(WifiUtils.isHotspotPasswordValid(longPassword,
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isFalse();
+ assertThat(WifiUtils.isHotspotPasswordValid("",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isFalse();
+ assertThat(WifiUtils.isHotspotPasswordValid("€¥£",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isFalse();
+
+ // The WA3_SAE password is requested that length > 1 only.
+ assertThat(WifiUtils.isHotspotPasswordValid("",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isFalse();
+ assertThat(WifiUtils.isHotspotPasswordValid("1",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue();
+ assertThat(WifiUtils.isHotspotPasswordValid("123",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue();
+ assertThat(WifiUtils.isHotspotPasswordValid("12345678",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue();
+ assertThat(WifiUtils.isHotspotPasswordValid("1234567890",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue();
+ assertThat(WifiUtils.isHotspotPasswordValid(longPassword,
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue();
+ assertThat(WifiUtils.isHotspotPasswordValid("€¥£",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue();
}
@Test
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java
new file mode 100644
index 0000000..c86e3e5
--- /dev/null
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.tether;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.wifi.SoftApConfiguration;
+import android.net.wifi.WifiManager;
+import android.os.Looper;
+
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+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;
+
+@RunWith(AndroidJUnit4.class)
+public class WifiTetherSecurityPreferenceControllerTest {
+
+ private static final String PREF_KEY = "wifi_tether_security";
+ private static final String WPA3_SAE =
+ String.valueOf(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
+ private static final String WPA3_SAE_TRANSITION =
+ String.valueOf(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION);
+ private static final String WPA2_PSK =
+ String.valueOf(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ private static final String NONE = String.valueOf(SoftApConfiguration.SECURITY_TYPE_OPEN);
+
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Mock
+ private WifiManager mWifiManager;
+ @Mock
+ private WifiTetherBasePreferenceController.OnTetherConfigUpdateListener mListener;
+
+ private WifiTetherSecurityPreferenceController mController;
+ private ListPreference mPreference;
+ private SoftApConfiguration mConfig;
+
+ @Before
+ public void setUp() {
+ final Context context = spy(ApplicationProvider.getApplicationContext());
+ mConfig = new SoftApConfiguration.Builder().setSsid("test_1234")
+ .setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN).build();
+ when(context.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
+ when(mWifiManager.getSoftApConfiguration()).thenReturn(mConfig);
+
+ mController = new WifiTetherSecurityPreferenceController(context, mListener);
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+ final PreferenceManager preferenceManager = new PreferenceManager(context);
+ final PreferenceScreen screen = preferenceManager.createPreferenceScreen(context);
+ mPreference = new ListPreference(context);
+ mPreference.setKey(PREF_KEY);
+ screen.addPreference(mPreference);
+ mController.displayPreference(screen);
+ }
+
+ @Test
+ public void onPreferenceChange_toWpa3Sae_shouldUpdateSecurityValue() {
+ mController.onPreferenceChange(mPreference, WPA3_SAE);
+
+ assertThat(mController.getSecurityType())
+ .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
+ assertThat(mPreference.getSummary().toString()).isEqualTo("WPA3-Personal");
+ }
+
+ @Test
+ public void onPreferenceChange_toWpa3SaeTransition_shouldUpdateSecurityValue() {
+ mController.onPreferenceChange(mPreference, WPA3_SAE_TRANSITION);
+
+ assertThat(mController.getSecurityType())
+ .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION);
+ assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2/WPA3-Personal");
+ }
+
+ @Test
+ public void onPreferenceChange_toWpa2Psk_shouldUpdateSecurityValue() {
+ mController.onPreferenceChange(mPreference, WPA2_PSK);
+
+ assertThat(mController.getSecurityType())
+ .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal");
+ }
+
+ @Test
+ public void onPreferenceChange_toNone_shouldUpdateSecurityValue() {
+ mController.onPreferenceChange(mPreference, NONE);
+
+ assertThat(mController.getSecurityType())
+ .isEqualTo(SoftApConfiguration.SECURITY_TYPE_OPEN);
+ assertThat(mPreference.getSummary().toString()).isEqualTo("None");
+ }
+
+ @Test
+ public void updateDisplay_toWpa3Sae_shouldUpdateSecurityValue() {
+ SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig)
+ .setPassphrase("test_password",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE).build();
+ when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+
+ mController.updateDisplay();
+
+ assertThat(mController.getSecurityType())
+ .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
+ assertThat(mPreference.getSummary().toString()).isEqualTo("WPA3-Personal");
+ }
+
+ @Test
+ public void updateDisplay_toWpa3SaeTransition_shouldUpdateSecurityValue() {
+ SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig)
+ .setPassphrase("test_password",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION).build();
+ when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+
+ mController.updateDisplay();
+
+ assertThat(mController.getSecurityType())
+ .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION);
+ assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2/WPA3-Personal");
+ }
+
+ @Test
+ public void updateDisplay_toWpa2Psk_shouldUpdateSecurityValue() {
+ SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig)
+ .setPassphrase("test_password",
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK).build();
+ when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+
+ mController.updateDisplay();
+
+ assertThat(mController.getSecurityType())
+ .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal");
+ }
+
+ @Test
+ public void updateDisplay_toNone_shouldUpdateSecurityValue() {
+ SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig)
+ .setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN).build();
+ when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+
+ mController.updateDisplay();
+
+ assertThat(mController.getSecurityType())
+ .isEqualTo(SoftApConfiguration.SECURITY_TYPE_OPEN);
+ assertThat(mPreference.getSummary().toString()).isEqualTo("None");
+ }
+
+ @Test
+ public void updateDisplay_toWpa3SaeButNotSupportWpa3_shouldBeDefaultToWpa2() {
+ mController.mIsWpa3Supported = false;
+ SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig)
+ .setPassphrase("test_password",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE).build();
+ when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+
+ mController.updateDisplay();
+
+ assertThat(mController.getSecurityType())
+ .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal");
+ }
+
+ @Test
+ public void updateDisplay_toWpa3SaeTransitionButNotSupportWpa3_shouldBeDefaultToWpa2() {
+ mController.mIsWpa3Supported = false;
+ SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig)
+ .setPassphrase("test_password",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION).build();
+ when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+
+ mController.updateDisplay();
+
+ assertThat(mController.getSecurityType())
+ .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal");
+ }
+}