Merge "[Settings] Adds an intent extra when setup wizard start the WallpaperSuggestionActivity"
diff --git a/Android.bp b/Android.bp
index b997b91..d21a430 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,7 +43,17 @@
libs: [
"telephony-common",
"ims-common",
+ "app-compat-annotations",
],
+
+ plugins: [
+ "compat-changeid-annotation-processor",
+ ]
+}
+
+platform_compat_config {
+ name: "settings-platform-compat-config",
+ src: ":Settings-core",
}
android_app {
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6ee6a87..a4803a9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3244,6 +3244,24 @@
android:value="com.android.settings.gestures.GlobalActionsPanelSettings" />
</activity>
+ <activity
+ android:name="Settings$GestureNavigationSettingsActivity"
+ android:label="@string/gesture_settings_activity_title"
+ android:enabled="true">
+ <intent-filter android:priority="32">
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.settings.SHORTCUT" />
+ </intent-filter>
+ <intent-filter android:priority="1">
+ <action android:name="com.android.settings.GESTURE_NAVIGATION_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.gestures.GestureNavigationSettingsFragment" />
+ <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+ android:value="true" />
+ </activity>
+
<!-- This is the longest AndroidManifest.xml ever. -->
</application>
</manifest>
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 3cb964f..a258cc6 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -2,18 +2,6 @@
<issues format="4">
<issue
- id="LintError"
- severity="Error"
- message="No `.class` files were found in project ".", so none of the classfile based checks could be run. Does the project need to be built first?"
- category="Lint"
- priority="10"
- summary="Lint Failure"
- explanation="This issue type represents a problem running lint itself. Examples include failure to find bytecode for source files (which means certain detectors could not be run), parsing errors in lint configuration files, etc.
These errors are not errors in your own code, but they are shown to make it clear that some checks were not completed.">
- <location
- file="."/>
- </issue>
-
- <issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
@@ -121,7 +109,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout-land/choose_lock_pattern.xml"
- line="178"
+ line="127"
column="17"/>
</issue>
@@ -1081,7 +1069,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="113"
+ line="111"
column="5"/>
</issue>
@@ -1097,7 +1085,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="114"
+ line="112"
column="5"/>
</issue>
@@ -1113,7 +1101,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="115"
+ line="113"
column="5"/>
</issue>
@@ -1129,7 +1117,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="116"
+ line="114"
column="5"/>
</issue>
@@ -1145,7 +1133,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="117"
+ line="115"
column="5"/>
</issue>
@@ -1161,7 +1149,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="118"
+ line="116"
column="5"/>
</issue>
@@ -1177,7 +1165,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="121"
+ line="119"
column="5"/>
</issue>
@@ -1193,7 +1181,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="122"
+ line="120"
column="5"/>
</issue>
@@ -1209,7 +1197,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="123"
+ line="121"
column="5"/>
</issue>
@@ -1225,7 +1213,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="124"
+ line="122"
column="5"/>
</issue>
@@ -1241,7 +1229,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="125"
+ line="123"
column="5"/>
</issue>
@@ -1257,7 +1245,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="128"
+ line="126"
column="5"/>
</issue>
@@ -1273,7 +1261,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="129"
+ line="127"
column="5"/>
</issue>
@@ -1289,7 +1277,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="130"
+ line="128"
column="5"/>
</issue>
@@ -1305,7 +1293,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="131"
+ line="129"
column="5"/>
</issue>
@@ -1321,7 +1309,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="132"
+ line="130"
column="5"/>
</issue>
@@ -1337,7 +1325,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="133"
+ line="131"
column="5"/>
</issue>
@@ -1353,7 +1341,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="139"
+ line="137"
column="5"/>
</issue>
@@ -1369,7 +1357,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="140"
+ line="138"
column="5"/>
</issue>
@@ -1385,7 +1373,39 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="141"
+ line="139"
+ 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="face_intro_outline">#ffdadce0</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="148"
+ 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="back_gesture_indicator">#4182ef</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="150"
column="5"/>
</issue>
@@ -1433,7 +1453,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/crypt_keeper_emergency_button.xml"
- line="36"
+ line="35"
column="9"/>
</issue>
@@ -1509,6 +1529,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:fillColor="@color/face_intro_outline""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/drawable/face_enroll_introduction.xml"
+ line="25"
+ column="9"/>
+ </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:background="#80000000""
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -2393,7 +2429,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/running_processes_header.xml"
- line="146"
+ line="129"
column="13"/>
</issue>
@@ -2581,27 +2617,11 @@
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=" <string name="sync_plug" msgid="3905078969081888738">""<font fgcolor="#ffffffff">"Welcome to Google sync!"</font>" \nA Google approach to syncing data to allow access to your contacts, appointments, and more from wherever you are."</string>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values-en-rXC/strings.xml"
- line="2652"
- column="169"/>
- </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=" <string name="sync_plug" msgid="3905078969081888738"><font fgcolor="#ffffffff">"Welcome to Google sync!"</font>" \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are."</string>"
+ errorLine1=" <string name="sync_plug" msgid="7956982719077985381"><font fgcolor="#ffffffff">"Welcome to Google sync!"</font>" \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are."</string>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rAU/strings.xml"
- line="2653"
+ line="2663"
column="64"/>
</issue>
@@ -2613,11 +2633,11 @@
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=" <string name="sync_plug" msgid="3905078969081888738"><font fgcolor="#ffffffff">"Welcome to Google sync!"</font>" \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are."</string>"
+ errorLine1=" <string name="sync_plug" msgid="7956982719077985381"><font fgcolor="#ffffffff">"Welcome to Google sync!"</font>" \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are."</string>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rCA/strings.xml"
- line="2653"
+ line="2663"
column="64"/>
</issue>
@@ -2629,11 +2649,11 @@
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=" <string name="sync_plug" msgid="3905078969081888738"><font fgcolor="#ffffffff">"Welcome to Google sync!"</font>" \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are."</string>"
+ errorLine1=" <string name="sync_plug" msgid="7956982719077985381"><font fgcolor="#ffffffff">"Welcome to Google sync!"</font>" \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are."</string>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rGB/strings.xml"
- line="2653"
+ line="2663"
column="64"/>
</issue>
@@ -2645,11 +2665,11 @@
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=" <string name="sync_plug" msgid="3905078969081888738"><font fgcolor="#ffffffff">"Welcome to Google sync!"</font>" \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are."</string>"
+ errorLine1=" <string name="sync_plug" msgid="7956982719077985381"><font fgcolor="#ffffffff">"Welcome to Google sync!"</font>" \nA Google approach to syncing data to allow access to your contacts, appointments and more from wherever you are."</string>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rIN/strings.xml"
- line="2653"
+ line="2663"
column="64"/>
</issue>
@@ -2661,11 +2681,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=" <string name="sync_plug" msgid="7956982719077985381">""<font fgcolor="#ffffffff">"Welcome to Google sync!"</font>" \nA Google approach to syncing data to allow access to your contacts, appointments, and more from wherever you are."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values-en-rXC/strings.xml"
+ line="2663"
+ column="170"/>
+ </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=" <string name="sync_plug"><font fgcolor="#ffffffff">Welcome to Google sync!</font>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/strings.xml"
- line="6186"
+ line="6183"
column="36"/>
</issue>
@@ -2697,7 +2733,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
- line="380"
+ line="378"
column="44"/>
</issue>
@@ -2713,7 +2749,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
- line="386"
+ line="384"
column="44"/>
</issue>
@@ -2729,7 +2765,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
- line="387"
+ line="385"
column="44"/>
</issue>
@@ -2745,7 +2781,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
- line="423"
+ line="421"
column="34"/>
</issue>
@@ -2761,7 +2797,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
- line="103"
+ line="106"
column="40"/>
</issue>
@@ -2777,7 +2813,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
- line="103"
+ line="106"
column="40"/>
</issue>
@@ -2793,7 +2829,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
- line="171"
+ line="176"
column="45"/>
</issue>
@@ -2809,7 +2845,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
- line="172"
+ line="177"
column="49"/>
</issue>
@@ -2825,7 +2861,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
- line="180"
+ line="185"
column="45"/>
</issue>
@@ -2841,7 +2877,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
- line="181"
+ line="186"
column="49"/>
</issue>
@@ -2857,7 +2893,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
- line="249"
+ line="254"
column="42"/>
</issue>
@@ -2905,7 +2941,7 @@
errorLine2=" ^">
<location
file="res/values/themes_suw.xml"
- line="67"
+ line="66"
column="40"/>
</issue>
@@ -2921,7 +2957,7 @@
errorLine2=" ^">
<location
file="res/values/themes_suw.xml"
- line="86"
+ line="85"
column="40"/>
</issue>
@@ -2937,7 +2973,7 @@
errorLine2=" ^">
<location
file="res/values/themes_suw.xml"
- line="105"
+ line="103"
column="40"/>
</issue>
@@ -2953,7 +2989,7 @@
errorLine2=" ^">
<location
file="res/values/themes_suw.xml"
- line="124"
+ line="127"
column="40"/>
</issue>
@@ -2969,7 +3005,7 @@
errorLine2=" ^">
<location
file="res/values/themes_suw.xml"
- line="186"
+ line="188"
column="43"/>
</issue>
@@ -2985,7 +3021,7 @@
errorLine2=" ^">
<location
file="res/values/themes_suw.xml"
- line="187"
+ line="189"
column="42"/>
</issue>
@@ -3001,7 +3037,7 @@
errorLine2=" ^">
<location
file="res/values/themes_suw.xml"
- line="188"
+ line="190"
column="45"/>
</issue>
@@ -3037,36 +3073,4 @@
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="face_intro_outline">#ffdadce0</color> </color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="150"
- column="40"/>
- </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:fillColor="@color/face_intro_outline""
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/drawable/face_enroll_introduction.xml"
- line="25"
- column="40"/>
- </issue>
-
</issues>
diff --git a/res/drawable/accessibility_magnification_full_screen.png b/res/drawable/accessibility_magnification_full_screen.png
new file mode 100644
index 0000000..7fcd17d
--- /dev/null
+++ b/res/drawable/accessibility_magnification_full_screen.png
Binary files differ
diff --git a/res/drawable/accessibility_magnification_window_screen.png b/res/drawable/accessibility_magnification_window_screen.png
new file mode 100644
index 0000000..db1f332
--- /dev/null
+++ b/res/drawable/accessibility_magnification_window_screen.png
Binary files differ
diff --git a/res/drawable/accessibility_shortcut_type_hardware.png b/res/drawable/accessibility_shortcut_type_hardware.png
new file mode 100644
index 0000000..141af83
--- /dev/null
+++ b/res/drawable/accessibility_shortcut_type_hardware.png
Binary files differ
diff --git a/res/drawable/accessibility_shortcut_type_software.png b/res/drawable/accessibility_shortcut_type_software.png
new file mode 100644
index 0000000..5b0611d
--- /dev/null
+++ b/res/drawable/accessibility_shortcut_type_software.png
Binary files differ
diff --git a/res/drawable/accessibility_shortcut_type_software_gesture.png b/res/drawable/accessibility_shortcut_type_software_gesture.png
new file mode 100644
index 0000000..a5df752
--- /dev/null
+++ b/res/drawable/accessibility_shortcut_type_software_gesture.png
Binary files differ
diff --git a/res/drawable/accessibility_shortcut_type_triple_tap.png b/res/drawable/accessibility_shortcut_type_triple_tap.png
new file mode 100644
index 0000000..5c6ce95
--- /dev/null
+++ b/res/drawable/accessibility_shortcut_type_triple_tap.png
Binary files differ
diff --git a/res/layout/accessibility_edit_magnification_mode.xml b/res/layout/accessibility_edit_magnification_mode.xml
new file mode 100644
index 0000000..e34f32e
--- /dev/null
+++ b/res/layout/accessibility_edit_magnification_mode.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License
+ -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbarStyle="outsideOverlay">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingEnd="24dp"
+ android:paddingStart="24dp">
+
+ <TextView
+ style="@style/AccessibilityDialogDescription"
+ android:text="@string/accessibility_magnification_area_settings_message" />
+
+ <include
+ android:id="@+id/magnify_full_screen"
+ layout="@layout/accessibility_edit_shortcut_component" />
+
+ <include
+ android:id="@+id/magnify_window_screen"
+ layout="@layout/accessibility_edit_shortcut_component" />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/res/layout/accessibility_edit_shortcut_component.xml b/res/layout/accessibility_edit_shortcut_component.xml
index 2e1ad2d..52b8935 100644
--- a/res/layout/accessibility_edit_shortcut_component.xml
+++ b/res/layout/accessibility_edit_shortcut_component.xml
@@ -19,12 +19,14 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:paddingBottom="16dp">
<CheckBox
android:id="@+id/checkbox"
android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"
+ android:saveEnabled="false"/>
<TextView
android:id="@+id/summary"
diff --git a/res/layout/accessibility_shortcut_secondary_action.xml b/res/layout/accessibility_shortcut_secondary_action.xml
index 81d7bd5..9d59b2e 100644
--- a/res/layout/accessibility_shortcut_secondary_action.xml
+++ b/res/layout/accessibility_shortcut_secondary_action.xml
@@ -60,7 +60,7 @@
android:paddingBottom="16dp">
<TextView
- android:id="@+android:id/title"
+ android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
@@ -68,7 +68,7 @@
android:ellipsize="marquee" />
<TextView
- android:id="@+android:id/summary"
+ android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+android:id/title"
diff --git a/res/layout/back_gesture_indicator_container.xml b/res/layout/back_gesture_indicator_container.xml
new file mode 100644
index 0000000..17b9126
--- /dev/null
+++ b/res/layout/back_gesture_indicator_container.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ImageView
+ android:layout_width="@dimen/back_gesture_indicator_width"
+ android:layout_height="match_parent"
+ android:id="@+id/indicator_left">
+ </ImageView>
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <ImageView
+ android:layout_width="@dimen/back_gesture_indicator_width"
+ android:layout_height="match_parent"
+ android:id="@+id/indicator_right">
+ </ImageView>
+
+</LinearLayout>
+
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 6b7f842..e4a6b27 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -277,8 +277,8 @@
<!-- Wi-Fi AP band settings. Either Auto, 2.4GHz or 5GHz. -->
<!-- Note that adding/removing/moving the items will need wifi settings code change. -->
<string-array translatable="false" name="wifi_ap_band_config_full">
- <item>0</item>
<item>1</item>
+ <item>2</item>
</string-array>
<string-array translatable="false" name="wifi_ap_band_summary_full">
@@ -287,8 +287,8 @@
</string-array>
<string-array translatable="false" name="wifi_ap_band_dual_mode">
- <item>0</item>
- <item>-1</item>
+ <item>1</item>
+ <item>3</item>
</string-array>
<string-array translatable="false" name="wifi_ap_band_dual_mode_summary">
@@ -482,6 +482,11 @@
<item>1xRTT</item>
<item>IS95B</item>
<item>IS95A</item>
+ <item>GSM</item>
+ <item>TD_SCDMA</item>
+ <item>IWLAN</item>
+ <item>LTE_CA</item>
+ <item>NR</item>
</string-array>
<string-array translatable="false" name="bearer_values">
@@ -517,6 +522,16 @@
<item>5</item>
<!-- Do not translate. -->
<item>4</item>
+ <!-- Do not translate. -->
+ <item>16</item>
+ <!-- Do not translate. -->
+ <item>17</item>
+ <!-- Do not translate. -->
+ <item>18</item>
+ <!-- Do not translate. -->
+ <item>19</item>
+ <!-- Do not translate. -->
+ <item>20</item>
</string-array>
<!-- MVNO Info used in APN editor -->
@@ -1014,8 +1029,25 @@
<item>\?</item>
</string-array>
+ <!-- Summary for magnification adjustment modes for accessibility -->
+ <string-array name="magnification_mode_summaries" translatable="false">
+ <item>@string/accessibility_magnification_area_settings_full_screen_summary</item>
+ <item>@string/accessibility_magnification_area_settings_window_screen_summary</item>
+ <item>@string/accessibility_magnification_area_settings_all_summary</item>
+ </string-array>
+
+ <!-- Values for magnification adjustment modes for accessibility -->
+ <integer-array name="magnification_mode_values" translatable="false">
+ <!-- Full screen -->
+ <item>1</item>
+ <!-- Window screen -->
+ <item>2</item>
+ <!-- Full screen and window screen. -->
+ <item>3</item>
+ </integer-array>
+
<!-- Summary for color space adjustment modes for accessibility -->
- <string-array name="daltonizer_mode_summary" translatable="false">
+ <string-array name="daltonizer_mode_summaries" translatable="false">
<item>@string/daltonizer_mode_deuteranomaly</item>
<item>@string/daltonizer_mode_protanomaly</item>
<item>@string/daltonizer_mode_tritanomaly</item>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index a1cb8fc..3fd77e8 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -146,4 +146,6 @@
<color name="dialog_background">@*android:color/background_device_default_light</color>
<color name="face_intro_outline">#ffdadce0</color>
+
+ <color name="back_gesture_indicator">#4182ef</color>
</resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 41c059c..aca64fb 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -216,8 +216,8 @@
<dimen name="fingerprint_finish_max_size">288dp</dimen>
<!-- Face -->
- <dimen name="face_preview_translate_y">0dp</dimen>
- <dimen name="face_preview_translate_x">0dp</dimen>
+ <item name="face_preview_translate_y" format="float" type="dimen">0</item>
+ <item name="face_preview_translate_x" format="float" type="dimen">0</item>
<item name="face_preview_scale" format="float" type="dimen">1.0</item>
<!-- Confirm device credentials -->
@@ -403,6 +403,8 @@
<!-- System navigation settings illustration height -->
<dimen name="system_navigation_illustration_height">320dp</dimen>
+ <dimen name="back_gesture_indicator_width">60dp</dimen>
+
<!-- Header title size of advanced bluetooth device -->
<dimen name="advanced_bluetooth_header_title_text_size">16sp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 206c704..86708a4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1776,6 +1776,11 @@
<!-- Debugging developer settings: Enable ART verifier for Debuggable Apps [CHAR LIMIT=NONE] -->
<string name="art_verifier_for_debuggable_summary">Allow ART to verify bytecode for debuggable apps</string>
+ <!-- Debugging developer settings: show refresh rate? [CHAR LIMIT=25] -->
+ <string name="show_refresh_rate">Show refresh rate</string>
+ <!-- Debugging developer settings: show refresh rate summary [CHAR LIMIT=50] -->
+ <string name="show_refresh_rate_summary">Show the current display refresh rate</string>
+
<!-- NFC settings -->
<!-- Used in the 1st-level settings screen to turn on NFC -->
<string name="nfc_quick_toggle_title">NFC</string>
@@ -4750,6 +4755,26 @@
<string name="accessibility_captioning_title">Caption preferences</string>
<!-- Title for the accessibility preference screen to enable screen magnification. [CHAR LIMIT=35] -->
<string name="accessibility_screen_magnification_title">Magnification</string>
+ <!-- Title for the accessibility preference screen to edit magnification area. [CHAR LIMIT=35] -->
+ <string name="accessibility_magnification_mode_title">Magnification area</string>
+ <!-- Message for the accessibility preference screen to edit magnification area dialog. [CHAR LIMIT=none] -->
+ <string name="accessibility_magnification_area_settings_message">Choose the magnification area(s) you want to use when magnifying the screen</string>
+ <!-- Summary for the accessibility preference screen to edit full screen. [CHAR LIMIT=none] -->
+ <string name="accessibility_magnification_area_settings_full_screen_summary">Full screen</string>
+ <!-- Summary for the accessibility preference screen to edit window screen. [CHAR LIMIT=none] -->
+ <string name="accessibility_magnification_area_settings_window_screen_summary">Part of screen</string>
+ <!-- Summary for the accessibility preference screen to edit entire screen. [CHAR LIMIT=none] -->
+ <string name="accessibility_magnification_area_settings_all_summary">Full screen & part of screen</string>
+ <!-- Message for the accessibility preference screen to edit entire screen. [CHAR LIMIT=none] -->
+ <string name="accessibility_magnification_area_settings_full_screen">Magnify entire screen</string>
+ <!-- Message for the accessibility preference screen to edit part of screen. [CHAR LIMIT=none] -->
+ <string name="accessibility_magnification_area_settings_window_screen">Magnify part of screen</string>
+ <!-- Title for the accessibility preference screen to show move controller. [CHAR LIMIT=35] -->
+ <string name="accessibility_magnification_window_control_switch_title">Show move controller</string>
+ <!-- Summary for the accessibility preference screen to show move controller. [CHAR LIMIT=none] -->
+ <string name="accessibility_magnification_window_control_switch_summary">Show a joystick-like controller to move the magnification area</string>
+ <!-- Title for the accessibility preference screen to enable screen magnification settings. [CHAR LIMIT=35] -->
+ <string name="accessibility_magnification_service_settings_title">Magnify settings</string>
<!-- Title for the accessibility preference screen to enable triple-tap gesture screen magnification. [CHAR LIMIT=35] -->
<string name="accessibility_screen_magnification_gestures_title">Magnify with triple-tap</string>
<!-- Title for the accessibility preference screen to enable navigation bar screen magnification. [CHAR LIMIT=35] -->
@@ -4784,6 +4809,16 @@
<string name="accessibility_tutorial_dialog_message_gesture_settings_with_talkback">To turn an accessibility service on or off, swipe up from the bottom of the screen with three fingers.\n\nTo switch between services, swipe up with three fingers and hold.</string>
<!-- Button for the Accessibility tutorial dialog to dismiss the dialog when user clicks it. [CHAR LIMIT=10] -->
<string name="accessibility_tutorial_dialog_button">Got it</string>
+ <!-- Title for accessibility shortcut preference for accessibility apps. [CHAR LIMIT=40] -->
+ <string name="accessibility_shortcut_title">Use shortcut to open</string>
+ <!-- Title for accessibility shortcut preference for magnification. [CHAR LIMIT=40] -->
+ <string name="accessibility_magnification_shortcut_title">Use shortcut to magnify</string>
+ <!-- Title for Accessibility edit shortcut dialog. [CHAR LIMIT=40] -->
+ <string name="accessibility_shortcut_edit_dialog_title">Shortcut to open <xliff:g id="service" example="Select to Speak">%1$s</xliff:g></string>
+ <!-- Title for Accessibility edit shortcut dialog in Magnify. [CHAR LIMIT=40] -->
+ <string name="accessibility_shortcut_edit_dialog_title_magnification">Shortcut to magnify</string>
+ <!-- Title for Accessibility edit shortcut dialog in Color correction. [CHAR LIMIT=40] -->
+ <string name="accessibility_shortcut_edit_dialog_title_daltonizer">Shortcut to open Color correction</string>
<!-- Title for software shortcut in Accessibility edit shortcut dialog. [CHAR LIMIT=NONE] -->
<string name="accessibility_shortcut_edit_dialog_title_software">Accessibility Button</string>
<!-- Title for software shortcut in gesture mode in Accessibility edit shortcut dialog. [CHAR LIMIT=NONE] -->
@@ -10237,6 +10272,9 @@
<!-- Title for the screen to show all the gesture navigation settings [CHAR LIMIT=80] -->
<string name="gesture_settings_activity_title">Gesture Settings</string>
+ <!-- Keywords for the gesture navigation settings. [CHAR LIMIT=NONE] -->
+ <string name="keywords_gesture_navigation_settings">gesture navigation, back sensitivity, back gesture</string>
+
<!-- Preference and settings suggestion title text for ambient display double tap (phone) [CHAR LIMIT=60]-->
<string name="ambient_display_title" product="default">Double-tap to check phone</string>
<!-- Preference and settings suggestion title text for ambient display double tap (tablet) [CHAR LIMIT=60]-->
@@ -11386,14 +11424,14 @@
<!-- Developer Settings: Footer text for bug report handler picker [CHAR LIMIT=NONE] -->
<string name="bug_report_handler_picker_footer_text">Determines which app handles the Bug Report shortcut on your device.</string>
- <!-- Label of personal profile app for current setting [CHAR LIMIT=NONE] -->
- <string name="personal_profile_app">(Personal)</string>
+ <!-- Subtext of personal profile app for current setting [CHAR LIMIT=NONE] -->
+ <string name="personal_profile_app_subtext">Personal</string>
- <!-- Label of work profile app for current setting [CHAR LIMIT=NONE] -->
- <string name="work_profile_app">(Work)</string>
+ <!-- Subtext of work profile app for current setting [CHAR LIMIT=NONE] -->
+ <string name="work_profile_app_subtext">Work</string>
- <!-- Title of Shell app for current setting [CHAR LIMIT=NONE] -->
- <string name="shell_app">Android System (Shell)</string>
+ <!-- Subtext of system default app for current setting [CHAR LIMIT=NONE] -->
+ <string name="system_default_app_subtext">System default</string>
<!-- Developer settings: text for the bug report handler selection toast shown if an invalid bug report handler was chosen. [CHAR LIMIT=NONE] -->
<string name="select_invalid_bug_report_handler_toast_text">This choice is no longer valid. Try again.</string>
diff --git a/res/xml/accessibility_magnification_service_settings.xml b/res/xml/accessibility_magnification_service_settings.xml
new file mode 100644
index 0000000..d67fc66
--- /dev/null
+++ b/res/xml/accessibility_magnification_service_settings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:key="magnification_mode_screen"
+ android:persistent="false"
+ android:title="@string/accessibility_magnification_service_settings_title">
+
+ <Preference
+ android:key="magnification_mode"
+ android:persistent="false"
+ android:title="@string/accessibility_magnification_mode_title"
+ settings:controller="com.android.settings.accessibility.MagnificationModePreferenceController" />
+
+ <SwitchPreference
+ android:key="magnification_window_control_switch"
+ android:persistent="false"
+ android:summary="@string/accessibility_magnification_window_control_switch_summary"
+ android:title="@string/accessibility_magnification_window_control_switch_title"
+ settings:controller="com.android.settings.accessibility.MagnificationWindowControlPreferenceController" />
+</PreferenceScreen>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 42ce465..9a4add4 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -230,6 +230,11 @@
android:fragment="com.android.settings.development.compat.PlatformCompatDashboard"
/>
+ <SwitchPreference
+ android:key="show_refresh_rate"
+ android:title="@string/show_refresh_rate"
+ android:summary="@string/show_refresh_rate_summary" />
+
</PreferenceCategory>
<PreferenceCategory
diff --git a/res/xml/gesture_navigation_settings.xml b/res/xml/gesture_navigation_settings.xml
new file mode 100644
index 0000000..2751f88
--- /dev/null
+++ b/res/xml/gesture_navigation_settings.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:key="gesture_navigation_settings_page"
+ android:title="@string/gesture_settings_activity_title"
+ settings:keywords="@string/keywords_gesture_navigation_settings">
+
+ <PreferenceCategory
+ android:key="back_sensitivity_category"
+ android:persistent="false"
+ android:title="@string/back_sensitivity_dialog_title">
+
+ <com.android.settings.gestures.GestureNavigationSeekBarPreference
+ android:key="gesture_left_back_sensitivity"
+ android:title="@string/left_edge"
+ android:max="3"
+ android:selectable="true"/>
+
+ <com.android.settings.gestures.GestureNavigationSeekBarPreference
+ android:key="gesture_right_back_sensitivity"
+ android:title="@string/right_edge"
+ android:max="3"
+ android:selectable="true"/>
+ </PreferenceCategory>
+
+ <com.android.settingslib.widget.FooterPreference
+ android:key="gesture_navigation_settings_footer"
+ android:title="@string/back_sensitivity_dialog_message"
+ android:selectable="false"
+ settings:searchable="false"
+ settings:allowDividerAbove="true"/>
+</PreferenceScreen>
+
diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml
index b7d444b..cd05512 100644
--- a/res/xml/security_settings_face.xml
+++ b/res/xml/security_settings_face.xml
@@ -64,7 +64,11 @@
android:summary="@string/security_settings_face_settings_require_confirmation_details"
app:keywords="@string/keywords_face_unlock"
app:controller="com.android.settings.biometrics.face.FaceSettingsConfirmPreferenceController"/>
+ </PreferenceCategory>
+ <PreferenceCategory
+ android:key="security_settings_face_button_category"
+ android:title="@string/security_settings_face_preference_title">
<com.android.settingslib.widget.LayoutPreference
android:key="security_settings_face_delete_faces_container"
android:selectable="false"
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index c50e200..ffc0412 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -105,9 +105,10 @@
p2pFactoryReset(mContext);
TelephonyManager telephonyManager = (TelephonyManager)
- mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
if (telephonyManager != null) {
- telephonyManager.factoryReset(mSubId);
+ telephonyManager.resetSettings();
}
NetworkPolicyManager policyManager = (NetworkPolicyManager)
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 46992ef..50caf32 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -131,6 +131,7 @@
public static class PhotosStorageActivity extends SettingsActivity {
/* empty */
}
+ public static class GestureNavigationSettingsActivity extends SettingsActivity { /* empty */ }
public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
public static class WifiCallingSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
index 62d6d34..1d87477 100644
--- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
+++ b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
@@ -24,6 +24,7 @@
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
+import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.view.LayoutInflater;
import android.view.View;
@@ -53,13 +54,15 @@
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({
- DialogType.EDIT_SHORTCUT_GENERIC,
- DialogType.EDIT_SHORTCUT_MAGNIFICATION,
+ DialogType.EDIT_SHORTCUT_GENERIC,
+ DialogType.EDIT_SHORTCUT_MAGNIFICATION,
+ DialogType.EDIT_MAGNIFICATION_MODE,
})
private @interface DialogType {
int EDIT_SHORTCUT_GENERIC = 0;
int EDIT_SHORTCUT_MAGNIFICATION = 1;
+ int EDIT_MAGNIFICATION_MODE = 2;
}
/**
@@ -96,6 +99,23 @@
return alertDialog;
}
+ /**
+ * Method to show the magnification mode dialog in Magnification.
+ *
+ * @param context A valid context
+ * @param dialogTitle The title of magnify mode dialog
+ * @param listener The listener to determine the action of magnify mode dialog
+ * @return A magnification mode dialog in Magnification
+ */
+ public static AlertDialog showMagnificationModeDialog(Context context,
+ CharSequence dialogTitle, DialogInterface.OnClickListener listener) {
+ final AlertDialog alertDialog = createDialog(context,
+ DialogType.EDIT_MAGNIFICATION_MODE, dialogTitle, listener);
+ alertDialog.show();
+
+ return alertDialog;
+ }
+
private static AlertDialog createDialog(Context context, int dialogType,
CharSequence dialogTitle, DialogInterface.OnClickListener listener) {
@@ -138,6 +158,12 @@
initMagnifyShortcut(context, contentView);
initAdvancedWidget(contentView);
break;
+ case DialogType.EDIT_MAGNIFICATION_MODE:
+ contentView = inflater.inflate(
+ R.layout.accessibility_edit_magnification_mode, null);
+ initMagnifyFullScreen(context, contentView);
+ initMagnifyWindowScreen(context, contentView);
+ break;
default:
throw new IllegalArgumentException();
}
@@ -145,12 +171,37 @@
return contentView;
}
+ private static void initMagnifyFullScreen(Context context, View view) {
+ final View dialogView = view.findViewById(R.id.magnify_full_screen);
+ final String title = context.getString(
+ R.string.accessibility_magnification_area_settings_full_screen);
+ // TODO(b/146019459): Use vector drawable instead of temporal png file to avoid distorted.
+ setupShortcutWidget(dialogView, title, R.drawable.accessibility_magnification_full_screen);
+ }
+
+ private static void initMagnifyWindowScreen(Context context, View view) {
+ final View dialogView = view.findViewById(R.id.magnify_window_screen);
+ final String title = context.getString(
+ R.string.accessibility_magnification_area_settings_window_screen);
+ // TODO(b/146019459): Use vector drawable instead of temporal png file to avoid distorted.
+ setupShortcutWidget(dialogView, title,
+ R.drawable.accessibility_magnification_window_screen);
+ }
+
+ private static void setupShortcutWidget(View view, CharSequence titleText, int imageResId) {
+ setupShortcutWidget(view, titleText, null, imageResId);
+ }
+
private static void setupShortcutWidget(View view, CharSequence titleText,
CharSequence summaryText, int imageResId) {
final CheckBox checkBox = view.findViewById(R.id.checkbox);
checkBox.setText(titleText);
final TextView summary = view.findViewById(R.id.summary);
- summary.setText(summaryText);
+ if (TextUtils.isEmpty(summaryText)) {
+ summary.setVisibility(View.GONE);
+ } else {
+ summary.setText(summaryText);
+ }
final ImageView image = view.findViewById(R.id.image);
image.setImageResource(imageResId);
}
@@ -170,7 +221,8 @@
final String summary = context.getString(
R.string.accessibility_shortcut_edit_dialog_summary_hardware);
setupShortcutWidget(dialogView, title, summary,
- R.drawable.illustration_accessibility_button);
+ R.drawable.accessibility_shortcut_type_hardware);
+ // TODO(b/142531156): Use vector drawable instead of temporal png file to avoid distorted.
}
private static void initMagnifyShortcut(Context context, View view) {
@@ -180,7 +232,8 @@
final String summary = context.getString(
R.string.accessibility_shortcut_edit_dialog_summary_triple_tap);
setupShortcutWidget(dialogView, title, summary,
- R.drawable.illustration_accessibility_button);
+ R.drawable.accessibility_shortcut_type_triple_tap);
+ // TODO(b/142531156): Use vector drawable instead of temporal png file to avoid distorted.
}
private static void initAdvancedWidget(View view) {
@@ -213,8 +266,9 @@
private static int retrieveImageResId(Context context) {
return isGestureNavigateEnabled(context)
- ? R.drawable.illustration_accessibility_button
- : R.drawable.illustration_accessibility_button;
+ ? R.drawable.accessibility_shortcut_type_software_gesture
+ : R.drawable.accessibility_shortcut_type_software;
+ // TODO(b/142531156): Use vector drawable instead of temporal png file to avoid distorted.
}
private static SpannableString getSummaryStringWithIcon(Context context, int lineHeight) {
diff --git a/src/com/android/settings/accessibility/DaltonizerPreferenceController.java b/src/com/android/settings/accessibility/DaltonizerPreferenceController.java
index e026313..2922b76 100644
--- a/src/com/android/settings/accessibility/DaltonizerPreferenceController.java
+++ b/src/com/android/settings/accessibility/DaltonizerPreferenceController.java
@@ -42,15 +42,15 @@
@Override
public CharSequence getSummary() {
- final String[] daltonizerSummarys = mContext.getResources().getStringArray(
- R.array.daltonizer_mode_summary);
+ final String[] daltonizerSummaries = mContext.getResources().getStringArray(
+ R.array.daltonizer_mode_summaries);
final int[] daltonizerValues = mContext.getResources().getIntArray(
R.array.daltonizer_type_values);
final int timeoutValue =
DaltonizerRadioButtonPreferenceController.getSecureAccessibilityDaltonizerValue(
mContext.getContentResolver(), DALTONIZER_TYPE);
final int idx = Ints.indexOf(daltonizerValues, timeoutValue);
- final String serviceSummary = daltonizerSummarys[idx == -1 ? 0 : idx];
+ final String serviceSummary = daltonizerSummaries[idx == -1 ? 0 : idx];
final CharSequence serviceState = AccessibilityUtil.getSummary(mContext,
DALTONIZER_ENABLED);
diff --git a/src/com/android/settings/accessibility/MagnificationModePreferenceController.java b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java
new file mode 100644
index 0000000..b45ad88
--- /dev/null
+++ b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+
+/** Controller that shows the magnification area mode summary. */
+public class MagnificationModePreferenceController extends BasePreferenceController {
+
+ public MagnificationModePreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+
+ @Override
+ public CharSequence getSummary() {
+ return MagnificationSettingsFragment.getMagnificationCapabilitiesSummary(
+ mContext);
+ }
+}
diff --git a/src/com/android/settings/accessibility/MagnificationSettingsFragment.java b/src/com/android/settings/accessibility/MagnificationSettingsFragment.java
new file mode 100644
index 0000000..0e766b4
--- /dev/null
+++ b/src/com/android/settings/accessibility/MagnificationSettingsFragment.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.View;
+import android.widget.CheckBox;
+
+import androidx.annotation.IntDef;
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+import com.google.common.primitives.Ints;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Settings page for magnification. */
+@SearchIndexable
+public class MagnificationSettingsFragment extends DashboardFragment {
+
+ private static final String TAG = "MagnificationSettingsFragment";
+ private static final String PREF_KEY_MODE = "magnification_mode";
+ // TODO(b/146019459): Use magnification_capability.
+ private static final String KEY_CAPABILITY = Settings.System.MASTER_MONO;
+ private static final int DIALOG_MAGNIFICATION_CAPABILITY = 1;
+ private static final String EXTRA_CAPABILITY = "capability";
+ private Preference mModePreference;
+ private int mCapabilities = MagnifyMode.NONE;
+ private CheckBox mMagnifyFullScreenCheckBox;
+ private CheckBox mMagnifyWindowCheckBox;
+
+ static String getMagnificationCapabilitiesSummary(Context context) {
+ final String[] magnificationModeSummaries = context.getResources().getStringArray(
+ R.array.magnification_mode_summaries);
+ final int[] magnificationModeValues = context.getResources().getIntArray(
+ R.array.magnification_mode_values);
+ final int capabilities = MagnificationSettingsFragment.getMagnificationCapabilities(
+ context);
+
+ final int idx = Ints.indexOf(magnificationModeValues, capabilities);
+ return magnificationModeSummaries[idx == -1 ? 0 : idx];
+ }
+
+ private static int getMagnificationCapabilities(Context context) {
+ return getSecureIntValue(context, KEY_CAPABILITY, MagnifyMode.FULLSCREEN);
+ }
+
+ private static int getSecureIntValue(Context context, String key, int defaultValue) {
+ return Settings.Secure.getIntForUser(
+ context.getContentResolver(),
+ key, defaultValue, context.getContentResolver().getUserId());
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.ACCESSIBILITY_MAGNIFICATION_SETTINGS;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putInt(EXTRA_CAPABILITY, mCapabilities);
+ super.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ if (savedInstanceState != null) {
+ mCapabilities = savedInstanceState.getInt(EXTRA_CAPABILITY, MagnifyMode.NONE);
+ }
+ if (mCapabilities == MagnifyMode.NONE) {
+ mCapabilities = getMagnificationCapabilities(getPrefContext());
+ }
+ }
+
+ @Override
+ public int getDialogMetricsCategory(int dialogId) {
+ switch (dialogId) {
+ case DIALOG_MAGNIFICATION_CAPABILITY:
+ return SettingsEnums.DIALOG_MAGNIFICATION_CAPABILITY;
+ default:
+ return 0;
+ }
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mModePreference = findPreference(PREF_KEY_MODE);
+ mModePreference.setOnPreferenceClickListener(preference -> {
+ mCapabilities = getMagnificationCapabilities(getPrefContext());
+ showDialog(DIALOG_MAGNIFICATION_CAPABILITY);
+ return true;
+ });
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.accessibility_magnification_service_settings;
+ }
+
+ @Override
+ public Dialog onCreateDialog(int dialogId) {
+ if (dialogId == DIALOG_MAGNIFICATION_CAPABILITY) {
+ final String title = getPrefContext().getString(
+ R.string.accessibility_magnification_mode_title);
+ AlertDialog alertDialog = AccessibilityEditDialogUtils
+ .showMagnificationModeDialog(getPrefContext(), title,
+ this::callOnAlertDialogCheckboxClicked);
+ initializeDialogCheckBox(alertDialog);
+ return alertDialog;
+ }
+ throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
+ }
+
+ private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
+ updateCapabilities(true);
+ mModePreference.setSummary(
+ getMagnificationCapabilitiesSummary(getPrefContext()));
+ }
+
+ private void initializeDialogCheckBox(AlertDialog dialog) {
+ final View dialogFullScreenView = dialog.findViewById(R.id.magnify_full_screen);
+ mMagnifyFullScreenCheckBox = dialogFullScreenView.findViewById(R.id.checkbox);
+
+ final View dialogWidowView = dialog.findViewById(R.id.magnify_window_screen);
+ mMagnifyWindowCheckBox = dialogWidowView.findViewById(R.id.checkbox);
+
+ updateAlertDialogCheckState();
+ updateAlertDialogEnableState();
+ }
+
+ private void updateAlertDialogCheckState() {
+ updateCheckStatus(mMagnifyWindowCheckBox, MagnifyMode.WINDOW);
+ updateCheckStatus(mMagnifyFullScreenCheckBox, MagnifyMode.FULLSCREEN);
+
+ }
+
+ private void updateCheckStatus(CheckBox checkBox, int mode) {
+ checkBox.setChecked((mode & mCapabilities) != 0);
+ checkBox.setOnClickListener(v -> {
+ updateCapabilities(false);
+ updateAlertDialogEnableState();
+ });
+ }
+
+ private void updateAlertDialogEnableState() {
+ if (mCapabilities != MagnifyMode.ALL) {
+ disableEnabledMagnificationModePreference();
+ } else {
+ enableAllPreference();
+ }
+ }
+
+ private void enableAllPreference() {
+ mMagnifyFullScreenCheckBox.setEnabled(true);
+ mMagnifyWindowCheckBox.setEnabled(true);
+ }
+
+ private void disableEnabledMagnificationModePreference() {
+ if (!mMagnifyFullScreenCheckBox.isChecked()) {
+ mMagnifyWindowCheckBox.setEnabled(false);
+ } else if (!mMagnifyWindowCheckBox.isChecked()) {
+ mMagnifyFullScreenCheckBox.setEnabled(false);
+ }
+ }
+
+ private void updateCapabilities(boolean saveToDB) {
+ int capabilities = 0;
+ capabilities |=
+ mMagnifyFullScreenCheckBox.isChecked() ? MagnifyMode.FULLSCREEN : 0;
+ capabilities |= mMagnifyWindowCheckBox.isChecked() ? MagnifyMode.WINDOW : 0;
+ mCapabilities = capabilities;
+ if (saveToDB) {
+ setMagnificationCapabilities(capabilities);
+ }
+ }
+
+ private void setSecureIntValue(String key, int value) {
+ Settings.Secure.putIntForUser(getPrefContext().getContentResolver(),
+ key, value, getPrefContext().getContentResolver().getUserId());
+ }
+
+ private void setMagnificationCapabilities(int capabilities) {
+ setSecureIntValue(KEY_CAPABILITY, capabilities);
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ MagnifyMode.NONE,
+ MagnifyMode.FULLSCREEN,
+ MagnifyMode.WINDOW,
+ MagnifyMode.ALL,
+ })
+ private @interface MagnifyMode {
+ int NONE = 0;
+ int FULLSCREEN = 1;
+ int WINDOW = 2;
+ int ALL = 3;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.accessibility_magnification_service_settings);
+}
diff --git a/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceController.java b/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceController.java
new file mode 100644
index 0000000..4badc3f
--- /dev/null
+++ b/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settings.core.TogglePreferenceController;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Controller that shows and updates the magnification window control switch. */
+public class MagnificationWindowControlPreferenceController extends TogglePreferenceController {
+
+ // TODO(b/146019459): Use magnification_window_control_enabled.
+ private static final String KEY_CONTROL = Settings.System.MASTER_MONO;
+
+ public MagnificationWindowControlPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return Settings.System.getIntForUser(mContext.getContentResolver(),
+ KEY_CONTROL, State.OFF, UserHandle.USER_CURRENT) == State.ON;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ return Settings.System.putIntForUser(mContext.getContentResolver(),
+ KEY_CONTROL, isChecked ? State.ON : State.OFF, UserHandle.USER_CURRENT);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface State {
+ int OFF = 0;
+ int ON = 1;
+ }
+}
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index ea293b7..e54446f 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -37,10 +37,15 @@
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.text.TextUtils;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
+import android.widget.CheckBox;
+
+import androidx.preference.PreferenceScreen;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
@@ -57,11 +62,33 @@
private static final int DIALOG_ID_ENABLE_WARNING = 1;
private static final int DIALOG_ID_DISABLE_WARNING = 2;
private static final int DIALOG_ID_LAUNCH_ACCESSIBILITY_TUTORIAL = 3;
+ private static final int DIALOG_ID_EDIT_SHORTCUT = 4;
public static final int ACTIVITY_REQUEST_CONFIRM_CREDENTIAL_FOR_WEAKER_ENCRYPTION = 1;
+ private CharSequence mDialogTitle;
+
private LockPatternUtils mLockPatternUtils;
+ private final DialogInterface.OnClickListener mDialogListener =
+ (DialogInterface dialog, int id) -> {
+ if (id == DialogInterface.BUTTON_POSITIVE) {
+ // TODO(b/142531156): Save the shortcut type preference.
+ }
+ };
+
+ private final View.OnClickListener mSettingButtonListener = (View view) -> showDialog(
+ DIALOG_ID_EDIT_SHORTCUT);
+
+ private final View.OnClickListener mCheckBoxListener = (View view) -> {
+ CheckBox checkBox = (CheckBox) view;
+ if (checkBox.isChecked()) {
+ // TODO(b/142530063): Enable shortcut when checkbox is checked.
+ } else {
+ // TODO(b/142530063): Disable shortcut when checkbox is unchecked.
+ }
+ };
+
private final SettingsContentObserver mSettingsContentObserver =
new SettingsContentObserver(new Handler()) {
@Override
@@ -127,6 +154,13 @@
}
@Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ initShortcutPreference();
+ return super.onCreateView(inflater, container, savedInstanceState);
+ }
+
+ @Override
public void onResume() {
mSettingsContentObserver.register(getContentResolver());
updateSwitchBarToggleSwitch();
@@ -195,6 +229,13 @@
}
break;
}
+ case DIALOG_ID_EDIT_SHORTCUT: {
+ final CharSequence dialogTitle = getActivity().getString(
+ R.string.accessibility_shortcut_edit_dialog_title, mDialogTitle);
+ mDialog = AccessibilityEditDialogUtils.showEditShortcutDialog(getActivity(),
+ dialogTitle, mDialogListener);
+ break;
+ }
default: {
throw new IllegalArgumentException();
}
@@ -204,10 +245,19 @@
@Override
public int getDialogMetricsCategory(int dialogId) {
- if (dialogId == DIALOG_ID_ENABLE_WARNING) {
- return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_ENABLE;
- } else {
- return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_DISABLE;
+ switch (dialogId) {
+ case DIALOG_ID_ENABLE_WARNING:
+ return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_ENABLE;
+ case DIALOG_ID_DISABLE_WARNING:
+ return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_DISABLE;
+ case DIALOG_ID_LAUNCH_ACCESSIBILITY_TUTORIAL:
+ return isGestureNavigateEnabled()
+ ? SettingsEnums.DIALOG_TOGGLE_SCREEN_GESTURE_NAVIGATION
+ : SettingsEnums.DIALOG_TOGGLE_SCREEN_ACCESSIBILITY_BUTTON;
+ case DIALOG_ID_EDIT_SHORTCUT:
+ return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT;
+ default:
+ return 0;
}
}
@@ -220,6 +270,21 @@
switchBar.setSwitchBarText(switchBarText, switchBarText);
}
+ private void initShortcutPreference() {
+ final PreferenceScreen preferenceScreen = getPreferenceScreen();
+ final ShortcutPreference shortcutPreference = new ShortcutPreference(
+ preferenceScreen.getContext(), null);
+ // Put the shortcutPreference before settingsPreference.
+ shortcutPreference.setOrder(-1);
+ shortcutPreference.setTitle(R.string.accessibility_shortcut_title);
+ // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
+ // TODO(b/142530063): Check if gesture mode is on to decide which summary should be shown.
+ // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
+ shortcutPreference.setSettingButtonListener(mSettingButtonListener);
+ shortcutPreference.setCheckBoxListener(mCheckBoxListener);
+ preferenceScreen.addPreference(shortcutPreference);
+ }
+
private void updateSwitchBarToggleSwitch() {
final boolean checked = AccessibilityUtils.getEnabledServicesFromSettings(getActivity())
.contains(mComponentName);
@@ -350,5 +415,9 @@
// Settings html description.
mHtmlDescription = arguments.getCharSequence(AccessibilitySettings.EXTRA_HTML_DESCRIPTION);
+
+ // Get Accessibility service name.
+ mDialogTitle = getAccessibilityServiceInfo().getResolveInfo().loadLabel(
+ getPackageManager());
}
}
diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
index 3cde80a..f093dc7 100644
--- a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
@@ -16,13 +16,21 @@
package com.android.settings.accessibility;
+import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.res.Resources;
+import android.os.Bundle;
import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
import android.widget.Switch;
import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -30,6 +38,7 @@
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.RadioButtonPreference;
import java.util.ArrayList;
import java.util.List;
@@ -42,6 +51,8 @@
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.accessibility_daltonizer_settings);
private static final String ENABLED = Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED;
+ private static final String RADIOPREFERENCE_KEY = "daltonizer_mode_deuteranomaly";
+ private static final int DIALOG_ID_EDIT_SHORTCUT = 1;
private static final List<AbstractPreferenceController> sControllers = new ArrayList<>();
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
@@ -59,6 +70,27 @@
return sControllers;
}
+ private final DialogInterface.OnClickListener mDialogListener =
+ (DialogInterface dialog, int id) -> {
+ if (id == DialogInterface.BUTTON_POSITIVE) {
+ // TODO(b/142531156): Save the shortcut type preference.
+ }
+ };
+
+ private final View.OnClickListener mSettingButtonListener =
+ (View view) -> showDialog(DIALOG_ID_EDIT_SHORTCUT);
+
+ private final View.OnClickListener mCheckBoxListener = (View view) -> {
+ CheckBox checkBox = (CheckBox) view;
+ if (checkBox.isChecked()) {
+ // TODO(b/142530063): Enable shortcut when checkbox is checked.
+ } else {
+ // TODO(b/142530063): Disable shortcut when checkbox is unchecked.
+ }
+ };
+
+ private Dialog mDialog;
+
@Override
public void onCheckedChanged(Preference preference) {
for (AbstractPreferenceController controller : sControllers) {
@@ -67,6 +99,13 @@
}
@Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ initShortcutPreference();
+ return super.onCreateView(inflater, container, savedInstanceState);
+ }
+
+ @Override
public void onResume() {
super.onResume();
for (AbstractPreferenceController controller :
@@ -87,11 +126,31 @@
}
@Override
+ public Dialog onCreateDialog(int dialogId) {
+ if (dialogId == DIALOG_ID_EDIT_SHORTCUT) {
+ final CharSequence dialogTitle = getActivity().getString(
+ R.string.accessibility_shortcut_edit_dialog_title_daltonizer);
+ mDialog = AccessibilityEditDialogUtils.showEditShortcutDialog(getActivity(),
+ dialogTitle, mDialogListener);
+ }
+
+ return mDialog;
+ }
+
+ @Override
public int getMetricsCategory() {
return SettingsEnums.ACCESSIBILITY_TOGGLE_DALTONIZER;
}
@Override
+ public int getDialogMetricsCategory(int dialogId) {
+ if (dialogId == DIALOG_ID_EDIT_SHORTCUT) {
+ return SettingsEnums.DIALOG_DALTONIZER_EDIT_SHORTCUT;
+ }
+ return 0;
+ }
+
+ @Override
public int getHelpResource() {
return R.string.help_url_color_correction;
}
@@ -131,4 +190,20 @@
Settings.Secure.getInt(getContentResolver(), ENABLED, 0) == 1);
mSwitchBar.addOnSwitchChangeListener(this);
}
+
+ private void initShortcutPreference() {
+ final PreferenceScreen preferenceScreen = getPreferenceScreen();
+ final ShortcutPreference shortcutPreference = new ShortcutPreference(
+ preferenceScreen.getContext(), null);
+ final RadioButtonPreference radioButtonPreference = findPreference(RADIOPREFERENCE_KEY);
+ // Put the shortcutPreference before radioButtonPreference.
+ shortcutPreference.setOrder(radioButtonPreference.getOrder() - 1);
+ shortcutPreference.setTitle(R.string.accessibility_shortcut_title);
+ // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
+ // TODO(b/142530063): Check if gesture mode is on to decide which summary should be shown.
+ // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
+ shortcutPreference.setSettingButtonListener(mSettingButtonListener);
+ shortcutPreference.setCheckBoxListener(mCheckBoxListener);
+ preferenceScreen.addPreference(shortcutPreference);
+ }
}
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index 842ec5c..f9016e8 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -22,6 +22,7 @@
import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.res.Resources;
import android.graphics.Point;
import android.media.AudioManager;
@@ -32,8 +33,12 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
+import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.Switch;
@@ -49,8 +54,29 @@
public class ToggleScreenMagnificationPreferenceFragment extends
ToggleFeaturePreferenceFragment implements SwitchBar.OnSwitchChangeListener {
+ private static final String SETTINGS_KEY = "screen_magnification_settings";
private static final int DIALOG_ID_GESTURE_NAVIGATION_TUTORIAL = 1;
private static final int DIALOG_ID_ACCESSIBILITY_BUTTON_TUTORIAL = 2;
+ private static final int DIALOG_ID_EDIT_SHORTCUT = 3;
+
+ private final DialogInterface.OnClickListener mDialogListener =
+ (DialogInterface dialog, int id) -> {
+ if (id == DialogInterface.BUTTON_POSITIVE) {
+ // TODO(b/142531156): Save the shortcut type preference.
+ }
+ };
+
+ private final View.OnClickListener mSettingButtonListener =
+ (View view) -> showDialog(DIALOG_ID_EDIT_SHORTCUT);
+
+ private final View.OnClickListener mCheckBoxListener = (View view) -> {
+ CheckBox checkBox = (CheckBox) view;
+ if (checkBox.isChecked()) {
+ // TODO(b/142530063): Enable shortcut when checkbox is checked.
+ } else {
+ // TODO(b/142530063): Disable shortcut when checkbox is unchecked.
+ }
+ };
private Dialog mDialog;
@@ -145,6 +171,13 @@
mVideoPreference.setPersistent(false);
mVideoPreference.setLayoutResource(R.layout.magnification_video_preference);
+ final Preference settingsPreference = new Preference(getPrefContext());
+ final String SettingsText = getString(R.string.settings_button);
+ settingsPreference.setTitle(SettingsText);
+ settingsPreference.setKey(SETTINGS_KEY);
+ settingsPreference.setFragment(MagnificationSettingsFragment.class.getName());
+ settingsPreference.setPersistent(false);
+
mConfigWarningPreference = new Preference(getPrefContext());
mConfigWarningPreference.setSelectable(false);
mConfigWarningPreference.setPersistent(false);
@@ -154,12 +187,21 @@
final PreferenceScreen preferenceScreen = getPreferenceManager().getPreferenceScreen();
preferenceScreen.setOrderingAsAdded(false);
mVideoPreference.setOrder(0);
+ settingsPreference.setOrder(1);
mConfigWarningPreference.setOrder(2);
preferenceScreen.addPreference(mVideoPreference);
+ preferenceScreen.addPreference(settingsPreference);
preferenceScreen.addPreference(mConfigWarningPreference);
}
@Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ initShortcutPreference();
+ return super.onCreateView(inflater, container, savedInstanceState);
+ }
+
+ @Override
public void onResume() {
super.onResume();
@@ -182,6 +224,12 @@
mDialog = AccessibilityGestureNavigationTutorial
.showAccessibilityButtonTutorialDialog(getActivity());
break;
+ case DIALOG_ID_EDIT_SHORTCUT:
+ final CharSequence dialogTitle = getActivity().getString(
+ R.string.accessibility_shortcut_edit_dialog_title_magnification);
+ mDialog = AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
+ getActivity(), dialogTitle, mDialogListener);
+ break;
default:
throw new IllegalArgumentException();
}
@@ -202,6 +250,8 @@
return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION;
case DIALOG_ID_ACCESSIBILITY_BUTTON_TUTORIAL:
return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_ACCESSIBILITY_BUTTON;
+ case DIALOG_ID_EDIT_SHORTCUT:
+ return SettingsEnums.DIALOG_MAGNIFICATION_EDIT_SHORTCUT;
default:
return 0;
}
@@ -277,6 +327,21 @@
}
}
+ private void initShortcutPreference() {
+ final PreferenceScreen preferenceScreen = getPreferenceScreen();
+ final ShortcutPreference shortcutPreference = new ShortcutPreference(
+ preferenceScreen.getContext(), null);
+ // Put the shortcutPreference before videoPreference.
+ shortcutPreference.setOrder(mVideoPreference.getOrder() - 1);
+ shortcutPreference.setTitle(R.string.accessibility_magnification_shortcut_title);
+ // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
+ // TODO(b/142530063): Check if gesture mode is on to decide which summary should be shown.
+ // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
+ shortcutPreference.setSettingButtonListener(mSettingButtonListener);
+ shortcutPreference.setCheckBoxListener(mCheckBoxListener);
+ preferenceScreen.addPreference(shortcutPreference);
+ }
+
private boolean isGestureNavigateEnabled() {
return getContext().getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode)
diff --git a/src/com/android/settings/accounts/AccountDashboardFragment.java b/src/com/android/settings/accounts/AccountDashboardFragment.java
index 53b5ea3..7b50b46 100644
--- a/src/com/android/settings/accounts/AccountDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDashboardFragment.java
@@ -17,8 +17,13 @@
import static android.provider.Settings.EXTRA_AUTHORITIES;
+import android.accounts.Account;
+import android.accounts.AccountManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
@@ -97,7 +102,26 @@
@Override
public List<SearchIndexableRaw> getDynamicRawDataToIndex(Context context,
boolean enabled) {
- return null;
+ final List<SearchIndexableRaw> indexRaws = new ArrayList<>();
+ final UserManager userManager = (UserManager) context.getSystemService(
+ Context.USER_SERVICE);
+ final List<UserInfo> profiles = userManager.getProfiles(UserHandle.myUserId());
+ for (final UserInfo userInfo : profiles) {
+ if (userInfo.isManagedProfile()) {
+ return indexRaws;
+ }
+ }
+
+ final AccountManager accountManager = AccountManager.get(context);
+ final Account[] accounts = accountManager.getAccounts();
+ for (Account account : accounts) {
+ final SearchIndexableRaw raw = new SearchIndexableRaw(context);
+ raw.key = AccountTypePreference.buildKey(account);
+ raw.title = account.name;
+ indexRaws.add(raw);
+ }
+
+ return indexRaws;
}
};
}
diff --git a/src/com/android/settings/applications/appops/AppOpsState.java b/src/com/android/settings/applications/appops/AppOpsState.java
index fed77ae..cbffe47 100644
--- a/src/com/android/settings/applications/appops/AppOpsState.java
+++ b/src/com/android/settings/applications/appops/AppOpsState.java
@@ -28,7 +28,6 @@
import android.os.Parcelable;
import android.text.format.DateUtils;
import android.util.Log;
-import android.util.Pair;
import android.util.SparseArray;
import com.android.settings.R;
@@ -619,7 +618,7 @@
}
AppOpsManager.OpEntry opEntry = new AppOpsManager.OpEntry(
- permOps.get(k), AppOpsManager.MODE_ALLOWED, new Pair[0]);
+ permOps.get(k), AppOpsManager.MODE_ALLOWED, Collections.emptyMap());
dummyOps.add(opEntry);
addOp(entries, pkgOps, appEntry, opEntry, packageName == null,
packageName == null ? 0 : opToOrder[opEntry.getOp()]);
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 7da89e4..02e42e2 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -34,14 +34,19 @@
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.settings.SettingsEnums;
import android.app.usage.IUsageStatsManager;
+import android.compat.annotation.ChangeId;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
+import android.os.IBinder;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
@@ -69,6 +74,7 @@
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import com.android.internal.compat.IPlatformCompat;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.Settings.GamesStorageActivity;
@@ -172,6 +178,15 @@
private static final int NO_USER_SPECIFIED = -1;
+ /**
+ * Intents with action {@link android.provider.Settings#ACTION_MANAGE_APP_OVERLAY_PERMISSION}
+ * and data URI scheme "package" don't go to the app-specific screen for managing the permission
+ * anymore. Instead, they redirect to this screen for managing all the apps that have requested
+ * such permission.
+ */
+ @ChangeId
+ private static final long CHANGE_RESTRICT_SAW_INTENT = 135920175L;
+
// sort order
@VisibleForTesting
int mSortOrder = R.id.sort_order_alpha;
@@ -275,6 +290,8 @@
} else if (className.equals(OverlaySettingsActivity.class.getName())) {
mListType = LIST_TYPE_OVERLAY;
screenTitle = R.string.system_alert_window_settings;
+
+ reportIfRestrictedSawIntent(intent);
} else if (className.equals(WriteSettingsActivity.class.getName())) {
mListType = LIST_TYPE_WRITE_SETTINGS;
screenTitle = R.string.write_settings;
@@ -334,6 +351,31 @@
}
}
+ private void reportIfRestrictedSawIntent(Intent intent) {
+ try {
+ Uri data = intent.getData();
+ if (data == null || !TextUtils.equals("package", data.getScheme())) {
+ // Not a restricted intent
+ return;
+ }
+ IBinder activityToken = getActivity().getActivityToken();
+ int callingUid = ActivityManager.getService().getLaunchedFromUid(activityToken);
+ if (callingUid == -1) {
+ Log.w(TAG, "Error obtaining calling uid");
+ return;
+ }
+ IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+ ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+ if (platformCompat == null) {
+ Log.w(TAG, "Error obtaining IPlatformCompat service");
+ return;
+ }
+ platformCompat.reportChangeByUid(CHANGE_RESTRICT_SAW_INTENT, callingUid);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error reporting SAW intent restriction", e);
+ }
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index 64ddf4f..61c417c 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -21,6 +21,8 @@
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
import com.android.settings.SetupWizardUtils;
import com.android.settings.biometrics.face.FaceEnrollIntroduction;
@@ -50,6 +52,9 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ Log.d(TAG, "Min strength: " + getIntent()
+ .getIntExtra(Settings.EXTRA_BIOMETRIC_MINIMUM_STRENGTH_REQUIRED, 0));
+
final PackageManager pm = getApplicationContext().getPackageManager();
Intent intent = null;
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java b/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
index 8806712..853ca7c 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
@@ -18,6 +18,7 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
@@ -316,14 +317,19 @@
scaleX = scaleX / smaller;
scaleY = scaleY / smaller;
- // Apply the transformation/scale
- mTextureView.setTranslationX(getResources().getDimension(R.dimen.face_preview_translate_x));
- mTextureView.setTranslationY(getResources().getDimension(R.dimen.face_preview_translate_y));
-
+ final TypedValue tx = new TypedValue();
+ final TypedValue ty = new TypedValue();
final TypedValue scale = new TypedValue();
+ getResources().getValue(R.dimen.face_preview_translate_x, tx, true /* resolveRefs */);
+ getResources().getValue(R.dimen.face_preview_translate_y, ty, true /* resolveRefs */);
getResources().getValue(R.dimen.face_preview_scale, scale, true /* resolveRefs */);
- mTextureView.setScaleX(scaleX * scale.getFloat());
- mTextureView.setScaleY(scaleY * scale.getFloat());
+
+ // Apply the transformation/scale
+ final Matrix transform = new Matrix();
+ mTextureView.getTransform(transform);
+ transform.setScale(scaleX * scale.getFloat(), scaleY * scale.getFloat());
+ transform.postTranslate(tx.getFloat(), ty.getFloat());
+ mTextureView.setTransform(transform);
}
private void closeCamera() {
diff --git a/src/com/android/settings/bugreporthandler/BugReportHandlerPicker.java b/src/com/android/settings/bugreporthandler/BugReportHandlerPicker.java
index 9c2ac9e..1db2b86 100644
--- a/src/com/android/settings/bugreporthandler/BugReportHandlerPicker.java
+++ b/src/com/android/settings/bugreporthandler/BugReportHandlerPicker.java
@@ -164,13 +164,13 @@
private String getDescription(String handlerApp, int handlerUser) {
final Context context = getContext();
if (BugReportHandlerUtil.SHELL_APP_PACKAGE.equals(handlerApp)) {
- return context.getString(R.string.system_default_app);
+ return context.getString(R.string.system_default_app_subtext);
}
final UserHandle managedProfile = Utils.getManagedProfile(mUserManager);
if (managedProfile != null && managedProfile.getIdentifier() == handlerUser) {
- return context.getString(R.string.work_profile_app);
+ return context.getString(R.string.work_profile_app_subtext);
}
- return context.getString(R.string.personal_profile_app);
+ return context.getString(R.string.personal_profile_app_subtext);
}
private static class BugreportHandlerAppInfo extends DefaultAppInfo {
@@ -197,7 +197,7 @@
return null;
}
if (BugReportHandlerUtil.SHELL_APP_PACKAGE.equals(packageItemInfo.packageName)) {
- return mContext.getString(R.string.shell_app);
+ return mContext.getString(com.android.internal.R.string.android_system_label);
}
return super.loadLabel();
}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 01b1598..1e97bdb 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -87,6 +87,7 @@
import com.android.settings.gestures.DoubleTapPowerSettings;
import com.android.settings.gestures.DoubleTapScreenSettings;
import com.android.settings.gestures.DoubleTwistGestureSettings;
+import com.android.settings.gestures.GestureNavigationSettingsFragment;
import com.android.settings.gestures.GlobalActionsPanelSettings;
import com.android.settings.gestures.PickupGestureSettings;
import com.android.settings.gestures.SwipeToNotificationSettings;
@@ -289,7 +290,8 @@
MobileNetworkListFragment.class.getName(),
GlobalActionsPanelSettings.class.getName(),
DarkModeSettingsFragment.class.getName(),
- BugReportHandlerPicker.class.getName()
+ BugReportHandlerPicker.class.getName(),
+ GestureNavigationSettingsFragment.class.getName()
};
public static final String[] SETTINGS_FOR_RESTRICTED = {
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
index 9ae8284..d0187b9 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
@@ -150,7 +150,7 @@
if (bundle != null) {
final int extraTab = bundle.getInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, -1);
if (extraTab != -1) {
- return WORK_TAB;
+ return extraTab;
}
final int userId = bundle.getInt(EXTRA_USER_ID, UserHandle.SYSTEM.getIdentifier());
final boolean isWorkProfile = UserManager.get(activity).isManagedProfile(userId);
diff --git a/src/com/android/settings/development/BugReportHandlerPreferenceController.java b/src/com/android/settings/development/BugReportHandlerPreferenceController.java
index b95d31b..f154537 100644
--- a/src/com/android/settings/development/BugReportHandlerPreferenceController.java
+++ b/src/com/android/settings/development/BugReportHandlerPreferenceController.java
@@ -73,7 +73,7 @@
final String handlerApp = mBugReportHandlerUtil.getCurrentBugReportHandlerAppAndUser(
mContext).first;
if (BugReportHandlerUtil.SHELL_APP_PACKAGE.equals(handlerApp)) {
- return mContext.getString(R.string.shell_app);
+ return mContext.getString(com.android.internal.R.string.android_system_label);
}
ApplicationInfo applicationInfo;
try {
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 9387d52..88f2c50 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -471,6 +471,7 @@
controllers.add(new PointerLocationPreferenceController(context));
controllers.add(new ShowSurfaceUpdatesPreferenceController(context));
controllers.add(new ShowLayoutBoundsPreferenceController(context));
+ controllers.add(new ShowRefreshRatePreferenceController(context));
controllers.add(new RtlLayoutPreferenceController(context));
controllers.add(new WindowAnimationScalePreferenceController(context));
controllers.add(new EmulateDisplayCutoutPreferenceController(context));
diff --git a/src/com/android/settings/development/ShowRefreshRatePreferenceController.java b/src/com/android/settings/development/ShowRefreshRatePreferenceController.java
new file mode 100644
index 0000000..e56268d
--- /dev/null
+++ b/src/com/android/settings/development/ShowRefreshRatePreferenceController.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+/**
+ * Controller class for controlling the refresh rate overlay on SurfaceFlinger
+ */
+public class ShowRefreshRatePreferenceController extends DeveloperOptionsPreferenceController
+ implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+ private static final String SHOW_REFRESH_RATE_KEY = "show_refresh_rate";
+
+ private static final int SETTING_VALUE_QUERY = 2;
+ private static final int SETTING_VALUE_ON = 1;
+ private static final int SETTING_VALUE_OFF = 0;
+
+ @VisibleForTesting
+ static final String SURFACE_FLINGER_SERVICE_KEY = "SurfaceFlinger";
+ @VisibleForTesting
+ static final int SURFACE_FLINGER_CODE = 1034;
+
+ private static final String SURFACE_COMPOSER_INTERFACE_KEY = "android.ui.ISurfaceComposer";
+
+ private final IBinder mSurfaceFlinger;
+
+ public ShowRefreshRatePreferenceController(Context context) {
+ super(context);
+ mSurfaceFlinger = ServiceManager.getService(SURFACE_FLINGER_SERVICE_KEY);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return SHOW_REFRESH_RATE_KEY;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean isEnabled = (Boolean) newValue;
+ writeShowRefreshRateSetting(isEnabled);
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ updateShowRefreshRateSetting();
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ final SwitchPreference preference = (SwitchPreference) mPreference;
+ if (preference.isChecked()) {
+ // Writing false to the preference when the setting is already off will have a
+ // side effect of turning on the preference that we wish to avoid
+ writeShowRefreshRateSetting(false);
+ preference.setChecked(false);
+ }
+ }
+
+ @VisibleForTesting
+ void updateShowRefreshRateSetting() {
+ // magic communication with surface flinger.
+ try {
+ if (mSurfaceFlinger != null) {
+ final Parcel data = Parcel.obtain();
+ final Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(SURFACE_COMPOSER_INTERFACE_KEY);
+ data.writeInt(SETTING_VALUE_QUERY);
+ mSurfaceFlinger.transact(SURFACE_FLINGER_CODE, data, reply, 0 /* flags */);
+ final boolean enabled = reply.readBoolean();
+ ((SwitchPreference) mPreference).setChecked(enabled);
+ reply.recycle();
+ data.recycle();
+ }
+ } catch (RemoteException ex) {
+ // intentional no-op
+ }
+ }
+
+ @VisibleForTesting
+ void writeShowRefreshRateSetting(boolean isEnabled) {
+ try {
+ if (mSurfaceFlinger != null) {
+ final Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(SURFACE_COMPOSER_INTERFACE_KEY);
+ final int showRefreshRate = isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF;
+ data.writeInt(showRefreshRate);
+ mSurfaceFlinger.transact(SURFACE_FLINGER_CODE, data,
+ null /* reply */, 0 /* flags */);
+ data.recycle();
+ }
+ } catch (RemoteException ex) {
+ // intentional no-op
+ }
+ updateShowRefreshRateSetting();
+ }
+}
diff --git a/src/com/android/settings/gestures/BackGestureIndicatorDrawable.java b/src/com/android/settings/gestures/BackGestureIndicatorDrawable.java
new file mode 100644
index 0000000..2d09e6b
--- /dev/null
+++ b/src/com/android/settings/gestures/BackGestureIndicatorDrawable.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import android.animation.TimeAnimator;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+
+/** A drawable to animate the inset back gesture in both edges of the screen */
+public class BackGestureIndicatorDrawable extends Drawable {
+
+ private static final String TAG = "BackGestureIndicatorDrawable";
+
+ private static final int MSG_SET_INDICATOR_WIDTH = 1;
+ private static final int MSG_HIDE_INDICATOR = 3;
+
+ private static final long ANIMATION_DURATION_MS = 200L;
+ private static final long HIDE_DELAY_MS = 700L;
+
+ private static final int ALPHA_MAX = 64;
+
+ private Context mContext;
+
+ private Paint mPaint = new Paint();
+ private boolean mReversed;
+
+ private float mFinalWidth;
+ private float mCurrentWidth;
+ private float mWidthChangePerMs;
+
+ private TimeAnimator mTimeAnimator = new TimeAnimator();
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_SET_INDICATOR_WIDTH:
+ mTimeAnimator.end();
+ mFinalWidth = msg.arg1;
+ mWidthChangePerMs = Math.abs(mCurrentWidth - mFinalWidth)
+ / ANIMATION_DURATION_MS;
+ mTimeAnimator.start();
+ break;
+ case MSG_HIDE_INDICATOR:
+ mCurrentWidth = mFinalWidth;
+ removeMessages(MSG_SET_INDICATOR_WIDTH);
+ sendMessageDelayed(obtainMessage(MSG_SET_INDICATOR_WIDTH, 0, 0), HIDE_DELAY_MS);
+ invalidateSelf();
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ /**
+ * Creates an indicator drawable that responds to back gesture inset size change
+ * @param reversed If false, indicator will expand right. If true, indicator will expand left
+ */
+ public BackGestureIndicatorDrawable(Context context, boolean reversed) {
+ mContext = context;
+ mReversed = reversed;
+
+ // Restart the timer whenever a change is detected, so we can shrink/fade the indicators
+ mTimeAnimator.setTimeListener((TimeAnimator animation, long totalTime, long deltaTime) -> {
+ updateCurrentWidth(totalTime, deltaTime);
+ invalidateSelf();
+ });
+ }
+
+ private void updateCurrentWidth(long totalTime, long deltaTime) {
+ synchronized (mTimeAnimator) {
+ float step = deltaTime * mWidthChangePerMs;
+ if (totalTime >= ANIMATION_DURATION_MS
+ || step >= Math.abs(mFinalWidth - mCurrentWidth)) {
+ mCurrentWidth = mFinalWidth;
+ mTimeAnimator.end();
+ } else {
+ float direction = mCurrentWidth < mFinalWidth ? 1 : -1;
+ mCurrentWidth += direction * step;
+ }
+ }
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+
+ mPaint.setAntiAlias(true);
+ mPaint.setColor(mContext.getResources().getColor(R.color.back_gesture_indicator));
+ mPaint.setAlpha(ALPHA_MAX);
+
+ final int top = 0;
+ final int bottom = canvas.getHeight();
+ final int width = (int) mCurrentWidth;
+
+ Rect rect = new Rect(0, top, width, bottom);
+ if (mReversed) {
+ rect.offset(canvas.getWidth() - width, 0);
+ }
+
+ canvas.drawRect(rect, mPaint);
+ }
+
+ @Override
+ public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
+
+ }
+
+ @Override
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
+
+ }
+
+ @Override
+ public int getOpacity() {
+ return 0;
+ }
+
+ /**
+ * Sets the visible width of the indicator in pixels.
+ */
+ public void setWidth(int width) {
+ if (width == 0) {
+ mHandler.sendEmptyMessage(MSG_HIDE_INDICATOR);
+ } else {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_INDICATOR_WIDTH, width, 0));
+ }
+ }
+
+ @VisibleForTesting
+ public int getWidth() {
+ return (int) mFinalWidth;
+ }
+}
diff --git a/src/com/android/settings/gestures/BackGestureIndicatorView.java b/src/com/android/settings/gestures/BackGestureIndicatorView.java
new file mode 100644
index 0000000..2bb8435
--- /dev/null
+++ b/src/com/android/settings/gestures/BackGestureIndicatorView.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.PixelFormat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.settings.R;
+
+/**
+ * A linear layout containing the left and right location indicators.
+ */
+public class BackGestureIndicatorView extends LinearLayout {
+ private ViewGroup mLayout;
+ private ImageView mLeftIndicator;
+ private ImageView mRightIndicator;
+ private BackGestureIndicatorDrawable mLeftDrawable;
+ private BackGestureIndicatorDrawable mRightDrawable;
+
+ public BackGestureIndicatorView(Context context) {
+ super(context);
+
+ LayoutInflater factory = LayoutInflater.from(context);
+ mLayout = (ViewGroup) factory.inflate(R.layout.back_gesture_indicator_container,
+ this, false);
+
+ if (mLayout == null) {
+ return;
+ }
+
+ addView(mLayout);
+
+ mLeftDrawable = new BackGestureIndicatorDrawable(context, false);
+ mRightDrawable = new BackGestureIndicatorDrawable(context, true);
+
+ mLeftIndicator = mLayout.findViewById(R.id.indicator_left);
+ mRightIndicator = mLayout.findViewById(R.id.indicator_right);
+
+ mLeftIndicator.setImageDrawable(mLeftDrawable);
+ mRightIndicator.setImageDrawable(mRightDrawable);
+
+ TypedArray a = context.obtainStyledAttributes(new int[] {
+ android.R.attr.windowLightNavigationBar,
+ android.R.attr.windowLightStatusBar});
+ if (a.getBoolean(0, false)) {
+ setSystemUiVisibility(
+ getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+ }
+ if (a.getBoolean(1, false)) {
+ setSystemUiVisibility(
+ getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ }
+ a.recycle();
+ }
+
+ public void setIndicatorWidth(int width, boolean leftIndicator) {
+ BackGestureIndicatorDrawable indicator = leftIndicator ? mLeftDrawable : mRightDrawable;
+ indicator.setWidth(width);
+ }
+
+ public WindowManager.LayoutParams getLayoutParams(
+ WindowManager.LayoutParams parentWindowAttributes) {
+ int copiedFlags = (parentWindowAttributes.flags
+ & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_APPLICATION,
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | copiedFlags,
+ PixelFormat.TRANSLUCENT);
+
+ lp.setTitle("BackGestureIndicatorView");
+ lp.token = getContext().getActivityToken();
+ return lp;
+ }
+}
diff --git a/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java b/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java
new file mode 100644
index 0000000..c209c81
--- /dev/null
+++ b/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.WindowManager;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+/**
+ * A fragment to include all the settings related to Gesture Navigation mode.
+ */
+@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
+public class GestureNavigationSettingsFragment extends DashboardFragment {
+
+ public static final String TAG = "GestureNavigationSettingsFragment";
+
+ public static final String GESTURE_NAVIGATION_SETTINGS =
+ "com.android.settings.GESTURE_NAVIGATION_SETTINGS";
+
+ private static final String LEFT_EDGE_SEEKBAR_KEY = "gesture_left_back_sensitivity";
+ private static final String RIGHT_EDGE_SEEKBAR_KEY = "gesture_right_back_sensitivity";
+
+ private WindowManager mWindowManager;
+ private BackGestureIndicatorView mIndicatorView;
+
+ private static final float[] BACK_GESTURE_INSET_SCALES = {0.75f, 1.0f, 1.33f, 1.66f};
+
+ private float mDefaultBackGestureInset;
+
+ public GestureNavigationSettingsFragment() {
+ super();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mIndicatorView = new BackGestureIndicatorView(getActivity());
+ mWindowManager = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
+
+ mDefaultBackGestureInset = getActivity().getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.config_backGestureInset);
+ }
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ super.onCreatePreferences(savedInstanceState, rootKey);
+
+ initSeekBarPreference(LEFT_EDGE_SEEKBAR_KEY);
+ initSeekBarPreference(RIGHT_EDGE_SEEKBAR_KEY);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ mWindowManager.addView(mIndicatorView, mIndicatorView.getLayoutParams(
+ getActivity().getWindow().getAttributes()));
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ mWindowManager.removeView(mIndicatorView);
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.gesture_navigation_settings;
+ }
+
+ @Override
+ public int getHelpResource() {
+ // TODO(b/146001201): Replace with gesture navigation help page when ready.
+ return R.string.help_uri_default;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.SETTINGS_GESTURE_NAV_BACK_SENSITIVITY_DLG;
+ }
+
+ private void initSeekBarPreference(final String key) {
+ final GestureNavigationSeekBarPreference pref = getPreferenceScreen().findPreference(key);
+ pref.setContinuousUpdates(true);
+
+ final String settingsKey = key == LEFT_EDGE_SEEKBAR_KEY
+ ? Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT
+ : Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT;
+ final float initScale = Settings.Secure.getFloat(
+ getContext().getContentResolver(), settingsKey, 1.0f);
+
+ // Find the closest value to initScale
+ float minDistance = Float.MAX_VALUE;
+ int minDistanceIndex = -1;
+ for (int i = 0; i < BACK_GESTURE_INSET_SCALES.length; i++) {
+ float d = Math.abs(BACK_GESTURE_INSET_SCALES[i] - initScale);
+ if (d < minDistance) {
+ minDistance = d;
+ minDistanceIndex = i;
+ }
+ }
+ pref.setProgress(minDistanceIndex);
+
+ pref.setOnPreferenceChangeListener((p, v) -> {
+ final int width = (int) (mDefaultBackGestureInset * BACK_GESTURE_INSET_SCALES[(int) v]);
+ mIndicatorView.setIndicatorWidth(width, key == LEFT_EDGE_SEEKBAR_KEY);
+ return true;
+ });
+
+ pref.setOnPreferenceChangeStopListener((p, v) -> {
+ mIndicatorView.setIndicatorWidth(0, key == LEFT_EDGE_SEEKBAR_KEY);
+ final float scale = BACK_GESTURE_INSET_SCALES[(int) v];
+ Settings.Secure.putFloat(getContext().getContentResolver(), settingsKey, scale);
+ return true;
+ });
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.gesture_navigation_settings);
+}
diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java
index 3c79be3..f5fff1c 100644
--- a/src/com/android/settings/network/AirplaneModePreferenceController.java
+++ b/src/com/android/settings/network/AirplaneModePreferenceController.java
@@ -23,13 +23,13 @@
import android.content.pm.PackageManager;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
+import android.telephony.TelephonyManager;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.settings.AirplaneModeEnabler;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
@@ -77,7 +77,7 @@
// In ECM mode launch ECM app dialog
if (mFragment != null) {
mFragment.startActivityForResult(
- new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
+ new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
REQUEST_CODE_EXIT_ECM);
}
return true;
diff --git a/src/com/android/settings/network/MobileDataContentObserver.java b/src/com/android/settings/network/MobileDataContentObserver.java
index b8a1c8c..15e726f 100644
--- a/src/com/android/settings/network/MobileDataContentObserver.java
+++ b/src/com/android/settings/network/MobileDataContentObserver.java
@@ -33,9 +33,13 @@
super(handler);
}
- public static Uri getObservableUri(int subId) {
+ /**
+ * Return a URI of mobile data(ON vs OFF)
+ */
+ public static Uri getObservableUri(Context context, int subId) {
Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
- if (TelephonyManager.getDefault().getSimCount() != 1) {
+ TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+ if (telephonyManager.getSimCount() != 1) {
uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId);
}
return uri;
@@ -54,7 +58,7 @@
}
public void register(Context context, int subId) {
- final Uri uri = getObservableUri(subId);
+ final Uri uri = getObservableUri(context, subId);
context.getContentResolver().registerContentObserver(uri, false, this);
}
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 7e355c4..6220d45 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -22,10 +22,12 @@
import static com.android.internal.util.CollectionUtils.emptyIfNull;
import android.content.Context;
+import android.os.ParcelUuid;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccSlotInfo;
+import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
@@ -67,6 +69,12 @@
slotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT;
}
+ /**
+ * Get all of the subscriptions which is available to display to the user.
+ *
+ * @param context {@code Context}
+ * @return list of {@code SubscriptionInfo}
+ */
public static List<SubscriptionInfo> getAvailableSubscriptions(Context context) {
if (sAvailableResultsForTesting != null) {
return sAvailableResultsForTesting;
@@ -74,12 +82,12 @@
final SubscriptionManager subMgr = context.getSystemService(SubscriptionManager.class);
final TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
- List<SubscriptionInfo> subscriptions =
+ final List<SubscriptionInfo> subscriptions =
new ArrayList<>(emptyIfNull(subMgr.getSelectableSubscriptionInfoList()));
// Look for inactive but present physical SIMs that are missing from the selectable list.
final List<UiccSlotInfo> missing = new ArrayList<>();
- UiccSlotInfo[] slotsInfo = telMgr.getUiccSlotsInfo();
+ final UiccSlotInfo[] slotsInfo = telMgr.getUiccSlotsInfo();
for (int i = 0; slotsInfo != null && i < slotsInfo.length; i++) {
final UiccSlotInfo slotInfo = slotsInfo[i];
if (isInactiveInsertedPSim(slotInfo)) {
@@ -93,20 +101,164 @@
}
}
}
- if (!missing.isEmpty()) {
- for (SubscriptionInfo info : subMgr.getAllSubscriptionInfoList()) {
- for (UiccSlotInfo slotInfo : missing) {
- if (info.getSimSlotIndex() == slotInfo.getLogicalSlotIdx() &&
- info.getCardString().equals(slotInfo.getCardId())) {
- subscriptions.add(info);
- break;
- }
+ if (missing.isEmpty()) {
+ return subscriptions;
+ }
+ for (SubscriptionInfo info : subMgr.getAllSubscriptionInfoList()) {
+ for (UiccSlotInfo slotInfo : missing) {
+ if (info.getSimSlotIndex() == slotInfo.getLogicalSlotIdx()
+ && info.getCardString().equals(slotInfo.getCardId())) {
+ subscriptions.add(info);
+ break;
}
}
}
return subscriptions;
}
+ /**
+ * Get subscription which is available to be displayed to the user
+ * per subscription id.
+ *
+ * @param context {@code Context}
+ * @param subscriptionManager The ProxySubscriptionManager for accessing subcription
+ * information
+ * @param subId The id of subscription to be retrieved
+ * @return {@code SubscriptionInfo} based on the given subscription id. Null of subscription
+ * is invalid or not allowed to be displayed to the user.
+ */
+ public static SubscriptionInfo getAvailableSubscription(Context context,
+ ProxySubscriptionManager subscriptionManager, int subId) {
+ final SubscriptionInfo subInfo = subscriptionManager.getAccessibleSubscriptionInfo(subId);
+ if (subInfo == null) {
+ return null;
+ }
+
+ final ParcelUuid groupUuid = subInfo.getGroupUuid();
+
+ if (groupUuid != null) {
+ if (isPrimarySubscriptionWithinSameUuid(getUiccSlotsInfo(context), groupUuid,
+ subscriptionManager.getAccessibleSubscriptionsInfo(), subId)) {
+ return subInfo;
+ }
+ return null;
+ }
+
+ if (subInfo.isEmbedded()) {
+ return subInfo;
+ }
+
+ // Look for physical SIM which presented in slots no mater active or not.
+ final UiccSlotInfo[] slotsInfo = getUiccSlotsInfo(context);
+ if (slotsInfo == null) {
+ return null;
+ }
+ for (UiccSlotInfo slotInfo : slotsInfo) {
+ if ((!slotInfo.getIsEuicc())
+ && (slotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT)
+ && (slotInfo.getLogicalSlotIdx() == subInfo.getSimSlotIndex())
+ && TextUtils.equals(slotInfo.getCardId(), subInfo.getCardString())) {
+ return subInfo;
+ }
+ }
+ return null;
+ }
+
+ private static UiccSlotInfo [] getUiccSlotsInfo(Context context) {
+ final TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
+ return telMgr.getUiccSlotsInfo();
+ }
+
+ private static boolean isPrimarySubscriptionWithinSameUuid(UiccSlotInfo[] slotsInfo,
+ ParcelUuid groupUuid, List<SubscriptionInfo> subscriptions, int subId) {
+ // only interested in subscriptions with this group UUID
+ final ArrayList<SubscriptionInfo> physicalSubInfoList =
+ new ArrayList<SubscriptionInfo>();
+ final ArrayList<SubscriptionInfo> nonOpportunisticSubInfoList =
+ new ArrayList<SubscriptionInfo>();
+ final ArrayList<SubscriptionInfo> activeSlotSubInfoList =
+ new ArrayList<SubscriptionInfo>();
+ final ArrayList<SubscriptionInfo> inactiveSlotSubInfoList =
+ new ArrayList<SubscriptionInfo>();
+ for (SubscriptionInfo subInfo : subscriptions) {
+ if (groupUuid.equals(subInfo.getGroupUuid())) {
+ if (!subInfo.isEmbedded()) {
+ physicalSubInfoList.add(subInfo);
+ } else {
+ if (!subInfo.isOpportunistic()) {
+ nonOpportunisticSubInfoList.add(subInfo);
+ }
+ if (subInfo.getSimSlotIndex()
+ != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ activeSlotSubInfoList.add(subInfo);
+ } else {
+ inactiveSlotSubInfoList.add(subInfo);
+ }
+ }
+ }
+ }
+
+ // find any physical SIM which is currently inserted within logical slot
+ // and which is our target subscription
+ if ((slotsInfo != null) && (physicalSubInfoList.size() > 0)) {
+ final SubscriptionInfo subInfo = searchForSubscriptionId(physicalSubInfoList, subId);
+ if (subInfo == null) {
+ return false;
+ }
+ // verify if subscription is inserted within slot
+ for (UiccSlotInfo slotInfo : slotsInfo) {
+ if ((slotInfo != null) && (!slotInfo.getIsEuicc())
+ && (slotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT)
+ && (slotInfo.getLogicalSlotIdx() == subInfo.getSimSlotIndex())
+ && TextUtils.equals(slotInfo.getCardId(), subInfo.getCardString())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // When all of the eSIM profiles are opprtunistic and no physical SIM,
+ // first opportunistic subscriptions with same group UUID can be primary.
+ if (nonOpportunisticSubInfoList.size() <= 0) {
+ if (physicalSubInfoList.size() > 0) {
+ return false;
+ }
+ if (activeSlotSubInfoList.size() > 0) {
+ return (activeSlotSubInfoList.get(0).getSubscriptionId() == subId);
+ }
+ return (inactiveSlotSubInfoList.get(0).getSubscriptionId() == subId);
+ }
+
+ // Allow non-opportunistic + active eSIM subscription as primary
+ int numberOfActiveNonOpportunisticSubs = 0;
+ boolean isTargetNonOpportunistic = false;
+ for (SubscriptionInfo subInfo : nonOpportunisticSubInfoList) {
+ final boolean isTargetSubInfo = (subInfo.getSubscriptionId() == subId);
+ if (subInfo.getSimSlotIndex() != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ if (isTargetSubInfo) {
+ return true;
+ }
+ numberOfActiveNonOpportunisticSubs++;
+ } else {
+ isTargetNonOpportunistic |= isTargetSubInfo;
+ }
+ }
+ if (numberOfActiveNonOpportunisticSubs > 0) {
+ return false;
+ }
+ return isTargetNonOpportunistic;
+ }
+
+ private static SubscriptionInfo searchForSubscriptionId(List<SubscriptionInfo> subInfoList,
+ int subscriptionId) {
+ for (SubscriptionInfo subInfo : subInfoList) {
+ if (subInfo.getSubscriptionId() == subscriptionId) {
+ return subInfo;
+ }
+ }
+ return null;
+ }
+
public static String getDisplayName(SubscriptionInfo info) {
final CharSequence name = info.getDisplayName();
if (name != null) {
diff --git a/src/com/android/settings/network/TetherEnabler.java b/src/com/android/settings/network/TetherEnabler.java
new file mode 100644
index 0000000..9106aa1
--- /dev/null
+++ b/src/com/android/settings/network/TetherEnabler.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
+import static android.net.ConnectivityManager.TETHERING_USB;
+import static android.net.ConnectivityManager.TETHERING_WIFI;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothPan;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.text.TextUtils;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.PreferenceManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.datausage.DataSaverBackend;
+import com.android.settings.widget.SwitchWidgetController;
+
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * TetherEnabler is a helper to manage Tethering switch on/off state. It turns on/off
+ * different types of tethering based on stored values in {@link SharedPreferences} and ensures
+ * tethering state updated by data saver state.
+ */
+
+public final class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListener,
+ DataSaverBackend.Listener, LifecycleObserver {
+ @VisibleForTesting
+ static final String WIFI_TETHER_KEY = "enable_wifi_tethering";
+ @VisibleForTesting
+ static final String USB_TETHER_KEY = "enable_usb_tethering";
+ @VisibleForTesting
+ static final String BLUETOOTH_TETHER_KEY = "enable_bluetooth_tethering";
+
+ private final SwitchWidgetController mSwitchWidgetController;
+ private final WifiManager mWifiManager;
+ private final ConnectivityManager mConnectivityManager;
+
+ private final DataSaverBackend mDataSaverBackend;
+ private boolean mDataSaverEnabled;
+
+ private final Context mContext;
+
+ @VisibleForTesting
+ final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =
+ new ConnectivityManager.OnStartTetheringCallback() {
+ @Override
+ public void onTetheringFailed() {
+ super.onTetheringFailed();
+ mSwitchWidgetController.setChecked(false);
+ setSwitchWidgetEnabled(true);
+ }
+ };
+ private final AtomicReference<BluetoothPan> mBluetoothPan;
+ private final SharedPreferences mSharedPreferences;
+ private boolean mBluetoothEnableForTether;
+ private final BluetoothAdapter mBluetoothAdapter;
+
+ TetherEnabler(Context context, SwitchWidgetController switchWidgetController,
+ AtomicReference<BluetoothPan> bluetoothPan) {
+ mContext = context;
+ mSwitchWidgetController = switchWidgetController;
+ mDataSaverBackend = new DataSaverBackend(context);
+ mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
+ mConnectivityManager =
+ (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ mBluetoothPan = bluetoothPan;
+ mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled();
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_START)
+ public void onStart() {
+ mDataSaverBackend.addListener(this);
+ mSwitchWidgetController.setListener(this);
+ mSwitchWidgetController.startListening();
+ IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
+ filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ mContext.registerReceiver(mTetherChangeReceiver, filter);
+ mSwitchWidgetController.setChecked(isTethering());
+ setSwitchWidgetEnabled(true);
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+ public void onStop() {
+ mDataSaverBackend.remListener(this);
+ mSwitchWidgetController.stopListening();
+ mContext.unregisterReceiver(mTetherChangeReceiver);
+ }
+
+ private void setSwitchWidgetEnabled(boolean enabled) {
+ mSwitchWidgetController.setEnabled(enabled && !mDataSaverEnabled);
+ }
+
+ private boolean isTethering() {
+ String[] tethered = mConnectivityManager.getTetheredIfaces();
+ return isTethering(tethered);
+ }
+
+ private boolean isTethering(String[] tethered) {
+ if (tethered != null && tethered.length != 0) {
+ return true;
+ }
+
+ final BluetoothPan pan = mBluetoothPan.get();
+
+ return pan != null && pan.isTetheringOn();
+ }
+
+ @Override
+ public boolean onSwitchToggled(boolean isChecked) {
+ if (isChecked) {
+ startTether();
+ } else {
+ stopTether();
+ }
+ return true;
+ }
+
+ @VisibleForTesting
+ void stopTether() {
+ setSwitchWidgetEnabled(false);
+
+ // Wi-Fi tether is selected by default
+ if (mSharedPreferences.getBoolean(WIFI_TETHER_KEY, true)) {
+ mConnectivityManager.stopTethering(TETHERING_WIFI);
+ }
+
+ // USB tether is not selected by default
+ if (mSharedPreferences.getBoolean(USB_TETHER_KEY, false)) {
+ mConnectivityManager.stopTethering(TETHERING_USB);
+ }
+
+ // Bluetooth tether is not selected by default
+ if (mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)) {
+ mConnectivityManager.stopTethering(TETHERING_BLUETOOTH);
+ }
+ }
+
+ @VisibleForTesting
+ void startTether() {
+ setSwitchWidgetEnabled(false);
+
+ // Wi-Fi tether is selected by default
+ if (mSharedPreferences.getBoolean(WIFI_TETHER_KEY, true)) {
+ startTethering(TETHERING_WIFI);
+ }
+
+ // USB tether is not selected by default
+ if (mSharedPreferences.getBoolean(USB_TETHER_KEY, false)) {
+ startTethering(TETHERING_USB);
+ }
+
+ // Bluetooth tether is not selected by default
+ if (mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)) {
+ startTethering(TETHERING_BLUETOOTH);
+ }
+ }
+
+ @VisibleForTesting
+ void startTethering(int choice) {
+ if (choice == TETHERING_BLUETOOTH) {
+ // Turn on Bluetooth first.
+ if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
+ mBluetoothEnableForTether = true;
+ mBluetoothAdapter.enable();
+ return;
+ }
+ } else if (choice == TETHERING_WIFI && mWifiManager.isWifiApEnabled()) {
+ return;
+ }
+
+
+ mConnectivityManager.startTethering(choice, true /* showProvisioningUi */,
+ mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
+ }
+
+ private final BroadcastReceiver mTetherChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (TextUtils.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED, action)) {
+ ArrayList<String> active = intent.getStringArrayListExtra(
+ ConnectivityManager.EXTRA_ACTIVE_TETHER);
+ mSwitchWidgetController.setChecked(
+ isTethering(active.toArray(new String[active.size()])));
+ setSwitchWidgetEnabled(true);
+ } else if (TextUtils.equals(BluetoothAdapter.ACTION_STATE_CHANGED, action)) {
+ if (mBluetoothEnableForTether) {
+ switch (intent
+ .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
+ case BluetoothAdapter.STATE_ON:
+ startTethering(TETHERING_BLUETOOTH);
+ mBluetoothEnableForTether = false;
+ break;
+
+ case BluetoothAdapter.STATE_OFF:
+ case BluetoothAdapter.ERROR:
+ mBluetoothEnableForTether = false;
+ break;
+
+ default:
+ // ignore transition states
+ }
+ }
+ }
+ }
+ };
+
+ @Override
+ public void onDataSaverChanged(boolean isDataSaving) {
+ mDataSaverEnabled = isDataSaving;
+ setSwitchWidgetEnabled(!isDataSaving);
+ }
+
+ @Override
+ public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
+ // we don't care, since we just want to read the value
+ }
+
+ @Override
+ public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
+ // we don't care, since we just want to read the value
+ }
+}
diff --git a/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java b/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java
index 008a3e4..2348f70 100644
--- a/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java
+++ b/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java
@@ -38,6 +38,6 @@
@Override
protected void setDefaultSubscription(int subscriptionId) {
- mManager.setDefaultVoiceSubId(subscriptionId);
+ mManager.setDefaultVoiceSubscriptionId(subscriptionId);
}
}
diff --git a/src/com/android/settings/network/telephony/MobileDataSlice.java b/src/com/android/settings/network/telephony/MobileDataSlice.java
index 152028c..c70ae1a 100644
--- a/src/com/android/settings/network/telephony/MobileDataSlice.java
+++ b/src/com/android/settings/network/telephony/MobileDataSlice.java
@@ -252,7 +252,7 @@
}
public void register(Context context, int subId) {
- final Uri uri = MobileDataContentObserver.getObservableUri(subId);
+ final Uri uri = MobileDataContentObserver.getObservableUri(context, subId);
context.getContentResolver().registerContentObserver(uri, false, this);
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkActivity.java b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
index 9eb9e71..9dd6ddd 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkActivity.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
@@ -35,6 +35,7 @@
import com.android.settings.R;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.network.ProxySubscriptionManager;
+import com.android.settings.network.SubscriptionUtil;
import java.util.List;
@@ -161,8 +162,8 @@
@VisibleForTesting
SubscriptionInfo getSubscription() {
if (mCurSubscriptionId != SUB_ID_NULL) {
- final SubscriptionInfo subInfo =
- mProxySubscriptionMgr.getActiveSubscriptionInfo(mCurSubscriptionId);
+ final SubscriptionInfo subInfo = SubscriptionUtil.getAvailableSubscription(
+ this, mProxySubscriptionMgr, mCurSubscriptionId);
if (subInfo != null) {
return subInfo;
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index 2c3cd3a..90d8d4e 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -34,7 +34,6 @@
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.settings.R;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.datausage.BillingCyclePreferenceController;
@@ -98,7 +97,7 @@
|| TextUtils.equals(key, BUTTON_CDMA_SUBSCRIPTION_KEY)) {
if (mTelephonyManager.getEmergencyCallbackMode()) {
startActivityForResult(
- new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
+ new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
REQUEST_CODE_EXIT_ECM);
mClickedPrefKey = key;
}
diff --git a/src/com/android/settings/password/BiometricFragment.java b/src/com/android/settings/password/BiometricFragment.java
index 9898719..fe0740b 100644
--- a/src/com/android/settings/password/BiometricFragment.java
+++ b/src/com/android/settings/password/BiometricFragment.java
@@ -16,8 +16,6 @@
package com.android.settings.password;
-import android.app.Activity;
-import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.DialogInterface;
import android.hardware.biometrics.BiometricConstants;
@@ -26,16 +24,10 @@
import android.hardware.biometrics.BiometricPrompt.AuthenticationResult;
import android.os.Bundle;
import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
import androidx.annotation.NonNull;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.R;
import com.android.settings.core.InstrumentedFragment;
-import com.android.settings.overlay.FeatureFactory;
import java.util.concurrent.Executor;
@@ -139,7 +131,9 @@
.setSubtitle(mBundle.getString(BiometricPrompt.KEY_SUBTITLE))
.setDescription(mBundle.getString(BiometricPrompt.KEY_DESCRIPTION))
.setConfirmationRequired(
- mBundle.getBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true));
+ mBundle.getBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true))
+ .setDisallowBiometricsIfPolicyExists(mBundle.getBoolean(
+ BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, false));
mBiometricPrompt = builder.build();
mCancellationSignal = new CancellationSignal();
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index bf8c571..912b600 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -25,7 +25,6 @@
import android.app.trust.TrustManager;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
@@ -54,10 +53,11 @@
public static final String TAG = ConfirmDeviceCredentialActivity.class.getSimpleName();
/**
- * If the intent is sent from {@link com.android.systemui.keyguard.WorkLockActivity} then
- * check for device policy management flags.
+ * If the intent is sent from {@link com.android.systemui.keyguard.WorkLockActivityController}
+ * then check for device policy management flags.
*/
- public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY = "from_work_lock_activity";
+ public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY_CONTROLLER =
+ "from_work_lock_activity_controller";
// The normal flow that apps go through
private static final int CREDENTIAL_NORMAL = 1;
@@ -98,7 +98,7 @@
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private Handler mHandler = new Handler(Looper.getMainLooper());
private Context mContext;
- private boolean mFromWorkLockActivity;
+ private boolean mCheckDevicePolicyManager;
private String mTitle;
private String mDetails;
@@ -159,7 +159,8 @@
Intent intent = getIntent();
mContext = this;
- mFromWorkLockActivity = intent.getBooleanExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, false);
+ mCheckDevicePolicyManager = intent
+ .getBooleanExtra(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, false);
mTitle = intent.getStringExtra(KeyguardManager.EXTRA_TITLE);
mDetails = intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION);
String alternateButton = intent.getStringExtra(
@@ -189,6 +190,8 @@
mDetails = bpBundle.getString(BiometricPrompt.KEY_SUBTITLE);
bpBundle.putString(BiometricPrompt.KEY_TITLE, mTitle);
bpBundle.putString(BiometricPrompt.KEY_DESCRIPTION, mDetails);
+ bpBundle.putBoolean(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS,
+ mCheckDevicePolicyManager);
boolean launchedBiometric = false;
boolean launchedCDC = false;
@@ -201,7 +204,7 @@
} else if (isManagedProfile && isInternalActivity()
&& !lockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
mCredentialMode = CREDENTIAL_MANAGED;
- if (mFromWorkLockActivity && isBiometricAllowed(effectiveUserId, mUserId)) {
+ if (isBiometricAllowed(effectiveUserId, mUserId)) {
showBiometricPrompt(bpBundle);
launchedBiometric = true;
} else {
@@ -267,42 +270,9 @@
|| !mUserManager.isUserUnlocked(mUserId);
}
- /**
- * TODO: Pass a list of disabled features to an internal BiometricPrompt API, so we can
- * potentially show different modalities on multi-auth devices.
- *
- * @param effectiveUserId
- * @return false if their exists one biometric on the device which is not disabled by the
- * policy manager.
- */
- private boolean isBiometricDisabledByAdmin(int effectiveUserId) {
- final int disabledFeatures =
- mDevicePolicyManager.getKeyguardDisabledFeatures(null, effectiveUserId);
-
- final PackageManager pm = mContext.getPackageManager();
- if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
- && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) == 0) {
- Log.d(TAG,"Fingerprint enabled & allowed by device policy manager");
- return false;
- }
- if (pm.hasSystemFeature(PackageManager.FEATURE_IRIS)
- && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_IRIS) == 0) {
- Log.d(TAG,"Iris enabled & allowed by device policy manager");
- return false;
- }
- if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)
- && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FACE) == 0) {
- Log.d(TAG,"Face enabled & allowed by device policy manager");
- return false;
- }
-
- return true;
- }
-
private boolean isBiometricAllowed(int effectiveUserId, int realUserId) {
- return !isStrongAuthRequired(effectiveUserId)
- && !isBiometricDisabledByAdmin(effectiveUserId)
- && !mLockPatternUtils.hasPendingEscrowToken(realUserId);
+ return !isStrongAuthRequired(effectiveUserId) && !mLockPatternUtils
+ .hasPendingEscrowToken(realUserId);
}
private void showBiometricPrompt(Bundle bundle) {
@@ -346,7 +316,7 @@
.launchConfirmationActivityWithExternalAndChallenge(
0 /* request code */, null /* title */, mTitle, mDetails,
true /* isExternal */, 0L /* challenge */, mUserId);
- } else if (mCredentialMode == CREDENTIAL_NORMAL){
+ } else if (mCredentialMode == CREDENTIAL_NORMAL) {
launched = mChooseLockSettingsHelper.launchConfirmationActivity(
0 /* request code */, null /* title */,
mTitle, mDetails, false /* returnCredentials */, true /* isExternal */,
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index 59a1768..2208c97 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -215,6 +215,8 @@
searchDestination.putExtra(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key)
.setAction("com.android.settings.SEARCH_RESULT_TRAMPOLINE")
.setComponent(null);
+ searchDestination.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+
return searchDestination;
}
diff --git a/src/com/android/settings/wifi/WifiEntryShell.java b/src/com/android/settings/wifi/WifiEntryShell.java
new file mode 100644
index 0000000..6b6fef8
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiEntryShell.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import android.net.NetworkInfo.DetailedState;
+
+import com.android.wifitrackerlib.WifiEntry;
+
+/**
+ * {@link WifiEntry is working in progess, many methods are not available, this class is to group
+ * all the unavalable {@link AccessPoint} methods & constants.
+ *
+ * TODO(b/143326832): Replace all methods & constants with WifiEntry version when it's available.
+ * TODO(b/143326832): How about AccessPoint#getSettingsSummary(boolean convertSavedAsDisconnected)?
+ */
+public class WifiEntryShell {
+ public WifiEntryShell(){};
+
+ /**
+ * Lower bound on the 2.4 GHz (802.11b/g/n) WLAN channels
+ */
+ public static final int LOWER_FREQ_24GHZ = 2400;
+
+ /**
+ * Upper bound on the 2.4 GHz (802.11b/g/n) WLAN channels
+ */
+ public static final int HIGHER_FREQ_24GHZ = 2500;
+
+ /**
+ * Lower bound on the 5.0 GHz (802.11a/h/j/n/ac) WLAN channels
+ */
+ public static final int LOWER_FREQ_5GHZ = 4900;
+
+ /**
+ * Upper bound on the 5.0 GHz (802.11a/h/j/n/ac) WLAN channels
+ */
+ public static final int HIGHER_FREQ_5GHZ = 5900;
+
+ /**
+ * Mapping of the corresponding {@link WifiConfiguration} field
+ */
+ public static int getNetworkId(WifiEntry wifiEntry) {
+ return 0;
+ }
+
+ /**
+ * Mapping of the corresponding {@link WifiConfiguration} field
+ */
+ public static boolean hiddenSSID(WifiEntry wifiEntry) {
+ return false;
+ }
+
+ /**
+ * Mapping of the corresponding {@link WifiDetailPreferenceController} method
+ */
+ public static boolean canModifyNetwork(WifiEntry wifiEntry) {
+ return false;
+ }
+
+ /**
+ * Mapping of the corresponding {@link AccessPoint} method
+ */
+ public static String getSecurityString(WifiEntry wifiEntry, boolean concise) {
+ return "None";
+ }
+
+ /**
+ * Mapping of the corresponding {@link AccessPoint} method
+ */
+ public static DetailedState getDetailedState(WifiEntry wifiEntry) {
+ return null;
+ }
+
+ // Passpoint methods
+
+ /**
+ * Mapping of the corresponding {@link AccessPoint} method
+ */
+ public static boolean isPasspoint(WifiEntry wifiEntry) {
+ return false;
+ }
+
+ /**
+ * Mapping of the corresponding {@link AccessPoint} method
+ */
+ public static boolean isExpired(WifiEntry wifiEntry) {
+ return false;
+ }
+
+ /**
+ * Mapping of the corresponding {@link AccessPoint} method
+ */
+ public static boolean isPasspointConfigurationR1(WifiEntry wifiEntry) {
+ return false;
+ }
+
+ /**
+ * Mapping of the corresponding {@link AccessPoint} method
+ */
+ public static boolean isPasspointConfigurationOsuProvisioned(WifiEntry wifiEntry) {
+ return false;
+ }
+
+ /**
+ * Mapping of the corresponding {@link AccessPoint} method
+ */
+ public static boolean isOsuProvider(WifiEntry wifiEntry) {
+ return false;
+ }
+
+ /**
+ * Mapping of the corresponding {@link AccessPoint} method
+ */
+ public static String getPasspointFqdn(WifiEntry wifiEntry) {
+ return "Fake passpoint FQDN";
+ }
+}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 5369851..eb02833 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -68,7 +68,6 @@
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.SwitchBarController;
import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
-import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2;
import com.android.settings.wifi.dpp.WifiDppUtils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -952,21 +951,12 @@
? accessPoint.getTitle()
: context.getText(R.string.pref_title_network_details);
- if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_WIFITRACKER2)) {
- new SubSettingLauncher(getContext())
- .setTitleText(title)
- .setDestination(WifiNetworkDetailsFragment2.class.getName())
- .setArguments(pref.getExtras())
- .setSourceMetricsCategory(getMetricsCategory())
- .launch();
- } else {
- new SubSettingLauncher(getContext())
- .setTitleText(title)
- .setDestination(WifiNetworkDetailsFragment.class.getName())
- .setArguments(pref.getExtras())
- .setSourceMetricsCategory(getMetricsCategory())
- .launch();
- }
+ new SubSettingLauncher(getContext())
+ .setTitleText(title)
+ .setDestination(WifiNetworkDetailsFragment.class.getName())
+ .setArguments(pref.getExtras())
+ .setSourceMetricsCategory(getMetricsCategory())
+ .launch();
}
private Network getCurrentWifiNetwork() {
diff --git a/src/com/android/settings/wifi/WifiSettings2.java b/src/com/android/settings/wifi/WifiSettings2.java
index df7950a..ac9374f 100644
--- a/src/com/android/settings/wifi/WifiSettings2.java
+++ b/src/com/android/settings/wifi/WifiSettings2.java
@@ -38,6 +38,7 @@
import android.os.SimpleClock;
import android.os.SystemClock;
import android.provider.Settings;
+import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
@@ -55,12 +56,14 @@
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.SettingsActivity;
+import com.android.settings.core.FeatureFlags;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.datausage.DataUsagePreference;
import com.android.settings.datausage.DataUsageUtils;
import com.android.settings.location.ScanningSettings;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.SwitchBarController;
+import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2;
import com.android.settingslib.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.search.SearchIndexableRaw;
@@ -509,6 +512,14 @@
pref.setKey(connectedEntry.getKey());
pref.refresh();
mConnectedWifiEntryPreferenceCategory.addPreference(pref);
+ pref.setOnPreferenceClickListener(preference -> {
+ if (connectedEntry.canSignIn()) {
+ connectedEntry.signIn();
+ } else {
+ launchNetworkDetailsFragment(pref);
+ }
+ return true;
+ });
}
} else {
mConnectedWifiEntryPreferenceCategory.removeAll();
@@ -554,6 +565,25 @@
setAdditionalSettingsSummaries();
}
+ private void launchNetworkDetailsFragment(LongPressWifiEntryPreference pref) {
+ final WifiEntry wifiEntry = pref.getWifiEntry();
+ final Context context = getContext();
+ final CharSequence title =
+ FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_DATAUSAGE_HEADER)
+ ? wifiEntry.getTitle()
+ : context.getText(R.string.pref_title_network_details);
+
+ final Bundle bundle = new Bundle();
+ bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey());
+
+ new SubSettingLauncher(context)
+ .setTitleText(title)
+ .setDestination(WifiNetworkDetailsFragment2.class.getName())
+ .setArguments(bundle)
+ .setSourceMetricsCategory(getMetricsCategory())
+ .launch();
+ }
+
private LongPressWifiEntryPreference createLongPressWifiEntryPreference(WifiEntry wifiEntry) {
return new LongPressWifiEntryPreference(getPrefContext(), wifiEntry, this);
}
diff --git a/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java b/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java
index 93f73db..80e14dc 100644
--- a/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java
+++ b/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java
@@ -164,7 +164,6 @@
return inflater.inflate(R.layout.wifi_add_app_networks, container, false);
}
- // TODO: Makesure function work correctly after rotate.
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -585,8 +584,7 @@
@Override
public int getMetricsCategory() {
- // TODO(b/144891278): Need to define a new metric for this page, use the WIFI item first.
- return SettingsEnums.WIFI;
+ return SettingsEnums.PANEL_ADD_WIFI_NETWORKS;
}
private void showSaveStatusByState(int status) {
diff --git a/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java b/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java
index de831b7..3a50107 100644
--- a/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java
@@ -25,7 +25,7 @@
import com.android.settings.core.BasePreferenceController;
import com.android.settings.wifi.dpp.WifiDppUtils;
-import com.android.settingslib.wifi.AccessPoint;
+import com.android.wifitrackerlib.WifiEntry;
/**
* {@link BasePreferenceController} that launches Wi-Fi Easy Connect configurator flow
@@ -36,7 +36,7 @@
private static final String KEY_ADD_DEVICE = "add_device_to_network";
- private AccessPoint mAccessPoint;
+ private WifiEntry mWifiEntry;
private WifiManager mWifiManager;
public AddDevicePreferenceController2(Context context) {
@@ -45,18 +45,13 @@
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
- /**
- * Initiate with an {@link AccessPoint}.
- */
- public AddDevicePreferenceController2 init(AccessPoint accessPoint) {
- mAccessPoint = accessPoint;
-
- return this;
+ public void setWifiEntry(WifiEntry wifiEntry) {
+ mWifiEntry = wifiEntry;
}
@Override
public int getAvailabilityStatus() {
- if (WifiDppUtils.isSupportConfiguratorQrCodeScanner(mContext, mAccessPoint)) {
+ if (WifiDppUtils.isSupportConfiguratorQrCodeScanner(mContext, mWifiEntry)) {
return AVAILABLE;
} else {
return CONDITIONALLY_UNAVAILABLE;
@@ -75,7 +70,7 @@
private void launchWifiDppConfiguratorQrCodeScanner() {
final Intent intent = WifiDppUtils.getConfiguratorQrCodeScannerIntentOrNull(mContext,
- mWifiManager, mAccessPoint);
+ mWifiManager, mWifiEntry);
if (intent == null) {
Log.e(TAG, "Launch Wi-Fi QR code scanner with a wrong Wi-Fi network!");
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index 1d6e457..f94ca9d 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -23,10 +23,8 @@
import android.app.Activity;
import android.app.AlertDialog;
import android.app.settings.SettingsEnums;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -41,10 +39,8 @@
import android.net.NetworkRequest;
import android.net.NetworkUtils;
import android.net.RouteInfo;
-import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import android.os.CountDownTimer;
import android.os.Handler;
import android.text.TextUtils;
import android.util.FeatureFlagUtils;
@@ -67,7 +63,7 @@
import com.android.settings.widget.EntityHeaderController;
import com.android.settings.wifi.WifiDialog;
import com.android.settings.wifi.WifiDialog.WifiDialogListener;
-import com.android.settings.wifi.WifiUtils;
+import com.android.settings.wifi.WifiEntryShell;
import com.android.settings.wifi.dpp.WifiDppUtils;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -77,15 +73,18 @@
import com.android.settingslib.core.lifecycle.events.OnResume;
import com.android.settingslib.widget.ActionButtonsPreference;
import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.wifi.AccessPoint;
-import com.android.settingslib.wifi.WifiTracker;
-import com.android.settingslib.wifi.WifiTrackerFactory;
+import com.android.wifitrackerlib.WifiEntry;
+import com.android.wifitrackerlib.WifiEntry.ConnectedInfo;
+import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback;
+import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.ConnectStatus;
+import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.DisconnectStatus;
+import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.ForgetStatus;
+import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.SignInStatus;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
-import java.time.Duration;
import java.util.StringJoiner;
import java.util.stream.Collectors;
@@ -95,7 +94,7 @@
*/
public class WifiDetailPreferenceController2 extends AbstractPreferenceController
implements PreferenceControllerMixin, WifiDialogListener, LifecycleObserver, OnPause,
- OnResume {
+ OnResume, WifiEntryCallback {
private static final String TAG = "WifiDetailsPrefCtrl2";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -133,21 +132,7 @@
@VisibleForTesting
static final String KEY_IPV6_ADDRESSES_PREF = "ipv6_addresses";
- private static final int STATE_NONE = 1;
- private static final int STATE_ENABLE_WIFI = 2;
- private static final int STATE_ENABLE_WIFI_FAILED = 3;
- private static final int STATE_CONNECTING = 4;
- private static final int STATE_CONNECTED = 5;
- private static final int STATE_FAILED = 6;
- private static final int STATE_NOT_IN_RANGE = 7;
- private static final int STATE_DISCONNECTED = 8;
- private static final long TIMEOUT = Duration.ofSeconds(10).toMillis();
-
- // Be static to avoid too much object not be reset.
- @VisibleForTesting
- static CountDownTimer sTimer;
-
- private AccessPoint mAccessPoint;
+ private final WifiEntry mWifiEntry;
private final ConnectivityManager mConnectivityManager;
private final PreferenceFragmentCompat mFragment;
private final Handler mHandler;
@@ -157,16 +142,9 @@
private NetworkCapabilities mNetworkCapabilities;
private int mRssiSignalLevel = -1;
private String[] mSignalStr;
- private WifiConfiguration mWifiConfig;
private WifiInfo mWifiInfo;
private final WifiManager mWifiManager;
- private final WifiTracker mWifiTracker;
private final MetricsFeatureProvider mMetricsFeatureProvider;
- private boolean mIsOutOfRange;
- private boolean mIsEphemeral;
- private boolean mConnected;
- private int mConnectingState;
- private WifiManager.ActionListener mConnectListener;
// UI elements - in order of appearance
private ActionButtonsPreference mButtonsPref;
@@ -189,36 +167,6 @@
WifiDataUsageSummaryPreferenceController mSummaryHeaderController;
private final IconInjector mIconInjector;
- private final IntentFilter mFilter;
-
- // Passpoint information - cache it in case of losing these information after
- // updateAccessPointFromScannedList(). For R2, we should update these data from
- // WifiManager#getPasspointConfigurations() after users manage the passpoint profile.
- private boolean mIsExpired;
- private boolean mIsPasspointConfigurationR1;
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- switch (intent.getAction()) {
- case WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION:
- if (!intent.getBooleanExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED,
- false /* defaultValue */)) {
- // only one network changed
- WifiConfiguration wifiConfiguration = intent
- .getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION);
- if (mAccessPoint.matches(wifiConfiguration)) {
- mWifiConfig = wifiConfiguration;
- }
- }
- // fall through
- case WifiManager.NETWORK_STATE_CHANGED_ACTION:
- case WifiManager.RSSI_CHANGED_ACTION:
- refreshPage();
- break;
- }
- }
- };
private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
.clearCapabilities().addTransportType(TRANSPORT_WIFI).build();
@@ -265,7 +213,8 @@
|| hasCapabilityChanged(nc, NET_CAPABILITY_VALIDATED)
|| hasCapabilityChanged(nc, NET_CAPABILITY_CAPTIVE_PORTAL)
|| hasCapabilityChanged(nc, NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
- mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
+ // TODO(b/143326832): What to do with WifiEntry?
+ // mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
refreshEntityHeader();
}
mNetworkCapabilities = nc;
@@ -277,45 +226,20 @@
@Override
public void onLost(Network network) {
// Ephemeral network not a saved network, leave detail page once disconnected
- if (mIsEphemeral && network.equals(mNetwork)) {
- exitActivity();
+ if (!mWifiEntry.isSaved() && network.equals(mNetwork)) {
+ if (DEBUG) {
+ Log.d(TAG, "OnLost and exit WifiNetworkDetailsPage");
+ }
+ mFragment.getActivity().finish();
}
}
};
- @VisibleForTesting
- final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
- /** Called when the state of Wifi has changed. */
- public void onWifiStateChanged(int state) {
- Log.d(TAG, "onWifiStateChanged(" + state + ")");
- if (mConnectingState == STATE_ENABLE_WIFI && state == WifiManager.WIFI_STATE_ENABLED) {
- updateConnectingState(STATE_CONNECTING);
- } else if (mConnectingState != STATE_NONE && state == WifiManager.WIFI_STATE_DISABLED) {
- // update as disconnected once Wi-Fi disabled since may not received
- // onConnectedChanged for this case.
- updateConnectingState(STATE_DISCONNECTED);
- }
- }
-
- /** Called when the connection state of wifi has changed. */
- public void onConnectedChanged() {
- refreshPage();
- }
-
- /**
- * Called to indicate the list of AccessPoints has been updated and
- * {@link WifiTracker#getAccessPoints()} should be called to get the updated list.
- */
- public void onAccessPointsChanged() {
- refreshPage();
- }
- };
-
/**
* To get an instance of {@link WifiDetailPreferenceController2}
*/
public static WifiDetailPreferenceController2 newInstance(
- AccessPoint accessPoint,
+ WifiEntry wifiEntry,
ConnectivityManager connectivityManager,
Context context,
PreferenceFragmentCompat fragment,
@@ -324,13 +248,13 @@
WifiManager wifiManager,
MetricsFeatureProvider metricsFeatureProvider) {
return new WifiDetailPreferenceController2(
- accessPoint, connectivityManager, context, fragment, handler, lifecycle,
+ wifiEntry, connectivityManager, context, fragment, handler, lifecycle,
wifiManager, metricsFeatureProvider, new IconInjector(context));
}
@VisibleForTesting
/* package */ WifiDetailPreferenceController2(
- AccessPoint accessPoint,
+ WifiEntry wifiEntry,
ConnectivityManager connectivityManager,
Context context,
PreferenceFragmentCompat fragment,
@@ -341,49 +265,18 @@
IconInjector injector) {
super(context);
- mAccessPoint = accessPoint;
+ mWifiEntry = wifiEntry;
+ mWifiEntry.setListener(this);
mConnectivityManager = connectivityManager;
mFragment = fragment;
mHandler = handler;
mSignalStr = context.getResources().getStringArray(R.array.wifi_signal);
- mWifiConfig = accessPoint.getConfig();
mWifiManager = wifiManager;
mMetricsFeatureProvider = metricsFeatureProvider;
mIconInjector = injector;
- mFilter = new IntentFilter();
- mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
- mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
-
mLifecycle = lifecycle;
lifecycle.addObserver(this);
-
- mWifiTracker = WifiTrackerFactory.create(
- mFragment.getActivity(),
- mWifiListener,
- mLifecycle,
- true /*includeSaved*/,
- true /*includeScans*/);
- mConnected = mAccessPoint.isActive();
- // When lost the network connection, WifiInfo/NetworkInfo will be clear. So causes we
- // could not check if the AccessPoint is ephemeral. Need to cache it in first.
- mIsEphemeral = mAccessPoint.isEphemeral();
- mConnectingState = STATE_NONE;
- mConnectListener = new WifiManager.ActionListener() {
- @Override
- public void onSuccess() {
- // Do nothing
- }
-
- @Override
- public void onFailure(int reason) {
- updateConnectingState(STATE_FAILED);
- }
- };
-
- mIsExpired = mAccessPoint.isExpired();
- mIsPasspointConfigurationR1 = mAccessPoint.isPasspointConfigurationR1();
}
@Override
@@ -404,7 +297,8 @@
setupEntityHeader(screen);
mButtonsPref = ((ActionButtonsPreference) screen.findPreference(KEY_BUTTONS_PREF))
- .setButton1Text(R.string.forget)
+ .setButton1Text(!mWifiEntry.isSaved()
+ ? R.string.wifi_disconnect_button_text : R.string.forget)
.setButton1Icon(R.drawable.ic_settings_delete)
.setButton1OnClickListener(view -> forgetNetwork())
.setButton2Text(R.string.wifi_sign_in_button_text)
@@ -418,11 +312,6 @@
.setButton4Icon(R.drawable.ic_qrcode_24dp)
.setButton4OnClickListener(view -> shareNetwork());
- if (isPasspointConfigurationR1Expired()) {
- // Hide Connect button.
- mButtonsPref.setButton3Visible(false);
- }
-
mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
mTxLinkSpeedPref = screen.findPreference(KEY_TX_LINK_SPEED);
mRxLinkSpeedPref = screen.findPreference(KEY_RX_LINK_SPEED);
@@ -439,7 +328,7 @@
mIpv6Category = screen.findPreference(KEY_IPV6_CATEGORY);
mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
- mSecurityPref.setSummary(mAccessPoint.getSecurityString(/* concise */ false));
+ mSecurityPref.setSummary(WifiEntryShell.getSecurityString(mWifiEntry, /* concise */ false));
}
private void setupEntityHeader(PreferenceScreen screen) {
@@ -451,7 +340,8 @@
mDataUsageSummaryPref.setVisible(true);
mSummaryHeaderController =
new WifiDataUsageSummaryPreferenceController(mFragment.getActivity(),
- mLifecycle, (PreferenceFragmentCompat) mFragment, mAccessPoint.getSsid());
+ mLifecycle, (PreferenceFragmentCompat) mFragment,
+ mWifiEntry.getTitle());
return;
}
@@ -464,22 +354,14 @@
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
- mEntityHeaderController.setLabel(mAccessPoint.getTitle());
+ mEntityHeaderController.setLabel(mWifiEntry.getTitle());
}
private void refreshEntityHeader() {
if (usingDataUsageHeader(mContext)) {
mSummaryHeaderController.updateState(mDataUsageSummaryPref);
} else {
- String summary;
- if (isPasspointConfigurationR1Expired()) {
- // Not able to get summary from AccessPoint because we may lost
- // PasspointConfiguration information after updateAccessPointFromScannedList().
- summary = mContext.getResources().getString(
- com.android.settingslib.R.string.wifi_passpoint_expired);
- } else {
- summary = mAccessPoint.getSettingsSummary(true /* convertSavedAsDisconnected */);
- }
+ String summary = mWifiEntry.getSummary();
mEntityHeaderController
.setSummary(summary)
@@ -489,9 +371,19 @@
}
private void updateNetworkInfo() {
- mNetwork = mWifiManager.getCurrentNetwork();
- mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
- mNetworkCapabilities = mConnectivityManager.getNetworkCapabilities(mNetwork);
+ if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
+ mNetwork = mWifiManager.getCurrentNetwork();
+ mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
+ mNetworkCapabilities = mConnectivityManager.getNetworkCapabilities(mNetwork);
+ mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
+ mWifiInfo = mWifiManager.getConnectionInfo();
+ } else {
+ mNetwork = null;
+ mLinkProperties = null;
+ mNetworkCapabilities = null;
+ mNetworkInfo = null;
+ mWifiInfo = null;
+ }
}
@Override
@@ -500,27 +392,16 @@
// NetworkCallback only looks at changes to mNetwork.
updateNetworkInfo();
refreshPage();
- mContext.registerReceiver(mReceiver, mFilter);
mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback,
mHandler);
}
@Override
public void onPause() {
- mNetwork = null;
- mLinkProperties = null;
- mNetworkCapabilities = null;
- mNetworkInfo = null;
- mWifiInfo = null;
- mContext.unregisterReceiver(mReceiver);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
}
private void refreshPage() {
- if (!updateAccessPoint()) {
- return;
- }
-
Log.d(TAG, "Update UI!");
// refresh header
@@ -545,65 +426,11 @@
refreshMacAddress();
}
- @VisibleForTesting
- boolean updateAccessPoint() {
- boolean changed = false;
- // remember mIsOutOfRange as old before updated
- boolean oldState = mIsOutOfRange;
- updateAccessPointFromScannedList();
-
- if (mAccessPoint.isActive()) {
- updateNetworkInfo();
- mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
- mWifiInfo = mWifiManager.getConnectionInfo();
- if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
- // Once connected, can't get mNetwork immediately, return false and wait for
- // next time to update UI. also reset {@code mIsOutOfRange}
- mIsOutOfRange = oldState;
- return false;
- }
- changed |= mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
- }
-
- // signal level changed
- changed |= mRssiSignalLevel != mAccessPoint.getLevel();
- // In/Out of range changed
- changed |= oldState != mIsOutOfRange;
- // connect state changed
- if (mConnected != mAccessPoint.isActive()) {
- mConnected = mAccessPoint.isActive();
- changed = true;
- updateConnectingState(mAccessPoint.isActive() ? STATE_CONNECTED : STATE_DISCONNECTED);
- }
-
- return changed;
- }
-
- private void updateAccessPointFromScannedList() {
- mIsOutOfRange = true;
-
- for (AccessPoint ap : mWifiTracker.getAccessPoints()) {
- if (mAccessPoint.matches(ap)) {
- mAccessPoint = ap;
- mWifiConfig = ap.getConfig();
- mIsOutOfRange = !mAccessPoint.isReachable();
- return;
- }
- }
- }
-
- private void exitActivity() {
- if (DEBUG) {
- Log.d(TAG, "Exiting the WifiNetworkDetailsPage");
- }
- mFragment.getActivity().finish();
- }
-
private void refreshRssiViews() {
- int signalLevel = mAccessPoint.getLevel();
+ int signalLevel = mWifiEntry.getLevel();
// Disappears signal view if not in range. e.g. for saved networks.
- if (mIsOutOfRange) {
+ if (signalLevel == WifiEntry.WIFI_LEVEL_UNREACHABLE) {
mSignalStrengthPref.setVisible(false);
mRssiSignalLevel = -1;
return;
@@ -656,24 +483,26 @@
}
private void refreshFrequency() {
- if (mWifiInfo == null) {
+ final ConnectedInfo connectedInfo = mWifiEntry.getConnectedInfo();
+ if (connectedInfo == null) {
mFrequencyPref.setVisible(false);
return;
}
- final int frequency = mWifiInfo.getFrequency();
+ final int frequency = connectedInfo.frequencyMhz;
String band = null;
- if (frequency >= AccessPoint.LOWER_FREQ_24GHZ
- && frequency < AccessPoint.HIGHER_FREQ_24GHZ) {
+ if (frequency >= WifiEntryShell.LOWER_FREQ_24GHZ
+ && frequency < WifiEntryShell.HIGHER_FREQ_24GHZ) {
band = mContext.getResources().getString(R.string.wifi_band_24ghz);
- } else if (frequency >= AccessPoint.LOWER_FREQ_5GHZ
- && frequency < AccessPoint.HIGHER_FREQ_5GHZ) {
+ } else if (frequency >= WifiEntryShell.LOWER_FREQ_5GHZ
+ && frequency < WifiEntryShell.HIGHER_FREQ_5GHZ) {
band = mContext.getResources().getString(R.string.wifi_band_5ghz);
} else {
- Log.e(TAG, "Unexpected frequency " + frequency);
// Connecting state is unstable, make it disappeared if unexpected
- if (mConnectingState == STATE_CONNECTING) {
+ if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTING) {
mFrequencyPref.setVisible(false);
+ } else {
+ Log.e(TAG, "Unexpected frequency " + frequency);
}
return;
}
@@ -706,9 +535,9 @@
}
private void refreshSsid() {
- if (mAccessPoint.isPasspoint() || mAccessPoint.isOsuProvider()) {
+ if (WifiEntryShell.isPasspoint(mWifiEntry) || WifiEntryShell.isOsuProvider(mWifiEntry)) {
mSsidPref.setVisible(true);
- mSsidPref.setSummary(mAccessPoint.getSsidStr());
+ mSsidPref.setSummary(mWifiEntry.getTitle());
} else {
mSsidPref.setVisible(false);
}
@@ -733,15 +562,8 @@
}
private String getMacAddress() {
- if (mWifiInfo != null) {
- // get MAC address from connected network information
- return mWifiInfo.getMacAddress();
- }
-
- // return randomized MAC address
- if (mWifiConfig != null && mWifiConfig.macRandomizationSetting
- == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
- return mWifiConfig.getRandomizedMacAddress().toString();
+ if (mWifiEntry.isSaved() && mWifiEntry.getPrivacy() == WifiEntry.PRIVACY_RANDOMIZED_MAC) {
+ return mWifiEntry.getMacAddress();
}
// return device MAC address
@@ -764,13 +586,9 @@
}
private void refreshButtons() {
- // Ephemeral network won't be removed permanently, but be putted in blacklist.
- mButtonsPref.setButton1Text(
- mIsEphemeral ? R.string.wifi_disconnect_button_text : R.string.forget);
-
- boolean canForgetNetwork = canForgetNetwork();
+ boolean canForgetNetwork = mWifiEntry.canForget();
boolean canSignIntoNetwork = canSignIntoNetwork();
- boolean canConnectNetwork = canConnectNetwork() && !isPasspointConfigurationR1Expired();
+ boolean canConnectNetwork = mWifiEntry.canConnect();
boolean canShareNetwork = canShareNetwork();
mButtonsPref.setButton1Visible(canForgetNetwork);
@@ -783,18 +601,10 @@
|| canShareNetwork);
}
- private boolean canConnectNetwork() {
- // Display connect button for disconnected AP even not in the range.
- return !mAccessPoint.isActive();
- }
-
- private boolean isPasspointConfigurationR1Expired() {
- return mIsPasspointConfigurationR1 && mIsExpired;
- }
-
private void refreshIpLayerInfo() {
// Hide IP layer info if not a connected network.
- if (!mAccessPoint.isActive() || mNetwork == null || mLinkProperties == null) {
+ if (mWifiEntry.getConnectedState() != WifiEntry.CONNECTED_STATE_CONNECTED
+ || mNetwork == null || mLinkProperties == null) {
mIpAddressPref.setVisible(false);
mSubnetPref.setVisible(false);
mGatewayPref.setVisible(false);
@@ -857,47 +667,36 @@
}
/**
- * Returns whether the network represented by this preference can be forgotten.
- */
- private boolean canForgetNetwork() {
- return (mWifiInfo != null && mWifiInfo.isEphemeral()) || canModifyNetwork()
- || mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig();
- }
-
- /**
* Returns whether the network represented by this preference can be modified.
*/
public boolean canModifyNetwork() {
- return mWifiConfig != null && !WifiUtils.isNetworkLockedDown(mContext, mWifiConfig);
+ return WifiEntryShell.canModifyNetwork(mWifiEntry);
}
/**
* Returns whether the user can sign into the network represented by this preference.
*/
private boolean canSignIntoNetwork() {
- return mAccessPoint.isActive() && WifiUtils.canSignIntoNetwork(mNetworkCapabilities);
+ return mWifiEntry.canSignIn();
}
/**
* Returns whether the user can share the network represented by this preference with QR code.
*/
private boolean canShareNetwork() {
- return mAccessPoint.getConfig() != null
- && WifiDppUtils.isSupportConfiguratorQrCodeGenerator(mContext, mAccessPoint);
+ return mWifiEntry.canShare();
}
/**
* Forgets the wifi network associated with this preference.
*/
private void forgetNetwork() {
- if (mWifiInfo != null && mWifiInfo.isEphemeral()) {
- mWifiManager.disableEphemeralNetwork(mWifiInfo.getSSID());
- } else if (mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig()) {
+ if (WifiEntryShell.isPasspoint(mWifiEntry)) {
// Post a dialog to confirm if user really want to forget the passpoint network.
showConfirmForgetDialog();
return;
- } else if (mWifiConfig != null) {
- mWifiManager.forget(mWifiConfig.networkId, null /* action listener */);
+ } else {
+ mWifiEntry.forget();
}
mMetricsFeatureProvider.action(
@@ -910,10 +709,10 @@
final AlertDialog dialog = new AlertDialog.Builder(mContext)
.setPositiveButton(R.string.forget, ((dialog1, which) -> {
try {
- mWifiManager.removePasspointConfiguration(mAccessPoint.getPasspointFqdn());
+ mWifiEntry.forget();
} catch (RuntimeException e) {
Log.e(TAG, "Failed to remove Passpoint configuration for "
- + mAccessPoint.getPasspointFqdn());
+ + WifiEntryShell.getPasspointFqdn(mWifiEntry));
}
mMetricsFeatureProvider.action(
mFragment.getActivity(), SettingsEnums.ACTION_WIFI_FORGET);
@@ -931,7 +730,7 @@
*/
private void launchWifiDppConfiguratorActivity() {
final Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntentOrNull(mContext,
- mWifiManager, mAccessPoint);
+ mWifiManager, mWifiEntry);
if (intent == null) {
Log.e(TAG, "Launch Wi-Fi DPP QR code generator with a wrong Wi-Fi network!");
@@ -1005,203 +804,95 @@
@VisibleForTesting
void connectNetwork() {
- final Activity activity = mFragment.getActivity();
- // error handling, connected/saved network should have mWifiConfig.
- if (mWifiConfig == null) {
- Toast.makeText(activity,
- R.string.wifi_failed_connect_message,
- Toast.LENGTH_SHORT).show();
- return;
- }
-
- // init state before connect
- mConnectingState = STATE_NONE;
-
- if (mWifiManager.isWifiEnabled()) {
- updateConnectingState(STATE_CONNECTING);
- } else {
- // Enable Wi-Fi automatically to connect AP
- updateConnectingState(STATE_ENABLE_WIFI);
- }
- }
-
- private void updateConnectingState(int state) {
- final Activity activity = mFragment.getActivity();
- Log.d(TAG, "updateConnectingState from " + mConnectingState + " to " + state);
- switch (mConnectingState) {
- case STATE_NONE:
- case STATE_ENABLE_WIFI:
- if (state == STATE_ENABLE_WIFI) {
- Log.d(TAG, "Turn on Wi-Fi automatically!");
- updateConnectedButton(STATE_ENABLE_WIFI);
- Toast.makeText(activity,
- R.string.wifi_turned_on_message,
- Toast.LENGTH_SHORT).show();
- mWifiManager.setWifiEnabled(true);
- // start timer for error handling
- startTimer();
- } else if (state == STATE_CONNECTING) {
- Log.d(TAG, "connecting...");
- updateConnectedButton(STATE_CONNECTING);
- if (mAccessPoint.isPasspoint()) {
- mWifiManager.connect(mWifiConfig, mConnectListener);
- } else {
- mWifiManager.connect(mWifiConfig.networkId, mConnectListener);
- }
- // start timer for error handling since framework didn't call back if failed
- startTimer();
- } else if (state == STATE_ENABLE_WIFI_FAILED) {
- Log.e(TAG, "Wi-Fi failed to enable network!");
- stopTimer();
- // reset state
- state = STATE_NONE;
- Toast.makeText(activity,
- R.string.wifi_failed_connect_message,
- Toast.LENGTH_SHORT).show();
- updateConnectedButton(STATE_ENABLE_WIFI_FAILED);
- }
- // Do not break here for disconnected event.
- case STATE_CONNECTED:
- if (state == STATE_DISCONNECTED) {
- Log.d(TAG, "disconnected");
- // reset state
- state = STATE_NONE;
- updateConnectedButton(STATE_DISCONNECTED);
- refreshPage();
- // clear for getting MAC Address from saved configuration
- mWifiInfo = null;
- }
- break;
- case STATE_CONNECTING:
- if (state == STATE_CONNECTED) {
- Log.d(TAG, "connected");
- stopTimer();
- updateConnectedButton(STATE_CONNECTED);
- Toast.makeText(activity,
- mContext.getString(R.string.wifi_connected_to_message,
- mAccessPoint.getTitle()),
- Toast.LENGTH_SHORT).show();
-
- refreshPage();
- } else if (state == STATE_NOT_IN_RANGE) {
- Log.d(TAG, "AP not in range");
- stopTimer();
- // reset state
- state = STATE_NONE;
- Toast.makeText(activity,
- R.string.wifi_not_in_range_message,
- Toast.LENGTH_SHORT).show();
- updateConnectedButton(STATE_NOT_IN_RANGE);
- } else if (state == STATE_FAILED) {
- Log.d(TAG, "failed");
- stopTimer();
- // reset state
- state = STATE_NONE;
- Toast.makeText(activity,
- R.string.wifi_failed_connect_message,
- Toast.LENGTH_SHORT).show();
- updateConnectedButton(STATE_FAILED);
- }
- break;
- default:
- Log.e(TAG, "Invalid state : " + mConnectingState);
- // don't update invalid state
- return;
- }
-
- mConnectingState = state;
- }
-
- private void updateConnectedButton(int state) {
- switch (state) {
- case STATE_ENABLE_WIFI:
- case STATE_CONNECTING:
- mButtonsPref.setButton3Text(R.string.wifi_connecting)
- .setButton3Enabled(false);
- break;
- case STATE_CONNECTED:
- // init button state and set as invisible
- mButtonsPref.setButton3Text(R.string.wifi_connect)
- .setButton3Icon(R.drawable.ic_settings_wireless)
- .setButton3Enabled(true)
- .setButton3Visible(false);
- break;
- case STATE_DISCONNECTED:
- case STATE_NOT_IN_RANGE:
- case STATE_FAILED:
- case STATE_ENABLE_WIFI_FAILED:
- if (isPasspointConfigurationR1Expired()) {
- // Hide Connect button.
- mButtonsPref.setButton3Visible(false);
- } else {
- mButtonsPref.setButton3Text(R.string.wifi_connect)
- .setButton3Icon(R.drawable.ic_settings_wireless)
- .setButton3Enabled(true)
- .setButton3Visible(true);
- }
- break;
- default:
- Log.e(TAG, "Invalid connect button state : " + state);
- break;
- }
- }
-
- private void startTimer() {
- if (sTimer != null) {
- stopTimer();
- }
-
- sTimer = new CountDownTimer(TIMEOUT, TIMEOUT + 1) {
- @Override
- public void onTick(long millisUntilFinished) {
- // Do nothing
- }
- @Override
- public void onFinish() {
- if (mFragment == null || mFragment.getActivity() == null) {
- Log.d(TAG, "Ignore timeout since activity not exist!");
- return;
- }
- Log.e(TAG, "Timeout for state:" + mConnectingState);
- if (mConnectingState == STATE_ENABLE_WIFI) {
- updateConnectingState(STATE_ENABLE_WIFI_FAILED);
- } else if (mConnectingState == STATE_CONNECTING) {
- updateAccessPointFromScannedList();
- if (mIsOutOfRange) {
- updateConnectingState(STATE_NOT_IN_RANGE);
- } else {
- updateConnectingState(STATE_FAILED);
- }
- }
- }
- };
- sTimer.start();
- }
-
- private void stopTimer() {
- if (sTimer == null) return;
-
- sTimer.cancel();
- sTimer = null;
+ // TODO(b/143326832): What to do with WifiManager#isWifiEnabled() false case?
+ mButtonsPref.setButton3Text(R.string.wifi_connecting).setButton3Enabled(false);
+ mWifiEntry.connect();
}
private void refreshMacTitle() {
- if (mWifiConfig == null) {
+ if (!mWifiEntry.isSaved()) {
return;
}
// For saved Passpoint network, framework doesn't have the field to keep the MAC choice
// persistently, so Passpoint network will always use the default value so far, which is
// randomized MAC address, so don't need to modify title.
- if (mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig()) {
+ if (WifiEntryShell.isPasspoint(mWifiEntry)) {
return;
}
mMacAddressPref.setTitle(
- (mWifiConfig.macRandomizationSetting
- == WifiConfiguration.RANDOMIZATION_PERSISTENT)
+ (mWifiEntry.getPrivacy() == WifiEntry.PRIVACY_RANDOMIZED_MAC)
? R.string.wifi_advanced_randomized_mac_address_title
: R.string.wifi_advanced_device_mac_address_title);
+ }
+ /**
+ * Indicates the state of the WifiEntry has changed and clients may retrieve updates through
+ * the WifiEntry getter methods.
+ */
+ @Override
+ public void onUpdated() {
+ refreshPage();
+ }
+
+ /**
+ * Result of the connect request indicated by the CONNECT_STATUS constants.
+ */
+ @Override
+ public void onConnectResult(@ConnectStatus int status) {
+ if (status == WifiEntryCallback.CONNECT_STATUS_SUCCESS) {
+ Toast.makeText(mContext,
+ mContext.getString(R.string.wifi_connected_to_message, mWifiEntry.getTitle()),
+ Toast.LENGTH_SHORT).show();
+ updateNetworkInfo();
+ refreshPage();
+ } else if (mWifiEntry.getLevel() == WifiEntry.WIFI_LEVEL_UNREACHABLE) {
+ Toast.makeText(mContext,
+ R.string.wifi_not_in_range_message,
+ Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(mContext,
+ R.string.wifi_failed_connect_message,
+ Toast.LENGTH_SHORT).show();
+ }
+ mButtonsPref.setButton3Text(R.string.wifi_connect)
+ .setButton3Icon(R.drawable.ic_settings_wireless)
+ .setButton3Enabled(true)
+ .setButton3Visible(true);
+ }
+
+ /**
+ * Result of the disconnect request indicated by the DISCONNECT_STATUS constants.
+ */
+ @Override
+ public void onDisconnectResult(@DisconnectStatus int status) {
+ if (status != WifiEntryCallback.DISCONNECT_STATUS_SUCCESS) {
+ Log.e(TAG, "Disconnect Wi-Fi network failed");
+ }
+
+ updateNetworkInfo();
+ refreshPage();
+ }
+
+ /**
+ * Result of the forget request indicated by the FORGET_STATUS constants.
+ */
+ @Override
+ public void onForgetResult(@ForgetStatus int status) {
+ if (status != WifiEntryCallback.FORGET_STATUS_SUCCESS) {
+ Log.e(TAG, "Forget Wi-Fi network failed");
+ }
+
+ mMetricsFeatureProvider.action(mFragment.getActivity(), SettingsEnums.ACTION_WIFI_FORGET);
+ mFragment.getActivity().finish();
+ }
+
+ /**
+ * Result of the sign-in request indicated by the SIGNIN_STATUS constants.
+ */
+ @Override
+ public void onSignInResult(@SignInStatus int status) {
+ refreshPage();
}
}
diff --git a/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2.java
index 99967dc..0915152 100644
--- a/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2.java
@@ -18,8 +18,6 @@
import android.app.backup.BackupManager;
import android.content.Context;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.DropDownPreference;
@@ -29,6 +27,7 @@
import com.android.settings.core.BasePreferenceController;
import com.android.settings.wifi.WifiDialog;
import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.wifitrackerlib.WifiEntry;
/**
* {@link AbstractPreferenceController} that controls whether the wifi network is metered or not
@@ -37,14 +36,12 @@
Preference.OnPreferenceChangeListener, WifiDialog.WifiDialogListener {
private static final String KEY_WIFI_METERED = "metered";
- private WifiConfiguration mWifiConfiguration;
- private WifiManager mWifiManager;
+ private WifiEntry mWifiEntry;
private Preference mPreference;
- public WifiMeteredPreferenceController2(Context context, WifiConfiguration wifiConfiguration) {
+ public WifiMeteredPreferenceController2(Context context, WifiEntry wifiEntry) {
super(context, KEY_WIFI_METERED);
- mWifiConfiguration = wifiConfiguration;
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mWifiEntry = wifiEntry;
}
@Override
@@ -62,10 +59,10 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (mWifiConfiguration != null) {
- mWifiConfiguration.meteredOverride = Integer.parseInt((String) newValue);
+ if (mWifiEntry.isSaved()) {
+ mWifiEntry.setMeteredChoice(Integer.parseInt((String) newValue));
}
- mWifiManager.updateNetwork(mWifiConfiguration);
+
// Stage the backup of the SettingsProvider package which backs this up
BackupManager.dataChanged("com.android.providers.settings");
updateSummary((DropDownPreference) preference, getMeteredOverride());
@@ -74,11 +71,11 @@
@VisibleForTesting
int getMeteredOverride() {
- if (mWifiConfiguration != null) {
+ if (mWifiEntry.isSaved()) {
// Wrap the meteredOverride since robolectric cannot recognize it
- return mWifiConfiguration.meteredOverride;
+ return mWifiEntry.getMeteredChoice();
}
- return WifiConfiguration.METERED_OVERRIDE_NONE;
+ return WifiEntry.METERED_CHOICE_AUTO;
}
private void updateSummary(DropDownPreference preference, int meteredOverride) {
@@ -93,16 +90,17 @@
@Override
public void onSubmit(WifiDialog dialog) {
- if (dialog.getController() != null) {
- final WifiConfiguration newConfig = dialog.getController().getConfig();
- if (newConfig == null || mWifiConfiguration == null) {
- return;
- }
-
- if (newConfig.meteredOverride != mWifiConfiguration.meteredOverride) {
- mWifiConfiguration = newConfig;
- onPreferenceChange(mPreference, String.valueOf(newConfig.meteredOverride));
- }
- }
+ // TODO(b/143326832): Create WifiDialog2 and let it work for WifiEntry.
+ //if (dialog.getController() != null) {
+ // final WifiConfiguration newConfig = dialog.getController().getConfig();
+ // if (newConfig == null || mWifiConfiguration == null) {
+ // return;
+ // }
+ //
+ // if (newConfig.meteredOverride != mWifiConfiguration.meteredOverride) {
+ // mWifiConfiguration = newConfig;
+ // onPreferenceChange(mPreference, String.valueOf(newConfig.meteredOverride));
+ // }
+ //}
}
}
diff --git a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
index 5eb4b28..7e4c856 100644
--- a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
+++ b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
@@ -21,45 +21,61 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.NetworkScoreManager;
import android.net.wifi.WifiManager;
-import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
+import android.os.Process;
+import android.os.SimpleClock;
+import android.os.SystemClock;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.wifi.WifiConfigUiBase;
import com.android.settings.wifi.WifiDialog;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.wifi.AccessPoint;
+import com.android.wifitrackerlib.NetworkDetailsTracker;
+import com.android.wifitrackerlib.WifiEntry;
+import java.time.Clock;
+import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
/**
* Detail page for the currently connected wifi network.
*
- * <p>The AccessPoint should be saved to the intent Extras when launching this class via
- * {@link AccessPoint#saveWifiState(Bundle)} in order to properly render this page.
+ * <p>The key of {@link WifiEntry} should be saved to the intent Extras when launching this class
+ * in order to properly render this page.
*/
public class WifiNetworkDetailsFragment2 extends DashboardFragment implements
WifiDialog.WifiDialogListener {
private static final String TAG = "WifiNetworkDetailsFrg2";
- private AccessPoint mAccessPoint;
+ // Key of a Bundle to save/restore the selected WifiEntry
+ public static final String KEY_CHOSEN_WIFIENTRY_KEY = "key_chosen_wifientry_key";
+
+ // Max age of tracked WifiEntries
+ private static final long MAX_SCAN_AGE_MILLIS = 15_000;
+ // Interval between initiating SavedNetworkTracker scans
+ private static final long SCAN_INTERVAL_MILLIS = 10_000;
+
+ private NetworkDetailsTracker mNetworkDetailsTracker;
+ private HandlerThread mWorkerThread;
private WifiDetailPreferenceController2 mWifiDetailPreferenceController2;
private List<WifiDialog.WifiDialogListener> mWifiDialogListeners = new ArrayList<>();
@Override
- public void onAttach(Context context) {
- mAccessPoint = new AccessPoint(context, getArguments());
- super.onAttach(context);
+ public void onDestroy() {
+ mWorkerThread.quit();
+
+ super.onDestroy();
}
@Override
@@ -87,15 +103,15 @@
@Override
public Dialog onCreateDialog(int dialogId) {
- if (getActivity() == null || mWifiDetailPreferenceController2 == null
- || mAccessPoint == null) {
+ if (getActivity() == null || mWifiDetailPreferenceController2 == null) {
return null;
}
- return WifiDialog.createModal(getActivity(), this, mAccessPoint,
- WifiConfigUiBase.MODE_MODIFY);
+ // TODO(b/143326832): Replace it with WifiEntry.
+ return null;
+ //return WifiDialog.createModal(getActivity(), this, mAccessPoint,
+ // WifiConfigUiBase.MODE_MODIFY);
}
-
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem item = menu.add(0, Menu.FIRST, 0, R.string.wifi_modify);
@@ -124,9 +140,11 @@
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
+ setupNetworksDetailTracker();
+ final WifiEntry wifiEntry = mNetworkDetailsTracker.getWifiEntry();
mWifiDetailPreferenceController2 = WifiDetailPreferenceController2.newInstance(
- mAccessPoint,
+ wifiEntry,
cm,
context,
this,
@@ -134,20 +152,20 @@
getSettingsLifecycle(),
context.getSystemService(WifiManager.class),
mMetricsFeatureProvider);
-
controllers.add(mWifiDetailPreferenceController2);
- controllers.add(new AddDevicePreferenceController2(context).init(mAccessPoint));
+
+ final AddDevicePreferenceController2 addDevicePreferenceController2 =
+ new AddDevicePreferenceController2(context);
+ addDevicePreferenceController2.setWifiEntry(wifiEntry);
+ controllers.add(addDevicePreferenceController2);
final WifiMeteredPreferenceController2 meteredPreferenceController2 =
- new WifiMeteredPreferenceController2(context, mAccessPoint.getConfig());
+ new WifiMeteredPreferenceController2(context, wifiEntry);
controllers.add(meteredPreferenceController2);
final WifiPrivacyPreferenceController2 privacyController2 =
new WifiPrivacyPreferenceController2(context);
- privacyController2.setWifiConfiguration(mAccessPoint.getConfig());
- privacyController2.setIsEphemeral(mAccessPoint.isEphemeral());
- privacyController2.setIsPasspoint(
- mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig());
+ privacyController2.setWifiEntry(wifiEntry);
controllers.add(privacyController2);
// Sets callback listener for wifi dialog.
@@ -164,4 +182,35 @@
listener.onSubmit(dialog);
}
}
+
+ private void setupNetworksDetailTracker() {
+ if (mNetworkDetailsTracker != null) {
+ return;
+ }
+
+ final Context context = getContext();
+ mWorkerThread = new HandlerThread(TAG
+ + "{" + Integer.toHexString(System.identityHashCode(this)) + "}",
+ Process.THREAD_PRIORITY_BACKGROUND);
+ mWorkerThread.start();
+ final Clock elapsedRealtimeClock = new SimpleClock(ZoneOffset.UTC) {
+ @Override
+ public long millis() {
+ return SystemClock.elapsedRealtime();
+ }
+ };
+
+ mNetworkDetailsTracker = NetworkDetailsTracker.createNetworkDetailsTracker(
+ getSettingsLifecycle(),
+ context,
+ context.getSystemService(WifiManager.class),
+ context.getSystemService(ConnectivityManager.class),
+ context.getSystemService(NetworkScoreManager.class),
+ new Handler(Looper.getMainLooper()),
+ mWorkerThread.getThreadHandler(),
+ elapsedRealtimeClock,
+ MAX_SCAN_AGE_MILLIS,
+ SCAN_INTERVAL_MILLIS,
+ getArguments().getString(KEY_CHOSEN_WIFIENTRY_KEY));
+ }
}
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
index d85b607..bca4de1 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
@@ -17,8 +17,6 @@
package com.android.settings.wifi.details2;
import android.content.Context;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import androidx.annotation.VisibleForTesting;
@@ -30,6 +28,7 @@
import com.android.settings.core.BasePreferenceController;
import com.android.settings.wifi.WifiDialog;
import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.wifitrackerlib.WifiEntry;
/**
* {@link AbstractPreferenceController} that controls whether the wifi network is mac randomized
@@ -39,28 +38,18 @@
Preference.OnPreferenceChangeListener, WifiDialog.WifiDialogListener {
private static final String KEY_WIFI_PRIVACY = "privacy";
- private WifiConfiguration mWifiConfiguration;
private WifiManager mWifiManager;
- private boolean mIsEphemeral = false;
- private boolean mIsPasspoint = false;
+ private WifiEntry mWifiEntry;
private Preference mPreference;
public WifiPrivacyPreferenceController2(Context context) {
super(context, KEY_WIFI_PRIVACY);
- mWifiConfiguration = null;
+
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
- public void setWifiConfiguration(WifiConfiguration wifiConfiguration) {
- mWifiConfiguration = wifiConfiguration;
- }
-
- public void setIsEphemeral(boolean isEphemeral) {
- mIsEphemeral = isEphemeral;
- }
-
- public void setIsPasspoint(boolean isPasspoint) {
- mIsPasspoint = isPasspoint;
+ public void setWifiEntry(WifiEntry wifiEntry) {
+ mWifiEntry = wifiEntry;
}
@Override
@@ -83,7 +72,7 @@
updateSummary(dropDownPreference, randomizationLevel);
// Makes preference not selectable, when this is a ephemeral network.
- if (mIsEphemeral || mIsPasspoint) {
+ if (!mWifiEntry.canSetPrivacy()) {
preference.setSelectable(false);
dropDownPreference.setSummary(R.string.wifi_privacy_settings_ephemeral_summary);
}
@@ -91,27 +80,26 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (mWifiConfiguration != null) {
- mWifiConfiguration.macRandomizationSetting = Integer.parseInt((String) newValue);
- mWifiManager.updateNetwork(mWifiConfiguration);
+ final int privacy = Integer.parseInt((String) newValue);
+ if (mWifiEntry.isSaved()) {
+ mWifiEntry.setPrivacy(privacy);
// To activate changing, we need to reconnect network. WiFi will auto connect to
// current network after disconnect(). Only needed when this is connected network.
- final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
- if (wifiInfo != null && wifiInfo.getNetworkId() == mWifiConfiguration.networkId) {
- mWifiManager.disconnect();
+ if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
+ mWifiEntry.disconnect();
}
}
- updateSummary((DropDownPreference) preference, Integer.parseInt((String) newValue));
+ updateSummary((DropDownPreference) preference, privacy);
return true;
}
@VisibleForTesting
int getRandomizationValue() {
- if (mWifiConfiguration != null) {
- return mWifiConfiguration.macRandomizationSetting;
+ if (mWifiEntry.isSaved()) {
+ return mWifiEntry.getPrivacy();
}
- return WifiConfiguration.RANDOMIZATION_PERSISTENT;
+ return WifiEntry.PRIVACY_RANDOMIZED_MAC;
}
private static final int PREF_RANDOMIZATION_PERSISTENT = 0;
@@ -124,7 +112,7 @@
* @return index value of preference
*/
public static int translateMacRandomizedValueToPrefValue(int macRandomized) {
- return (macRandomized == WifiConfiguration.RANDOMIZATION_PERSISTENT)
+ return (macRandomized == WifiEntry.PRIVACY_RANDOMIZED_MAC)
? PREF_RANDOMIZATION_PERSISTENT : PREF_RANDOMIZATION_NONE;
}
@@ -136,7 +124,7 @@
*/
public static int translatePrefValueToMacRandomizedValue(int prefMacRandomized) {
return (prefMacRandomized == PREF_RANDOMIZATION_PERSISTENT)
- ? WifiConfiguration.RANDOMIZATION_PERSISTENT : WifiConfiguration.RANDOMIZATION_NONE;
+ ? WifiEntry.PRIVACY_RANDOMIZED_MAC : WifiEntry.PRIVACY_DEVICE_MAC;
}
private void updateSummary(DropDownPreference preference, int macRandomized) {
@@ -147,16 +135,17 @@
@Override
public void onSubmit(WifiDialog dialog) {
- if (dialog.getController() != null) {
- final WifiConfiguration newConfig = dialog.getController().getConfig();
- if (newConfig == null || mWifiConfiguration == null) {
- return;
- }
-
- if (newConfig.macRandomizationSetting != mWifiConfiguration.macRandomizationSetting) {
- mWifiConfiguration = newConfig;
- onPreferenceChange(mPreference, String.valueOf(newConfig.macRandomizationSetting));
- }
- }
+ // TODO(b/143326832): Create WifiDialog2 and let it work for WifiEntry.
+ //if (dialog.getController() != null) {
+ // final WifiConfiguration newConfig = dialog.getController().getConfig();
+ // if (newConfig == null || mWifiConfiguration == null) {
+ // return;
+ // }
+ //
+ // if (newConfig.macRandomizationSetting != mWifiConfiguration.macRandomizationSetting) {
+ // mWifiConfiguration = newConfig;
+ // onPreferenceChange(mPreference, String.valueOf(newConfig.macRandomizationSetting));
+ // }
+ //}
}
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 6e01aef..22180c3 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -32,7 +32,9 @@
import android.text.TextUtils;
import com.android.settings.R;
+import com.android.settings.wifi.WifiEntryShell;
import com.android.settingslib.wifi.AccessPoint;
+import com.android.wifitrackerlib.WifiEntry;
import java.time.Duration;
import java.util.List;
@@ -148,6 +150,24 @@
return wifiConfiguration.preSharedKey;
}
+ private static String getPresharedKey(WifiManager wifiManager, WifiEntry wifiEntry) {
+ final List<WifiConfiguration> privilegedWifiConfigurations =
+ wifiManager.getPrivilegedConfiguredNetworks();
+
+ for (WifiConfiguration privilegedWifiConfiguration : privilegedWifiConfigurations) {
+ if (privilegedWifiConfiguration.networkId == WifiEntryShell.getNetworkId(wifiEntry)) {
+ // WEP uses a shared key hence the AuthAlgorithm.SHARED is used to identify it.
+ if (wifiEntry.getSecurity() == WifiEntry.SECURITY_WEP) {
+ return privilegedWifiConfiguration
+ .wepKeys[privilegedWifiConfiguration.wepTxKeyIndex];
+ } else {
+ return privilegedWifiConfiguration.preSharedKey;
+ }
+ }
+ }
+ return "";
+ }
+
private static String removeFirstAndLastDoubleQuotes(String str) {
if (TextUtils.isEmpty(str)) {
return str;
@@ -179,6 +199,22 @@
WifiQrCode.SECURITY_NO_PASSWORD : WifiQrCode.SECURITY_WEP;
}
+ static String getSecurityString(WifiEntry wifiEntry) {
+ final int security = wifiEntry.getSecurity();
+ switch (security) {
+ case WifiEntry.SECURITY_SAE:
+ return WifiQrCode.SECURITY_SAE;
+ case WifiEntry.SECURITY_PSK:
+ return WifiQrCode.SECURITY_WPA_PSK;
+ case WifiEntry.SECURITY_WEP:
+ return WifiQrCode.SECURITY_WEP;
+ case WifiEntry.SECURITY_OWE:
+ case WifiEntry.SECURITY_NONE:
+ default:
+ return WifiQrCode.SECURITY_NO_PASSWORD;
+ }
+ }
+
/**
* Returns an intent to launch QR code generator. It may return null if the security is not
* supported by QR code generator.
@@ -212,6 +248,37 @@
}
/**
+ * Returns an intent to launch QR code generator. It may return null if the security is not
+ * supported by QR code generator.
+ *
+ * Do not use this method for Wi-Fi hotspot network, use
+ * {@code getHotspotConfiguratorIntentOrNull} instead.
+ *
+ * @param context The context to use for the content resolver
+ * @param wifiManager An instance of {@link WifiManager}
+ * @param wifiEntry An instance of {@link WifiEntry}
+ * @return Intent for launching QR code generator
+ */
+ public static Intent getConfiguratorQrCodeGeneratorIntentOrNull(Context context,
+ WifiManager wifiManager, WifiEntry wifiEntry) {
+ final Intent intent = new Intent(context, WifiDppConfiguratorActivity.class);
+ if (wifiEntry.canShare()) {
+ intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+ } else {
+ return null;
+ }
+
+ setConfiguratorIntentExtra(intent, wifiManager, wifiEntry);
+
+ // For a transition mode Wi-Fi AP, creates a QR code that's compatible with more devices
+ if (wifiEntry.getSecurity() == WifiEntry.SECURITY_PSK_SAE_TRANSITION) {
+ intent.putExtra(EXTRA_WIFI_SECURITY, WifiQrCode.SECURITY_WPA_PSK);
+ }
+
+ return intent;
+ }
+
+ /**
* Returns an intent to launch QR code scanner. It may return null if the security is not
* supported by QR code scanner.
*
@@ -242,6 +309,36 @@
}
/**
+ * Returns an intent to launch QR code scanner. It may return null if the security is not
+ * supported by QR code scanner.
+ *
+ * @param context The context to use for the content resolver
+ * @param wifiManager An instance of {@link WifiManager}
+ * @param wifiEntry An instance of {@link WifiEntry}
+ * @return Intent for launching QR code scanner
+ */
+ public static Intent getConfiguratorQrCodeScannerIntentOrNull(Context context,
+ WifiManager wifiManager, WifiEntry wifiEntry) {
+ final Intent intent = new Intent(context, WifiDppConfiguratorActivity.class);
+ if (isSupportConfiguratorQrCodeScanner(context, wifiEntry)) {
+ intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+ } else {
+ return null;
+ }
+
+ setConfiguratorIntentExtra(intent, wifiManager, wifiEntry);
+
+ final int networkId = WifiEntryShell.getNetworkId(wifiEntry);
+ if (networkId == WifiConfiguration.INVALID_NETWORK_ID) {
+ throw new IllegalArgumentException("Invalid network ID");
+ } else {
+ intent.putExtra(EXTRA_WIFI_NETWORK_ID, networkId);
+ }
+
+ return intent;
+ }
+
+ /**
* Returns an intent to launch QR code generator for the Wi-Fi hotspot. It may return null if
* the security is not supported by QR code generator.
*
@@ -320,6 +417,28 @@
intent.putExtra(EXTRA_WIFI_HIDDEN_SSID, wifiConfiguration.hiddenSSID);
}
+ private static void setConfiguratorIntentExtra(Intent intent, WifiManager wifiManager,
+ WifiEntry wifiEntry) {
+ final String ssid = removeFirstAndLastDoubleQuotes(wifiEntry.getTitle());
+ final String security = getSecurityString(wifiEntry);
+
+ // When the value of this key is read, the actual key is not returned, just a "*".
+ // Call privileged system API to obtain actual key.
+ final String preSharedKey = removeFirstAndLastDoubleQuotes(getPresharedKey(wifiManager,
+ wifiEntry));
+
+ if (!TextUtils.isEmpty(ssid)) {
+ intent.putExtra(EXTRA_WIFI_SSID, ssid);
+ }
+ if (!TextUtils.isEmpty(security)) {
+ intent.putExtra(EXTRA_WIFI_SECURITY, security);
+ }
+ if (!TextUtils.isEmpty(preSharedKey)) {
+ intent.putExtra(EXTRA_WIFI_PRE_SHARED_KEY, preSharedKey);
+ }
+ intent.putExtra(EXTRA_WIFI_HIDDEN_SSID, WifiEntryShell.hiddenSSID(wifiEntry));
+ }
+
/**
* Shows authentication screen to confirm credentials (pin, pattern or password) for the current
* user of the device.
@@ -379,6 +498,19 @@
}
/**
+ * Checks if QR code scanner supports to config other devices with the Wi-Fi network
+ *
+ * @param context The context to use for {@link WifiManager#isEasyConnectSupported()}
+ * @param wifiEntry The {@link WifiEntry} of the Wi-Fi network
+ */
+ public static boolean isSupportConfiguratorQrCodeScanner(Context context, WifiEntry wifiEntry) {
+ if (WifiEntryShell.isPasspoint(wifiEntry)) {
+ return false;
+ }
+ return isSupportWifiDpp(context, wifiEntry.getSecurity());
+ }
+
+ /**
* Checks if QR code generator supports to config other devices with the Wi-Fi network
*
* @param context The context to use for {@code WifiManager}
diff --git a/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java b/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java
index e094051..0145bb4 100644
--- a/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java
+++ b/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java
@@ -52,9 +52,6 @@
private static final String TAG = "SavedAccessPoints2";
- // Key of a Bundle to save/restore the selected WifiEntry
- static final String KEY_KEY = "key_key";
-
// Max age of tracked WifiEntries
private static final long MAX_SCAN_AGE_MILLIS = 15_000;
// Interval between initiating SavedNetworkTracker scans
@@ -139,7 +136,7 @@
}
final Bundle bundle = new Bundle();
- bundle.putString(KEY_KEY, key);
+ bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, key);
new SubSettingLauncher(getContext())
.setTitleText(title)
diff --git a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
index 78e592c..0741695 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
@@ -48,16 +48,17 @@
public void updateDisplay() {
final SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
if (config == null) {
- mBandIndex = 0;
- Log.d(TAG, "Updating band index to 0 because no config");
+ mBandIndex = SoftApConfiguration.BAND_2GHZ;
+ Log.d(TAG, "Updating band index to BAND_2GHZ because no config");
} else if (is5GhzBandSupported()) {
mBandIndex = validateSelection(config.getBand());
Log.d(TAG, "Updating band index to " + mBandIndex);
} else {
mWifiManager.setSoftApConfiguration(
- new SoftApConfiguration.Builder(config).setBand(0).build());
- mBandIndex = config.getBand();
- Log.d(TAG, "5Ghz not supported, updating band index to " + mBandIndex);
+ new SoftApConfiguration.Builder(config).setBand(SoftApConfiguration.BAND_2GHZ)
+ .build());
+ mBandIndex = SoftApConfiguration.BAND_2GHZ;
+ Log.d(TAG, "5Ghz not supported, updating band index to 2GHz");
}
ListPreference preference =
(ListPreference) mPreference;
@@ -74,10 +75,14 @@
}
String getConfigSummary() {
- if (mBandIndex == SoftApConfiguration.BAND_ANY) {
- return mContext.getString(R.string.wifi_ap_prefer_5G);
+ switch (mBandIndex) {
+ case SoftApConfiguration.BAND_2GHZ:
+ return mBandSummaries[0];
+ case SoftApConfiguration.BAND_5GHZ:
+ return mBandSummaries[1];
+ default:
+ return mContext.getString(R.string.wifi_ap_prefer_5G);
}
- return mBandSummaries[mBandIndex];
}
@Override
@@ -95,19 +100,18 @@
}
private int validateSelection(int band) {
- // Reset the band to 2.4 GHz if we get a weird config back to avoid a crash.
- final boolean isDualMode = mWifiManager.isDualModeSupported();
-
// unsupported states:
- // 1: no dual mode means we can't have AP_BAND_ANY - default to 5GHZ
- // 2: no 5 GHZ support means we can't have AP_BAND_5GHZ - default to 2GHZ
- // 3: With Dual mode support we can't have AP_BAND_5GHZ - default to ANY
- if (!isDualMode && SoftApConfiguration.BAND_ANY == band) {
+ // 1: no dual mode means we can't have multiband - default to 5GHZ
+ // 2: no 5 GHZ support means we can't have BAND_5GHZ - default to 2GHZ
+ // 3: With Dual mode support we can't have BAND_5GHZ only - include 2GHZ
+ if (!isDualMode
+ && ((band & (SoftApConfiguration.BAND_5GHZ
+ | SoftApConfiguration.BAND_2GHZ)) != 0)) {
return SoftApConfiguration.BAND_5GHZ;
} else if (!is5GhzBandSupported() && SoftApConfiguration.BAND_5GHZ == band) {
return SoftApConfiguration.BAND_2GHZ;
} else if (isDualMode && SoftApConfiguration.BAND_5GHZ == band) {
- return SoftApConfiguration.BAND_ANY;
+ return SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_2GHZ;
}
return band;
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index f836e64..80e179a 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -30,7 +30,6 @@
com.android.settings.bluetooth.DevicePickerFragment
com.android.settings.dashboard.profileselector.ProfileSelectAccountFragment
com.android.settings.dashboard.profileselector.ProfileSelectManageApplications
-com.android.settings.dashboard.profileselector.ProfileSelectStorageFragment
com.android.settings.dashboard.profileselector.ProfileSelectLocationFragment
com.android.settings.datausage.AppDataUsage
com.android.settings.datausage.DataUsageList
@@ -95,3 +94,4 @@
com.android.settings.applications.specialaccess.notificationaccess.NotificationAccessDetails
com.android.settings.wifi.details2.WifiNetworkDetailsFragment2
com.android.settings.wifi.savedaccesspoints2.SavedAccessPointsWifiSettings2
+com.android.settings.dashboard.profileselector.ProfileSelectRecentLocationRequestFragment
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java
new file mode 100644
index 0000000..5162bc2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class MagnificationModePreferenceControllerTest {
+ private static final String PREF_KEY = "screen_magnification_mode";
+ // TODO(b/146019459): Use magnification_capability.
+ private static final String KEY_CAPABILITY = Settings.System.MASTER_MONO;
+ private static final int WINDOW_SCREEN_VALUE = 2;
+ private static final int ALL_VALUE = 3;
+
+ private Context mContext;
+ private MagnificationModePreferenceController mController;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mController = new MagnificationModePreferenceController(mContext, PREF_KEY);
+ }
+
+ @Test
+ public void getSummary_saveWindowScreen_shouldReturnWindowScreenSummary() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ KEY_CAPABILITY, WINDOW_SCREEN_VALUE);
+
+ assertThat(mController.getSummary())
+ .isEqualTo(mContext.getString(
+ R.string.accessibility_magnification_area_settings_window_screen_summary));
+ }
+
+ @Test
+ public void getSummary_saveAll_shouldReturnAllSummary() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ KEY_CAPABILITY, ALL_VALUE);
+
+ assertThat(mController.getSummary())
+ .isEqualTo(mContext.getString(
+ R.string.accessibility_magnification_area_settings_all_summary));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceControllerTest.java
new file mode 100644
index 0000000..05dbb57
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationWindowControlPreferenceControllerTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.preference.SwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@RunWith(RobolectricTestRunner.class)
+public class MagnificationWindowControlPreferenceControllerTest {
+ private static final String PREF_KEY = "screen_magnification_window_control_switch";
+ // TODO(b/146019459): Use magnification_window_control_enabled.
+ private static final String KEY_CONTROL = Settings.System.MASTER_MONO;
+ private Context mContext;
+ private SwitchPreference mPreference;
+ private MagnificationWindowControlPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mPreference = new SwitchPreference(mContext);
+ mController = new MagnificationWindowControlPreferenceController(mContext, PREF_KEY);
+ }
+
+ @Test
+ public void isChecked_enabledWindowControl_shouldReturnTrue() {
+ Settings.System.putIntForUser(mContext.getContentResolver(),
+ KEY_CONTROL, State.ON, UserHandle.USER_CURRENT);
+
+ mController.updateState(mPreference);
+
+ assertThat(mController.isChecked()).isTrue();
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_disabledWindowControl_shouldReturnFalse() {
+ Settings.System.putIntForUser(mContext.getContentResolver(),
+ KEY_CONTROL, State.OFF, UserHandle.USER_CURRENT);
+
+ mController.updateState(mPreference);
+
+ assertThat(mController.isChecked()).isFalse();
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void setChecked_setTrue_shouldEnableWindowControl() {
+ mController.setChecked(true);
+
+ assertThat(Settings.System.getIntForUser(mContext.getContentResolver(),
+ KEY_CONTROL, State.UNKNOWN, UserHandle.USER_CURRENT)).isEqualTo(State.ON);
+ }
+
+ @Test
+ public void setChecked_setFalse_shouldDisableWindowControl() {
+ mController.setChecked(false);
+
+ assertThat(Settings.System.getIntForUser(mContext.getContentResolver(),
+ KEY_CONTROL, State.UNKNOWN, UserHandle.USER_CURRENT)).isEqualTo(State.OFF);
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface State {
+ int UNKNOWN = -1;
+ int OFF = 0;
+ int ON = 1;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/accounts/AccountDashboardFragmentTest.java
index 0060875..fe57090 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountDashboardFragmentTest.java
@@ -17,26 +17,55 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
import android.provider.SearchIndexableResource;
import com.android.settingslib.drawer.CategoryKey;
+import com.android.settingslib.search.SearchIndexableRaw;
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;
+import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class AccountDashboardFragmentTest {
+ private static final int PROFILE_ID = 10;
+ private static final String PROFILE_NAME = "User";
+ private static final String ACCOUNT_TYPE = "com.android.settings";
+ private static final String ACCOUNT_NAME = "test account";
+
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private AccountManager mAccountManager;
+
+ private Context mContext;
private AccountDashboardFragment mFragment;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
mFragment = new AccountDashboardFragment();
+
+ doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
}
@Test
@@ -45,7 +74,7 @@
}
@Test
- public void testSearchIndexProvider_shouldIndexResource() {
+ public void searchIndexProvider_shouldIndexResource() {
final List<SearchIndexableResource> indexRes =
AccountDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
.getXmlResourcesToIndex(RuntimeEnvironment.application, true /* enabled */);
@@ -53,4 +82,36 @@
assertThat(indexRes).isNotNull();
assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
}
+
+ @Test
+ public void searchIndexProvider_hasManagedProfile_shouldNotIndex() {
+ final List<UserInfo> infos = new ArrayList<>();
+ infos.add(new UserInfo(PROFILE_ID, PROFILE_NAME, UserInfo.FLAG_MANAGED_PROFILE));
+ doReturn(infos).when(mUserManager).getProfiles(anyInt());
+
+ final List<SearchIndexableRaw> indexRaws =
+ AccountDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+ .getDynamicRawDataToIndex(mContext, true /* enabled */);
+
+ assertThat(indexRaws).isEmpty();
+ }
+
+ @Test
+ public void searchIndexProvider_hasAccounts_shouldIndex() {
+ final List<UserInfo> infos = new ArrayList<>();
+ infos.add(new UserInfo(PROFILE_ID, PROFILE_NAME, UserInfo.FLAG_PRIMARY));
+ doReturn(infos).when(mUserManager).getProfiles(anyInt());
+
+ final Account[] accounts = {
+ new Account(ACCOUNT_NAME, ACCOUNT_TYPE)
+ };
+ when(AccountManager.get(mContext)).thenReturn(mAccountManager);
+ doReturn(accounts).when(mAccountManager).getAccounts();
+
+ final List<SearchIndexableRaw> indexRaws =
+ AccountDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+ .getDynamicRawDataToIndex(mContext, true /* enabled */);
+
+ assertThat(indexRaws).isNotEmpty();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
index 3f6f95a..1e19325 100644
--- a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
@@ -75,7 +75,7 @@
}
@Test
- public void getTabId_setArgument_setCorrectTab() {
+ public void getTabId_setArgumentWork_setCorrectTab() {
final Bundle bundle = new Bundle();
bundle.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, WORK_TAB);
@@ -83,6 +83,14 @@
}
@Test
+ public void getTabId_setArgumentPersonal_setCorrectTab() {
+ final Bundle bundle = new Bundle();
+ bundle.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PERSONAL_TAB);
+
+ assertThat(mFragment.getTabId(mActivity, bundle)).isEqualTo(PERSONAL_TAB);
+ }
+
+ @Test
public void getTabId_setWorkId_getCorrectTab() {
final Bundle bundle = new Bundle();
bundle.putInt(EXTRA_USER_ID, 10);
diff --git a/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java
index 3be4347..0a8f7d6 100644
--- a/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/MockLocationAppPreferenceControllerTest.java
@@ -146,6 +146,6 @@
}
private AppOpsManager.OpEntry createOpEntry(int opMode) {
- return new OpEntry(0, opMode, new Pair[0]);
+ return new OpEntry(0, opMode, Collections.emptyMap());
}
}
diff --git a/tests/robotests/src/com/android/settings/development/SelectDSUPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/SelectDSUPreferenceControllerTest.java
index 0aeafc7..b2d12ef 100644
--- a/tests/robotests/src/com/android/settings/development/SelectDSUPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/SelectDSUPreferenceControllerTest.java
@@ -27,6 +27,7 @@
import androidx.preference.SwitchPreference;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -56,6 +57,7 @@
}
@Test
+ @Ignore
public void onPreferenceChanged_settingEnabled_turnOnGpuViewUpdates() {
mController.handlePreferenceTreeClick(mPreference);
String flag = SystemProperties.get(DSULoader.PROPERTY_KEY_FEATURE_FLAG);
diff --git a/tests/robotests/src/com/android/settings/development/ShowRefreshRatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/ShowRefreshRatePreferenceControllerTest.java
new file mode 100644
index 0000000..495b723
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/ShowRefreshRatePreferenceControllerTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.android.settings.development.ShowRefreshRatePreferenceController
+ .SURFACE_FLINGER_CODE;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.testutils.shadow.ShadowParcel;
+
+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.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ShowRefreshRatePreferenceControllerTest {
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private SwitchPreference mPreference;
+ @Mock
+ private IBinder mSurfaceFlinger;
+
+ private ShowRefreshRatePreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mController = spy(new ShowRefreshRatePreferenceController(mContext));
+ ReflectionHelpers.setField(mController, "mSurfaceFlinger", mSurfaceFlinger);
+ doNothing().when(mController).writeShowRefreshRateSetting(anyBoolean());
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void onPreferenceChange_settingToggledOn_shouldWriteTrueToShowRefreshRateSetting() {
+ mController.onPreferenceChange(mPreference, true /* new value */);
+
+ verify(mController).writeShowRefreshRateSetting(true);
+ }
+
+ @Test
+ public void onPreferenceChange_settingToggledOff_shouldWriteFalseToShowRefreshRateSetting() {
+ mController.onPreferenceChange(mPreference, false /* new value */);
+
+ verify(mController).writeShowRefreshRateSetting(false);
+ }
+
+ @Test
+ @Config(shadows = ShadowParcel.class)
+ public void updateState_settingEnabled_shouldCheckPreference() throws RemoteException {
+ ShadowParcel.sReadIntResult = 1;
+ doReturn(true).when(mSurfaceFlinger)
+ .transact(eq(SURFACE_FLINGER_CODE), any(), any(), eq(0 /* flags */));
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(true);
+ }
+
+ @Test
+ @Config(shadows = {ShadowParcel.class})
+ public void updateState_settingDisabled_shouldUnCheckPreference() throws RemoteException {
+ ShadowParcel.sReadIntResult = 0;
+ doReturn(true).when(mSurfaceFlinger)
+ .transact(eq(SURFACE_FLINGER_CODE), any(), any(), eq(0 /* flags */));
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(false);
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchDisabled_preferenceUnchecked_shouldNotTurnOffPreference() {
+ when(mPreference.isChecked()).thenReturn(false);
+ mController.onDeveloperOptionsSwitchDisabled();
+
+ verify(mController, never()).writeShowRefreshRateSetting(anyBoolean());
+ verify(mPreference, never()).setChecked(anyBoolean());
+ verify(mPreference).setEnabled(false);
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchDisabled_preferenceChecked_shouldTurnOffPreference() {
+ when(mPreference.isChecked()).thenReturn(true);
+ mController.onDeveloperOptionsSwitchDisabled();
+
+ verify(mController).writeShowRefreshRateSetting(false);
+ verify(mPreference).setChecked(false);
+ verify(mPreference).setEnabled(false);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java
index 572f1d8..b2ac7f1 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java
@@ -28,6 +28,7 @@
import com.android.settings.deviceinfo.BuildNumberPreferenceController;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -35,6 +36,7 @@
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
+@Ignore
public class MyDeviceInfoFragmentTest {
private MyDeviceInfoFragment mMyDeviceInfoFragment;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java
index 1febbe4..598ef6e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java
@@ -54,6 +54,7 @@
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@@ -84,10 +85,12 @@
MockitoAnnotations.initMocks(this);
final List<AppOpsManager.OpEntry> allowOps = new ArrayList<>();
allowOps.add(new AppOpsManager.OpEntry(
- AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, AppOpsManager.MODE_ALLOWED, new Pair[0]));
+ AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, AppOpsManager.MODE_ALLOWED,
+ Collections.emptyMap()));
final List<AppOpsManager.OpEntry> restrictedOps = new ArrayList<>();
restrictedOps.add(new AppOpsManager.OpEntry(
- AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, AppOpsManager.MODE_IGNORED, new Pair[0]));
+ AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, AppOpsManager.MODE_IGNORED,
+ Collections.emptyMap()));
mAllowedPackageOps = new AppOpsManager.PackageOps(
ALLOWED_PACKAGE_NAME, ALLOWED_UID, allowOps);
mRestrictedPackageOps = new AppOpsManager.PackageOps(
diff --git a/tests/robotests/src/com/android/settings/gestures/BackGestureIndicatorViewTest.java b/tests/robotests/src/com/android/settings/gestures/BackGestureIndicatorViewTest.java
new file mode 100644
index 0000000..8d43aaa
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/BackGestureIndicatorViewTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.widget.ImageView;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BackGestureIndicatorViewTest {
+
+ private Context mContext;
+
+ private BackGestureIndicatorDrawable mLeftDrawable;
+ private BackGestureIndicatorDrawable mRightDrawable;
+
+ private BackGestureIndicatorView mView;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+ mView = new BackGestureIndicatorView(mContext);
+
+ mLeftDrawable = (BackGestureIndicatorDrawable) ((ImageView) mView.findViewById(
+ R.id.indicator_left)).getDrawable();
+ mRightDrawable = (BackGestureIndicatorDrawable) ((ImageView) mView.findViewById(
+ R.id.indicator_right)).getDrawable();
+ }
+
+ @Test
+ public void testSetIndicatoreWidth() {
+ mView.setIndicatorWidth(25, true);
+ mView.setIndicatorWidth(52, false);
+
+ assertEquals(25, mLeftDrawable.getWidth());
+ assertEquals(52, mRightDrawable.getWidth());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
index 5913f7b..f6bc05a 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
@@ -40,12 +40,16 @@
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
+import androidx.lifecycle.Lifecycle;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settings.widget.AddPreference;
import com.android.settingslib.RestrictedLockUtils;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -56,10 +60,8 @@
import java.util.Arrays;
-import androidx.lifecycle.Lifecycle;
-import androidx.preference.PreferenceScreen;
-
@RunWith(RobolectricTestRunner.class)
+@Ignore
public class MobileNetworkSummaryControllerTest {
@Mock
private Lifecycle mLifecycle;
diff --git a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
new file mode 100644
index 0000000..06f3893
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothPan;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.net.NetworkPolicyManager;
+import android.net.wifi.WifiManager;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.widget.SwitchBar;
+import com.android.settings.widget.SwitchBarController;
+
+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.util.ReflectionHelpers;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+@RunWith(RobolectricTestRunner.class)
+public class TetherEnablerTest {
+ @Mock
+ private WifiManager mWifiManager;
+ @Mock
+ private ConnectivityManager mConnectivityManager;
+ @Mock
+ private NetworkPolicyManager mNetworkPolicyManager;
+ @Mock
+ private BluetoothPan mBluetoothPan;
+ @Mock
+ private SharedPreferences mSharedPreferences;
+
+ private SwitchBar mSwitchBar;
+ private TetherEnabler mEnabler;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ Context context = spy(ApplicationProvider.getApplicationContext());
+ AtomicReference<BluetoothPan> panReference = spy(AtomicReference.class);
+ mSwitchBar = new SwitchBar(context);
+ when(context.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
+ when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
+ mConnectivityManager);
+ when(context.getSystemService(Context.NETWORK_POLICY_SERVICE)).thenReturn(
+ mNetworkPolicyManager);
+ when(mConnectivityManager.getTetherableIfaces()).thenReturn(new String[0]);
+ panReference.set(mBluetoothPan);
+ mEnabler = new TetherEnabler(context, new SwitchBarController(mSwitchBar), panReference);
+ }
+
+ @Test
+ public void lifecycle_onStart_setCheckedCorrectly() {
+ when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{""});
+
+ mEnabler.onStart();
+ assertThat(mSwitchBar.isChecked()).isTrue();
+ }
+
+ @Test
+ public void startTether_fail_resetSwitchBar() {
+ when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(false);
+
+ mEnabler.startTether();
+ mEnabler.mOnStartTetheringCallback.onTetheringFailed();
+
+ assertThat(mSwitchBar.isChecked()).isFalse();
+ assertThat(mSwitchBar.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void onDataSaverChanged_setsEnabledCorrectly() {
+ assertThat(mSwitchBar.isEnabled()).isTrue();
+
+ // try to turn data saver on
+ when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(true);
+ mEnabler.onDataSaverChanged(true);
+ assertThat(mSwitchBar.isEnabled()).isFalse();
+
+ // lets turn data saver off again
+ when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(false);
+ mEnabler.onDataSaverChanged(false);
+ assertThat(mSwitchBar.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void onSwitchToggled_onlyStartsWifiTetherWhenNeeded() {
+ when(mWifiManager.isWifiApEnabled()).thenReturn(true);
+ mEnabler.onSwitchToggled(true);
+
+ verify(mConnectivityManager, never()).startTethering(anyInt(), anyBoolean(), any(), any());
+
+ doReturn(false).when(mWifiManager).isWifiApEnabled();
+ mEnabler.onSwitchToggled(true);
+
+ verify(mConnectivityManager, times(1))
+ .startTethering(anyInt(), anyBoolean(), any(), any());
+ }
+
+ @Test
+ public void onSwitchToggled_shouldStartUSBTetherWhenSelected() {
+ SharedPreferences preference = mock(SharedPreferences.class);
+ ReflectionHelpers.setField(mEnabler, "mSharedPreferences", preference);
+ when(preference.getBoolean(mEnabler.WIFI_TETHER_KEY, true)).thenReturn(false);
+ when(preference.getBoolean(mEnabler.USB_TETHER_KEY, false)).thenReturn(true);
+ when(preference.getBoolean(mEnabler.BLUETOOTH_TETHER_KEY, true)).thenReturn(false);
+
+ mEnabler.startTether();
+ verify(mConnectivityManager, times(1))
+ .startTethering(eq(ConnectivityManager.TETHERING_USB), anyBoolean(), any(), any());
+ verify(mConnectivityManager, never())
+ .startTethering(eq(ConnectivityManager.TETHERING_WIFI), anyBoolean(), any(), any());
+ verify(mConnectivityManager, never()).startTethering(
+ eq(ConnectivityManager.TETHERING_BLUETOOTH), anyBoolean(), any(), any());
+ }
+
+ @Test
+ public void startTether_startsBluetoothTetherWhenOff() {
+ BluetoothAdapter adapter = mock(BluetoothAdapter.class);
+ ReflectionHelpers.setField(mEnabler, "mBluetoothAdapter", adapter);
+ when(adapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
+
+ mEnabler.startTethering(ConnectivityManager.TETHERING_BLUETOOTH);
+ verify(adapter, times(1)).enable();
+
+ when(adapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
+ mEnabler.startTethering(ConnectivityManager.TETHERING_BLUETOOTH);
+ verify(mConnectivityManager, times(1)).startTethering(
+ eq(ConnectivityManager.TETHERING_BLUETOOTH), anyBoolean(), any(), any());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java b/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java
index 6a9590b..0fefbe0 100644
--- a/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java
@@ -36,6 +36,7 @@
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -95,6 +96,7 @@
}
@Test
+ @Ignore
public void onCreateDialog_twoSubscriptionsAskEveryTime_threeSubsForDisplay() {
final int dialogType = SMS_PICK;
setDialogType(dialogType);
diff --git a/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
index 765f14d..065186b 100644
--- a/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
+import android.app.settings.SettingsEnums;
import android.net.wifi.WifiConfiguration;
import android.os.Bundle;
import android.os.Parcelable;
@@ -139,6 +140,12 @@
0).mWifiConfiguration.SSID).isEqualTo(FAKE_NEW_OPEN_SSID);
}
+ @Test
+ public void getMetricsCategory_shouldReturnPanelAddWifiNetworks() {
+ assertThat(mAddAppNetworksFragment.getMetricsCategory()).isEqualTo(
+ SettingsEnums.PANEL_ADD_WIFI_NETWORKS);
+ }
+
private void addOneSavedNetworkConfig(@NonNull WifiConfiguration wifiConfiguration) {
if (mFakeSavedNetworksList == null) {
mFakeSavedNetworksList = new ArrayList<>();
@@ -180,5 +187,4 @@
}
return config;
}
-
}
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
index 5b125e9..e60303e 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
@@ -22,7 +22,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@@ -77,11 +76,11 @@
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.ActionButtonsPreference;
import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.wifi.AccessPoint;
-import com.android.settingslib.wifi.WifiTracker;
-import com.android.settingslib.wifi.WifiTrackerFactory;
+import com.android.wifitrackerlib.NetworkDetailsTracker;
+import com.android.wifitrackerlib.WifiEntry;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -99,10 +98,12 @@
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;
+// TODO(b/143326832): Should add test cases for connect button.
+// TODO(b/143326832): WifiEntry is not mature, should remove @Ignore after it's constructed.
+@Ignore
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowDevicePolicyManager.class, ShadowEntityHeaderController.class})
public class WifiDetailPreferenceController2Test {
@@ -115,14 +116,15 @@
private static final String MAC_ADDRESS = "01:23:45:67:89:ab";
private static final String RANDOMIZED_MAC_ADDRESS = "RANDOMIZED_MAC_ADDRESS";
private static final String FACTORY_MAC_ADDRESS = "FACTORY_MAC_ADDRESS";
- private static final String SECURITY = "None";
+ // TODO(b/143326832): Add WifiEntry#getSecurityString
+ //private static final String SECURITY = "None";
private static final String FQDN = "fqdn";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceScreen mMockScreen;
@Mock
- private AccessPoint mMockAccessPoint;
+ private WifiEntry mMockWifiEntry;
@Mock
private FragmentActivity mMockActivity;
@Mock
@@ -140,7 +142,7 @@
@Mock
private WifiManager mMockWifiManager;
@Mock
- private WifiTracker mMockWifiTracker;
+ private NetworkDetailsTracker mMockNetworkDetailsTracker;
@Mock
private MetricsFeatureProvider mMockMetricsFeatureProvider;
@Mock
@@ -258,10 +260,10 @@
mLifecycle = new Lifecycle(mLifecycleOwner);
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
- when(mMockAccessPoint.getConfig()).thenReturn(mMockWifiConfig);
- when(mMockAccessPoint.getLevel()).thenReturn(LEVEL);
- when(mMockAccessPoint.getSecurityString(false)).thenReturn(SECURITY);
- when(mMockAccessPoint.getSsidStr()).thenReturn(SSID);
+ when(mMockWifiEntry.getLevel()).thenReturn(LEVEL);
+ // TODO(b/143326832): Add WifiEntry#getSecurityString
+ //when(mMockWifiEntry.getSecurityString(false)).thenReturn(SECURITY);
+ when(mMockWifiEntry.getTitle()).thenReturn(SSID);
when(mMockConnectivityManager.getNetworkInfo(any(Network.class)))
.thenReturn(mMockNetworkInfo);
doNothing().when(mMockConnectivityManager).registerNetworkCallback(
@@ -293,44 +295,30 @@
}
private void setUpForConnectedNetwork() {
- when(mMockAccessPoint.isActive()).thenReturn(true);
- ArrayList list = new ArrayList<>();
- list.add(mMockAccessPoint);
- when(mMockWifiTracker.getAccessPoints()).thenReturn(list);
- WifiTrackerFactory.setTestingWifiTracker(mMockWifiTracker);
- when(mMockAccessPoint.matches(any(AccessPoint.class))).thenReturn(true);
- when(mMockAccessPoint.isReachable()).thenReturn(true);
+ when(mMockNetworkDetailsTracker.getWifiEntry()).thenReturn(mMockWifiEntry);
+ when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
mController = newWifiDetailPreferenceController2();
}
private void setUpForDisconnectedNetwork() {
- when(mMockAccessPoint.isActive()).thenReturn(false);
- ArrayList list = new ArrayList<>();
- list.add(mMockAccessPoint);
- when(mMockWifiTracker.getAccessPoints()).thenReturn(list);
- WifiTrackerFactory.setTestingWifiTracker(mMockWifiTracker);
- when(mMockAccessPoint.matches(any(AccessPoint.class))).thenReturn(true);
- when(mMockAccessPoint.isReachable()).thenReturn(true);
+ when(mMockNetworkDetailsTracker.getWifiEntry()).thenReturn(mMockWifiEntry);
+ when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
mController = newWifiDetailPreferenceController2();
}
private void setUpForNotInRangeNetwork() {
- when(mMockAccessPoint.isActive()).thenReturn(false);
- ArrayList list = new ArrayList<>();
- list.add(mMockAccessPoint);
- when(mMockWifiTracker.getAccessPoints()).thenReturn(list);
- WifiTrackerFactory.setTestingWifiTracker(mMockWifiTracker);
- when(mMockAccessPoint.matches(any(AccessPoint.class))).thenReturn(false);
- when(mMockAccessPoint.isReachable()).thenReturn(false);
+ when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+ when(mMockNetworkDetailsTracker.getWifiEntry()).thenReturn(mMockWifiEntry);
+ when(mMockWifiEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_UNREACHABLE);
mController = newWifiDetailPreferenceController2();
}
private WifiDetailPreferenceController2 newWifiDetailPreferenceController2() {
- return new WifiDetailPreferenceController2(
- mMockAccessPoint,
+ return spy(new WifiDetailPreferenceController2(
+ mMockWifiEntry,
mMockConnectivityManager,
mContext,
mMockFragment,
@@ -338,7 +326,7 @@
mLifecycle,
mMockWifiManager,
mMockMetricsFeatureProvider,
- mMockIconInjector);
+ mMockIconInjector));
}
private void setupMockedPreferenceScreen() {
@@ -392,6 +380,7 @@
assertThat(mController.isAvailable()).isTrue();
}
+ /* TODO(b/143326832): Add WifiEntry#getSecurityString
@Test
public void securityPreference_stringShouldBeSet() {
setUpForConnectedNetwork();
@@ -399,6 +388,7 @@
verify(mMockSecurityPref).setSummary(SECURITY);
}
+ */
@Test
public void latestWifiInfo_shouldBeFetchedInDisplayPreferenceForConnectedNetwork() {
@@ -506,7 +496,7 @@
public void entityHeader_shouldHaveLabelSetToTitle() {
setUpForConnectedNetwork();
String label = "title";
- when(mMockAccessPoint.getTitle()).thenReturn(label);
+ when(mMockWifiEntry.getTitle()).thenReturn(label);
displayAndResume();
@@ -517,8 +507,7 @@
public void entityHeader_shouldHaveSummarySet() {
setUpForConnectedNetwork();
String summary = "summary";
- when(mMockAccessPoint.getSettingsSummary(true /*convertSavedAsDisconnected*/))
- .thenReturn(summary);
+ when(mMockWifiEntry.getSummary()).thenReturn(summary);
displayAndResume();
@@ -531,7 +520,7 @@
displayAndResume();
- verify(mMockAccessPoint, times(1)).getSettingsSummary(true /*convertSavedAsDisconnected*/);
+ verify(mMockWifiEntry, times(1)).getSummary();
}
@Test
@@ -674,6 +663,7 @@
verify(mMockRxLinkSpeedPref, never()).setSummary(any(String.class));
}
+ /* TODO(b/143326832): Support Passpoint test cases while WifiTracker2 supports it.
@Test
public void ssidPref_shouldHaveDetailTextSetForPasspointR1() {
setUpForConnectedNetwork();
@@ -708,6 +698,7 @@
verify(mMockSsidPref).setVisible(false);
}
+ */
@Test
public void macAddressPref_shouldVisibleForConnectedNetwork() {
@@ -958,8 +949,7 @@
.thenReturn(new NetworkCapabilities(nc));
String summary = "Connected, no Internet";
- when(mMockAccessPoint.getSettingsSummary(true /*convertSavedAsDisconnected*/))
- .thenReturn(summary);
+ when(mMockWifiEntry.getSummary()).thenReturn(summary);
InOrder inOrder = inOrder(mMockHeaderController);
displayAndResume();
@@ -968,8 +958,7 @@
// Check that an irrelevant capability update does not update the access point summary, as
// doing so could cause unnecessary jank...
summary = "Connected";
- when(mMockAccessPoint.getSettingsSummary(true /*convertSavedAsDisconnected*/))
- .thenReturn(summary);
+ when(mMockWifiEntry.getSummary()).thenReturn(summary);
updateNetworkCapabilities(nc);
inOrder.verify(mMockHeaderController, never()).setSummary(any(CharSequence.class));
@@ -979,8 +968,7 @@
inOrder.verify(mMockHeaderController).setSummary(summary);
summary = "Connected, no Internet";
- when(mMockAccessPoint.getSettingsSummary(true /*convertSavedAsDisconnected*/))
- .thenReturn(summary);
+ when(mMockWifiEntry.getSummary()).thenReturn(summary);
// Another irrelevant update won't cause the UI to refresh...
updateNetworkCapabilities(nc);
@@ -993,16 +981,14 @@
// UI will be refreshed when private DNS is broken.
summary = "Private DNS server cannot be accessed";
- when(mMockAccessPoint.getSettingsSummary(true /* convertSavedAsDisconnected */))
- .thenReturn(summary);
+ when(mMockWifiEntry.getSummary()).thenReturn(summary);
nc.setPrivateDnsBroken(true);
updateNetworkCapabilities(nc);
inOrder.verify(mMockHeaderController).setSummary(summary);
// UI will be refreshed when device connects to a partial connectivity network.
summary = "Limited connection";
- when(mMockAccessPoint.getSettingsSummary(true /*convertSavedAsDisconnected*/))
- .thenReturn(summary);
+ when(mMockWifiEntry.getSummary()).thenReturn(summary);
nc.addCapability(NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY);
updateNetworkCapabilities(nc);
inOrder.verify(mMockHeaderController).setSummary(summary);
@@ -1017,7 +1003,7 @@
@Test
public void canForgetNetwork_shouldInvisibleIfWithoutConfiguration() {
setUpForConnectedNetwork();
- when(mMockAccessPoint.getConfig()).thenReturn(null);
+ when(mMockWifiEntry.isSaved()).thenReturn(false);
mController = newWifiDetailPreferenceController2();
displayAndResume();
@@ -1029,7 +1015,7 @@
public void canForgetNetwork_ephemeral() {
setUpForConnectedNetwork();
when(mMockWifiInfo.isEphemeral()).thenReturn(true);
- when(mMockAccessPoint.getConfig()).thenReturn(null);
+ when(mMockWifiEntry.isSaved()).thenReturn(false);
displayAndResume();
@@ -1057,7 +1043,7 @@
@Test
public void canShareNetwork_shouldInvisibleIfWithoutConfiguration() {
setUpForConnectedNetwork();
- when(mMockAccessPoint.getConfig()).thenReturn(null);
+ when(mMockWifiEntry.isSaved()).thenReturn(false);
displayAndResume();
@@ -1129,6 +1115,7 @@
.action(mMockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
}
+ /* TODO(b/143326832): Support Passpoint test cases while WifiTracker2 supports it.
@Test
public void forgetNetwork_shouldShowDialog() {
setUpForConnectedNetwork();
@@ -1146,6 +1133,7 @@
.action(mMockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
verify(spyController).showConfirmForgetDialog();
}
+ */
@Test
public void networkStateChangedIntent_shouldRefetchInfo() {
@@ -1344,7 +1332,7 @@
when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
InOrder inOrder = inOrder(mMockButtonsPref);
String label = "title";
- when(mMockAccessPoint.getTitle()).thenReturn(label);
+ when(mMockWifiEntry.getTitle()).thenReturn(label);
setUpForToast();
displayAndResume();
@@ -1360,8 +1348,7 @@
verifyConnectBtnSetUpAsConnecting(inOrder);
// update as connected
- when(mMockAccessPoint.isActive()).thenReturn(true);
- mController.updateAccessPoint();
+ when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
// check connect button invisible, be init as default state and toast success message
verifyConnectBtnBeInitAsDefault(inOrder);
@@ -1419,364 +1406,21 @@
}
@Test
- public void testConnectButton_clickConnectButTimeout_displayFailMessage() {
- setUpForDisconnectedNetwork();
- when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
- InOrder inOrder = inOrder(mMockButtonsPref);
- setUpForToast();
-
- displayAndResume();
-
- // check connect button exist
- verifyConnectBtnSetUpAsVisible(inOrder);
-
- // click connect button
- mController.connectNetwork();
-
- // check display button as connecting
- verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
- verifyConnectBtnSetUpAsConnecting(inOrder);
-
- // update as failed
- mController.sTimer.onFinish();
-
- // check connect button visible, be init as default and toast failed message
- verifyConnectBtnBeInitAsDefault(inOrder);
- inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
- assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
- mContext.getString(R.string.wifi_failed_connect_message));
- }
-
- @Test
- public void testConnectButton_clickConnectButTimeout_displayNotInRangeMessage() {
- setUpForNotInRangeNetwork();
- when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
- InOrder inOrder = inOrder(mMockButtonsPref);
- setUpForToast();
-
- displayAndResume();
-
- // check connect button exist
- verifyConnectBtnSetUpAsVisible(inOrder);
-
- // click connect button
- mController.connectNetwork();
-
- // check display button as connecting
- verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
- verifyConnectBtnSetUpAsConnecting(inOrder);
-
- // update as failed
- mController.sTimer.onFinish();
-
- // check connect button visible, be init as default and toast failed message
- verifyConnectBtnBeInitAsDefault(inOrder);
- inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
- assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
- mContext.getString(R.string.wifi_not_in_range_message));
- }
-
- @Test
- public void testConnectButton_clickConnectWhenWiFiDisabled_displaySuccessMessage() {
- setUpForDisconnectedNetwork();
- when(mMockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
- InOrder inOrder = inOrder(mMockButtonsPref);
- String label = "title";
- when(mMockAccessPoint.getTitle()).thenReturn(label);
- setUpForToast();
-
- displayAndResume();
-
- // check connect button exist
- verifyConnectBtnSetUpAsVisible(inOrder);
-
- // click connect button
- mController.connectNetwork();
-
- // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
- verify(mMockWifiManager, times(1)).setWifiEnabled(true);
- verifyConnectBtnSetUpAsConnecting(inOrder);
- assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
- mContext.getString(R.string.wifi_turned_on_message));
-
- // notify Wi-Fi enabled
- mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
-
- // check had connect network and icon display as expected
- verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
- verifyConnectBtnSetUpAsConnecting(inOrder);
-
- // update as connected
- when(mMockAccessPoint.isActive()).thenReturn(true);
- mController.updateAccessPoint();
-
- // check connect button invisible, be init as default state and toast success message
- verifyConnectBtnBeInitAsDefault(inOrder);
- inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(false);
- assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
- mContext.getString(R.string.wifi_connected_to_message, label));
- }
-
- @Test
- public void testConnectButton_clickConnectWhenWiFiDisabled_failedToConnectWiFi() {
- setUpForDisconnectedNetwork();
- when(mMockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
- InOrder inOrder = inOrder(mMockButtonsPref);
- setUpForToast();
-
- displayAndResume();
-
- // check connect button exist
- verifyConnectBtnSetUpAsVisible(inOrder);
-
- // click connect button
- mController.connectNetwork();
-
- // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
- verify(mMockWifiManager, times(1)).setWifiEnabled(true);
- verifyConnectBtnSetUpAsConnecting(inOrder);
- assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
- mContext.getString(R.string.wifi_turned_on_message));
-
- // notify Wi-Fi enabled
- mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
-
- // check had connect network and icon display as expected
- verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
- verifyConnectBtnSetUpAsConnecting(inOrder);
-
- // update as failed
- mController.sTimer.onFinish();
-
- // check connect button visible, be init as default and toast failed message
- verifyConnectBtnBeInitAsDefault(inOrder);
- inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
- assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
- mContext.getString(R.string.wifi_failed_connect_message));
- }
-
- @Test
- public void
- testConnectButton_clickConnectWhenWiFiDisabled_failedToConnectWifiBecauseNotInRange() {
- setUpForNotInRangeNetwork();
- when(mMockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
- InOrder inOrder = inOrder(mMockButtonsPref);
- setUpForToast();
-
- displayAndResume();
-
- // check connect button exist
- verifyConnectBtnSetUpAsVisible(inOrder);
-
- // click connect button
- mController.connectNetwork();
-
- // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
- verify(mMockWifiManager, times(1)).setWifiEnabled(true);
- verifyConnectBtnSetUpAsConnecting(inOrder);
- assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
- mContext.getString(R.string.wifi_turned_on_message));
-
- // notify Wi-Fi enabled
- mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
-
- // check had connect network and icon display as expected
- verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
- verifyConnectBtnSetUpAsConnecting(inOrder);
-
- // update as failed
- mController.sTimer.onFinish();
-
- // check connect button visible, be init as default and toast failed message
- verifyConnectBtnBeInitAsDefault(inOrder);
- inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
- assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
- mContext.getString(R.string.wifi_not_in_range_message));
- }
-
- @Test
- public void testConnectButton_clickConnectWhenWiFiDisabled_failedToEnableWifi() {
- setUpForDisconnectedNetwork();
- when(mMockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
- InOrder inOrder = inOrder(mMockButtonsPref);
- setUpForToast();
-
- displayAndResume();
-
- // check connect button exist
- verifyConnectBtnSetUpAsVisible(inOrder);
-
- // click connect button
- mController.connectNetwork();
-
- // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
- verify(mMockWifiManager, times(1)).setWifiEnabled(true);
- verifyConnectBtnSetUpAsConnecting(inOrder);
- assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
- mContext.getString(R.string.wifi_turned_on_message));
-
- // notify turn on Wi-Fi failed
- mController.sTimer.onFinish();
-
- // check connect button visible, be init as default and toast failed message
- verifyConnectBtnBeInitAsDefault(inOrder);
- inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
- assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
- mContext.getString(R.string.wifi_failed_connect_message));
- }
-
- @Test
- public void testConnectButton_clickConnectAndBackKey_ignoreTimeoutEvent() {
- setUpForDisconnectedNetwork();
- when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
- InOrder inOrder = inOrder(mMockButtonsPref);
- setUpForToast();
-
- displayAndResume();
-
- // check connect button exist
- verifyConnectBtnSetUpAsVisible(inOrder);
-
- // click connect button
- mController.connectNetwork();
-
- // check display button as connecting
- verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
- verifyConnectBtnSetUpAsConnecting(inOrder);
-
- // leave detail page
- when(mMockFragment.getActivity()).thenReturn(null);
-
- // timeout happened
- mController.sTimer.onFinish();
-
- // check connect button visible, be init as default and toast failed message
- inOrder.verify(mMockButtonsPref, never()).setButton3Text(R.string.wifi_connect);
- inOrder.verify(mMockButtonsPref, never()).setButton3Icon(R.drawable.ic_settings_wireless);
- inOrder.verify(mMockButtonsPref, never()).setButton3Enabled(true);
- inOrder.verify(mMockButtonsPref, never()).setButton3Visible(true);
- assertThat(ShadowToast.shownToastCount()).isEqualTo(0);
- }
-
- @Test
- public void updateAccessPoint_returnFalseForNothingChanged() {
- setUpForDisconnectedNetwork();
-
- displayAndResume();
- boolean changed = mController.updateAccessPoint();
-
- assertThat(changed).isFalse();
- }
-
- @Test
- public void updateAccessPoint_returnTrueForSignalLevelChanged() {
- setUpForDisconnectedNetwork();
-
- displayAndResume();
-
- // Level changed
- when(mMockAccessPoint.getLevel()).thenReturn(LEVEL + 1);
- boolean changed = mController.updateAccessPoint();
-
- assertThat(changed).isTrue();
- }
-
- @Test
- public void updateAccessPoint_returnTrueForChangeAsNotInRange() {
- setUpForDisconnectedNetwork();
-
- displayAndResume();
-
- // change as not in range
- when(mMockAccessPoint.matches(any(AccessPoint.class))).thenReturn(false);
- boolean changed = mController.updateAccessPoint();
-
- assertThat(changed).isTrue();
- }
-
- @Test
- public void updateAccessPoint_returnTrueForChangeAsInRange() {
- setUpForNotInRangeNetwork();
-
- displayAndResume();
-
- // change as in range
- when(mMockAccessPoint.matches(any(AccessPoint.class))).thenReturn(true);
- boolean changed = mController.updateAccessPoint();
-
- assertThat(changed).isTrue();
- }
-
- @Test
- public void updateAccessPoint_returnTrueForChangeAsConnected() {
- setUpForDisconnectedNetwork();
-
- displayAndResume();
-
- // change as connected
- when(mMockAccessPoint.isActive()).thenReturn(true);
- boolean changed = mController.updateAccessPoint();
-
- assertThat(changed).isTrue();
- }
-
- @Test
- public void updateAccessPoint_returnTrueForChangeAsDisconnected() {
- setUpForConnectedNetwork();
-
- displayAndResume();
-
- // change as disconnected
- when(mMockAccessPoint.isActive()).thenReturn(false);
- boolean changed = mController.updateAccessPoint();
-
- assertThat(changed).isTrue();
- }
-
- @Test
- public void updateAccessPoint_returnTrueForAccessPointUpdated() {
- setUpForConnectedNetwork();
-
- displayAndResume();
-
- // change as disconnected
- when(mMockAccessPoint.update(mMockWifiConfig, mMockWifiInfo, mMockNetworkInfo))
- .thenReturn(true);
- boolean changed = mController.updateAccessPoint();
-
- assertThat(changed).isTrue();
- }
-
- @Test
- public void testRefreshRssiViews_shouldNotUpdateIfLevelIsSameForConnectedNetwork() {
+ public void testRefreshRssiViews_shouldOnUpdated() {
setUpForConnectedNetwork();
displayAndResume();
mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
- verify(mMockAccessPoint, times(3)).getLevel();
- verify(mMockIconInjector, times(1)).getIcon(anyInt());
- }
-
- @Test
- public void testRefreshRssiViews_shouldUpdateOnLevelChangeForConnectedNetwork() {
- setUpForConnectedNetwork();
- displayAndResume();
-
- when(mMockAccessPoint.getLevel()).thenReturn(0);
- mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
-
- verify(mMockAccessPoint, times(4)).getLevel();
- verify(mMockIconInjector, times(2)).getIcon(anyInt());
+ verify(mController).onUpdated();
}
@Test
public void testRefreshRssiViews_shouldNotUpdateForNotInRangeNetwork() {
setUpForNotInRangeNetwork();
-
displayAndResume();
- when(mMockAccessPoint.getLevel()).thenReturn(0);
+ when(mMockWifiEntry.getLevel()).thenReturn(0);
mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
verify(mMockSignalStrengthPref, times(2)).setVisible(false);
@@ -1858,6 +1502,7 @@
verify(mMockMacAddressPref).setTitle(R.string.wifi_advanced_device_mac_address_title);
}
+ /* TODO(b/143326832): Support Passpoint test cases while WifiTracker2 supports it.
@Test
public void entityHeader_expiredPasspointR1_shouldHandleExpiration() {
when(mMockAccessPoint.isPasspoint()).thenReturn(true);
@@ -1872,6 +1517,7 @@
verify(mMockButtonsPref, atLeastOnce()).setButton3Visible(false);
verify(mMockHeaderController).setSummary(expireSummary);
}
+ */
private ActionButtonsPreference createMock() {
final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2Test.java
index 517c96a..c453db3 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiMeteredPreferenceController2Test.java
@@ -21,13 +21,14 @@
import static org.mockito.Mockito.spy;
import android.content.Context;
-import android.net.wifi.WifiConfiguration;
import androidx.preference.DropDownPreference;
import com.android.settings.R;
+import com.android.wifitrackerlib.WifiEntry;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -42,7 +43,7 @@
private static final int METERED_OVERRIDE_NOT_METERED = 2;
@Mock
- private WifiConfiguration mWifiConfiguration;
+ private WifiEntry mWifiEntry;
private WifiMeteredPreferenceController2 mPreferenceController;
private Context mContext;
@@ -53,7 +54,7 @@
mContext = RuntimeEnvironment.application;
mPreferenceController = spy(
- new WifiMeteredPreferenceController2(mContext, mWifiConfiguration));
+ new WifiMeteredPreferenceController2(mContext, mWifiEntry));
mDropDownPreference = new DropDownPreference(mContext);
mDropDownPreference.setEntries(R.array.wifi_metered_entries);
mDropDownPreference.setEntryValues(R.array.wifi_metered_values);
@@ -87,6 +88,7 @@
}
@Test
+ @Ignore
public void testController_resilientToNullConfig() {
mPreferenceController = spy(new WifiMeteredPreferenceController2(mContext, null));
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
index 91cc01e..3403e0c 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
@@ -20,15 +20,17 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
import android.content.Context;
-import android.net.wifi.WifiConfiguration;
import androidx.preference.DropDownPreference;
import com.android.settings.R;
+import com.android.wifitrackerlib.WifiEntry;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -36,13 +38,14 @@
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
+@Ignore
public class WifiPrivacyPreferenceController2Test {
- private static final int PRIVACY_RANDOMIZED = WifiConfiguration.RANDOMIZATION_PERSISTENT;
- private static final int PRIVACY_TRUSTED = WifiConfiguration.RANDOMIZATION_NONE;
+ private static final int PRIVACY_RANDOMIZED = WifiEntry.PRIVACY_RANDOMIZED_MAC;
+ private static final int PRIVACY_TRUSTED = WifiEntry.PRIVACY_DEVICE_MAC;
@Mock
- private WifiConfiguration mWifiConfiguration;
+ private WifiEntry mWifiEntry;
private WifiPrivacyPreferenceController2 mPreferenceController;
private Context mContext;
@@ -55,7 +58,7 @@
WifiPrivacyPreferenceController2 preferenceController =
new WifiPrivacyPreferenceController2(mContext);
- preferenceController.setWifiConfiguration(mWifiConfiguration);
+ preferenceController.setWifiEntry(mWifiEntry);
mPreferenceController = spy(preferenceController);
mDropDownPreference = new DropDownPreference(mContext);
mDropDownPreference.setEntries(R.array.wifi_privacy_entries);
@@ -89,38 +92,23 @@
@Test
public void testController_resilientToNullConfig() {
mPreferenceController = spy(new WifiPrivacyPreferenceController2(mContext));
+ mPreferenceController.setWifiEntry(mWifiEntry);
mPreferenceController.getRandomizationValue();
mPreferenceController.onPreferenceChange(mDropDownPreference, "1");
}
@Test
- public void testUpdateState_isNotEphemeralNetwork_shouldBeSelectable() {
- mPreferenceController.setIsEphemeral(false);
+ public void testUpdateState_canSetPrivacy_shouldBeSelectable() {
+ when(mWifiEntry.canSetPrivacy()).thenReturn(true);
mPreferenceController.updateState(mDropDownPreference);
assertThat(mDropDownPreference.isSelectable()).isTrue();
}
@Test
- public void testUpdateState_isEphemeralNetwork_shouldNotSelectable() {
- mPreferenceController.setIsEphemeral(true);
- mPreferenceController.updateState(mDropDownPreference);
-
- assertThat(mDropDownPreference.isSelectable()).isFalse();
- }
-
- @Test
- public void testUpdateState_isNotPasspointNetwork_shouldBeSelectable() {
- mPreferenceController.setIsPasspoint(false);
- mPreferenceController.updateState(mDropDownPreference);
-
- assertThat(mDropDownPreference.isSelectable()).isTrue();
- }
-
- @Test
- public void testUpdateState_isPasspointNetwork_shouldNotSelectable() {
- mPreferenceController.setIsPasspoint(true);
+ public void testUpdateState_canNotSetPrivacy_shouldNotSelectable() {
+ when(mWifiEntry.canSetPrivacy()).thenReturn(false);
mPreferenceController.updateState(mDropDownPreference);
assertThat(mDropDownPreference.isSelectable()).isFalse();