Merge "[DPP R2] Added support for DPP R2 events"
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/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/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/layout/preference_gesture_navigation_slider.xml b/res/layout/preference_labeled_slider.xml
similarity index 96%
rename from res/layout/preference_gesture_navigation_slider.xml
rename to res/layout/preference_labeled_slider.xml
index ac7f334..42ad988 100644
--- a/res/layout/preference_gesture_navigation_slider.xml
+++ b/res/layout/preference_labeled_slider.xml
@@ -62,7 +62,6 @@
android:layout_height="wrap_content"
android:layout_gravity="start|top"
android:gravity="start"
- android:text="@string/low_label"
android:layout_weight="1"/>
<TextView
@@ -72,7 +71,6 @@
android:layout_height="wrap_content"
android:layout_gravity="end|top"
android:gravity="end"
- android:text="@string/high_label"
android:layout_weight="1"/>
</LinearLayout>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 34de0f5..e4a6b27 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1029,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/attrs.xml b/res/values/attrs.xml
index 6514304..ee47124 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -159,6 +159,12 @@
<attr name="textOff" format="reference" />
</declare-styleable>
+ <!-- For LabeledSeekBarPreference -->
+ <declare-styleable name="LabeledSeekBarPreference">
+ <attr name="textStart" format="reference" />
+ <attr name="textEnd" format="reference" />
+ </declare-styleable>
+
<declare-styleable name="TintDrawable">
<attr name="android:tint" />
<attr name="android:drawable" />
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 c911e6f..1821d7c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4761,6 +4761,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] -->
@@ -10258,6 +10278,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]-->
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/gesture_navigation_settings.xml b/res/xml/gesture_navigation_settings.xml
new file mode 100644
index 0000000..6230054
--- /dev/null
+++ b/res/xml/gesture_navigation_settings.xml
@@ -0,0 +1,55 @@
+<?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.widget.LabeledSeekBarPreference
+ android:key="gesture_left_back_sensitivity"
+ android:title="@string/left_edge"
+ android:max="3"
+ android:selectable="true"
+ settings:textStart="@string/low_label"
+ settings:textEnd="@string/high_label"/>
+
+ <com.android.settings.widget.LabeledSeekBarPreference
+ android:key="gesture_right_back_sensitivity"
+ android:title="@string/right_edge"
+ android:max="3"
+ android:selectable="true"
+ settings:textStart="@string/low_label"
+ settings:textEnd="@string/high_label"/>
+ </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/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 fb96bfd..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);
}
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/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index 4361933..f9016e8 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -54,6 +54,7 @@
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;
@@ -170,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);
@@ -179,8 +187,10 @@
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);
}
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/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/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/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/GestureNavigationSeekBarPreference.java b/src/com/android/settings/gestures/GestureNavigationSeekBarPreference.java
deleted file mode 100644
index 085411b..0000000
--- a/src/com/android/settings/gestures/GestureNavigationSeekBarPreference.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.util.AttributeSet;
-import android.widget.SeekBar;
-
-import androidx.core.content.res.TypedArrayUtils;
-
-import com.android.settings.R;
-import com.android.settings.widget.SeekBarPreference;
-
-/** A slider preference that is used to set the back gesture's sensitivity **/
-public class GestureNavigationSeekBarPreference extends SeekBarPreference {
-
- private OnPreferenceChangeListener mStopListener;
-
- public GestureNavigationSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
-
- super(context, attrs, defStyleAttr, defStyleRes);
- setLayoutResource(R.layout.preference_gesture_navigation_slider);
- }
-
- public GestureNavigationSeekBarPreference(Context context, AttributeSet attrs) {
- this(context, attrs, TypedArrayUtils.getAttr(context,
- androidx.preference.R.attr.seekBarPreferenceStyle,
- com.android.internal.R.attr.seekBarPreferenceStyle), 0);
- }
-
- public void setOnPreferenceChangeStopListener(OnPreferenceChangeListener listener) {
- mStopListener = listener;
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- super.onStopTrackingTouch(seekBar);
-
- if (mStopListener != null) {
- mStopListener.onPreferenceChange(this, seekBar.getProgress());
- }
- }
-}
-
diff --git a/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java b/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java
new file mode 100644
index 0000000..73d7b85
--- /dev/null
+++ b/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java
@@ -0,0 +1,149 @@
+/*
+ * 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.settings.widget.LabeledSeekBarPreference;
+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 LabeledSeekBarPreference 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/homepage/contextualcards/slices/DarkThemeSlice.java b/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSlice.java
index 36a3980..1b7f003 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSlice.java
@@ -17,15 +17,21 @@
import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+import static android.provider.Settings.Global.LOW_POWER_MODE;
+
import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.app.UiModeManager;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
+import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.Looper;
+import android.os.PowerManager;
+import android.provider.Settings;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -39,6 +45,9 @@
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
+import com.android.settings.slices.SliceBackgroundWorker;
+
+import java.io.IOException;
public class DarkThemeSlice implements CustomSliceable {
private static final String TAG = "DarkThemeSlice";
@@ -53,10 +62,12 @@
private final Context mContext;
private final UiModeManager mUiModeManager;
+ private final PowerManager mPowerManager;
public DarkThemeSlice(Context context) {
mContext = context;
mUiModeManager = context.getSystemService(UiModeManager.class);
+ mPowerManager = context.getSystemService(PowerManager.class);
}
@Override
@@ -67,15 +78,18 @@
sActiveUiSession = currentUiSession;
sKeepSliceShow = false;
}
- if (!sKeepSliceShow && !isAvailable(mContext)) {
- return null;
+ // Dark theme slice will disappear when battery saver is ON.
+ if (mPowerManager.isPowerSaveMode() || (!sKeepSliceShow && !isAvailable(mContext))) {
+ return new ListBuilder(mContext, CustomSliceRegistry.DARK_THEME_SLICE_URI,
+ ListBuilder.INFINITY)
+ .setIsError(true)
+ .build();
}
sKeepSliceShow = true;
final PendingIntent toggleAction = getBroadcastIntent(mContext);
@ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
final IconCompat icon =
IconCompat.createWithResource(mContext, R.drawable.dark_theme);
- final boolean isChecked = mUiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_YES;
return new ListBuilder(mContext, CustomSliceRegistry.DARK_THEME_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
@@ -85,7 +99,7 @@
.setSubtitle(mContext.getText(R.string.dark_theme_slice_subtitle))
.setPrimaryAction(
SliceAction.createToggle(toggleAction, null /* actionTitle */,
- isChecked)))
+ isDarkThemeMode(mContext))))
.build();
}
@@ -100,8 +114,7 @@
false);
// make toggle transition more smooth before dark theme takes effect
new Handler(Looper.getMainLooper()).postDelayed(() -> {
- mUiModeManager.setNightMode(
- isChecked ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO);
+ mUiModeManager.setNightModeActivated(isChecked);
}, DELAY_TIME_EXECUTING_DARK_THEME);
}
@@ -110,10 +123,15 @@
return null;
}
+ @Override
+ public Class getBackgroundWorkerClass() {
+ return DarkThemeWorker.class;
+ }
+
@VisibleForTesting
boolean isAvailable(Context context) {
// checking dark theme mode.
- if (mUiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_YES) {
+ if (isDarkThemeMode(context)) {
return false;
}
@@ -121,7 +139,47 @@
final BatteryManager batteryManager = context.getSystemService(BatteryManager.class);
final int level = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
Log.d(TAG, "battery level=" + level);
-
return level <= BATTERY_LEVEL_THRESHOLD;
}
+
+ @VisibleForTesting
+ boolean isDarkThemeMode(Context context) {
+ final int currentNightMode =
+ context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+ return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
+ }
+
+ public static class DarkThemeWorker extends SliceBackgroundWorker<Void> {
+ private final Context mContext;
+ private final ContentObserver mContentObserver =
+ new ContentObserver(new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean bChanged) {
+ if (mContext.getSystemService(PowerManager.class).isPowerSaveMode()) {
+ notifySliceChange();
+ }
+ }
+ };
+
+ public DarkThemeWorker(Context context, Uri uri) {
+ super(context, uri);
+ mContext = context;
+ }
+
+ @Override
+ protected void onSlicePinned() {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(LOW_POWER_MODE), false /* notifyForDescendants */,
+ mContentObserver);
+ }
+
+ @Override
+ protected void onSliceUnpinned() {
+ mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+ }
}
diff --git a/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java b/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
index e9e12e8..a5cc414 100644
--- a/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
+++ b/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
@@ -26,8 +26,10 @@
import com.android.settings.display.WallpaperPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.Indexable;
-import com.android.settingslib.search.SearchIndexableRaw;
import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.search.SearchIndexableRaw;
+
+import com.google.android.setupcompat.util.WizardManagerHelper;
import java.util.ArrayList;
import java.util.List;
@@ -37,10 +39,15 @@
private static final String WALLPAPER_FLAVOR_EXTRA = "com.android.launcher3.WALLPAPER_FLAVOR";
private static final String WALLPAPER_FOCUS = "focus_wallpaper";
+ private static final String WALLPAPER_ONLY = "wallpaper_only";
@Override
protected void addExtras(Intent intent) {
- intent.putExtra(WALLPAPER_FLAVOR_EXTRA, WALLPAPER_FOCUS);
+ if (WizardManagerHelper.isAnySetupWizard(intent)) {
+ intent.putExtra(WALLPAPER_FLAVOR_EXTRA, WALLPAPER_ONLY);
+ } else {
+ intent.putExtra(WALLPAPER_FLAVOR_EXTRA, WALLPAPER_FOCUS);
+ }
}
@VisibleForTesting
diff --git a/src/com/android/settings/widget/LabeledSeekBarPreference.java b/src/com/android/settings/widget/LabeledSeekBarPreference.java
new file mode 100644
index 0000000..e2b2d68
--- /dev/null
+++ b/src/com/android/settings/widget/LabeledSeekBarPreference.java
@@ -0,0 +1,83 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import androidx.core.content.res.TypedArrayUtils;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+
+/** A slider preference with left and right labels **/
+public class LabeledSeekBarPreference extends SeekBarPreference {
+
+ private final int mTextStartId;
+ private final int mTextEndId;
+ private OnPreferenceChangeListener mStopListener;
+
+ public LabeledSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+
+ super(context, attrs, defStyleAttr, defStyleRes);
+ setLayoutResource(R.layout.preference_labeled_slider);
+
+ final TypedArray styledAttrs = context.obtainStyledAttributes(attrs,
+ R.styleable.LabeledSeekBarPreference);
+ mTextStartId = styledAttrs.getResourceId(
+ R.styleable.LabeledSeekBarPreference_textStart,
+ R.string.summary_placeholder);
+ mTextEndId = styledAttrs.getResourceId(
+ R.styleable.LabeledSeekBarPreference_textEnd,
+ R.string.summary_placeholder);
+ styledAttrs.recycle();
+ }
+
+ public LabeledSeekBarPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, TypedArrayUtils.getAttr(context,
+ androidx.preference.R.attr.seekBarPreferenceStyle,
+ com.android.internal.R.attr.seekBarPreferenceStyle), 0);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ final TextView startText = (TextView) holder.findViewById(android.R.id.text1);
+ final TextView endText = (TextView) holder.findViewById(android.R.id.text2);
+ startText.setText(mTextStartId);
+ endText.setText(mTextEndId);
+ }
+
+ public void setOnPreferenceChangeStopListener(OnPreferenceChangeListener listener) {
+ mStopListener = listener;
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ super.onStopTrackingTouch(seekBar);
+
+ if (mStopListener != null) {
+ mStopListener.onPreferenceChange(this, seekBar.getProgress());
+ }
+ }
+}
+
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/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/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/gestures/GestureNavigationSeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/gestures/LabeledSeekBarPreferenceTest.java
similarity index 89%
rename from tests/robotests/src/com/android/settings/gestures/GestureNavigationSeekBarPreferenceTest.java
rename to tests/robotests/src/com/android/settings/gestures/LabeledSeekBarPreferenceTest.java
index 82c3262..4fb94f8 100644
--- a/tests/robotests/src/com/android/settings/gestures/GestureNavigationSeekBarPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/LabeledSeekBarPreferenceTest.java
@@ -27,6 +27,8 @@
import androidx.preference.Preference;
+import com.android.settings.widget.LabeledSeekBarPreference;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -36,11 +38,11 @@
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
-public class GestureNavigationSeekBarPreferenceTest {
+public class LabeledSeekBarPreferenceTest {
private Context mContext;
private SeekBar mSeekBar;
- private GestureNavigationSeekBarPreference mSeekBarPreference;
+ private LabeledSeekBarPreference mSeekBarPreference;
@Mock
private Preference.OnPreferenceChangeListener mListener;
@@ -50,7 +52,7 @@
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
- mSeekBarPreference = new GestureNavigationSeekBarPreference(mContext, null);
+ mSeekBarPreference = new LabeledSeekBarPreference(mContext, null);
LayoutInflater inflater = LayoutInflater.from(mContext);
final View view =
inflater.inflate(mSeekBarPreference.getLayoutResource(),
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java
index bb21332..1af7b2b 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java
@@ -22,10 +22,10 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import android.app.UiModeManager;
import android.content.Context;
import android.net.Uri;
import android.os.BatteryManager;
+import android.os.PowerManager;
import androidx.slice.Slice;
import androidx.slice.SliceMetadata;
@@ -48,9 +48,9 @@
@RunWith(RobolectricTestRunner.class)
public class DarkThemeSliceTest {
@Mock
- private UiModeManager mUiModeManager;
- @Mock
private BatteryManager mBatteryManager;
+ @Mock
+ private PowerManager mPowerManager;
private Context mContext;
private DarkThemeSlice mDarkThemeSlice;
@@ -63,11 +63,12 @@
mFeatureFactory = FakeFeatureFactory.setupForTest();
mFeatureFactory.slicesFeatureProvider = new SlicesFeatureProviderImpl();
mFeatureFactory.slicesFeatureProvider.newUiSession();
- doReturn(mUiModeManager).when(mContext).getSystemService(UiModeManager.class);
+ doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+ when(mPowerManager.isPowerSaveMode()).thenReturn(false);
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
- mDarkThemeSlice = new DarkThemeSlice(mContext);
+ mDarkThemeSlice = spy(new DarkThemeSlice(mContext));
mDarkThemeSlice.sKeepSliceShow = false;
}
@@ -80,7 +81,7 @@
@Test
public void isAvailable_inDarkThemeMode_returnFalse() {
- when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_YES);
+ doReturn(true).when(mDarkThemeSlice).isDarkThemeMode(mContext);
assertThat(mDarkThemeSlice.isAvailable(mContext)).isFalse();
}
@@ -100,23 +101,36 @@
}
@Test
- public void getSlice_notAvailable_returnNull() {
- when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_YES);
+ public void getSlice_batterySaver_returnErrorSlice() {
+ when(mPowerManager.isPowerSaveMode()).thenReturn(true);
- assertThat(mDarkThemeSlice.getSlice()).isNull();
+ final Slice mediaSlice = mDarkThemeSlice.getSlice();
+ final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice);
+ assertThat(metadata.isErrorSlice()).isTrue();
}
@Test
- public void getSlice_newSession_notAvailable_returnNull() {
+ public void getSlice_notAvailable_returnErrorSlice() {
+ doReturn(true).when(mDarkThemeSlice).isDarkThemeMode(mContext);
+
+ final Slice mediaSlice = mDarkThemeSlice.getSlice();
+ final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice);
+ assertThat(metadata.isErrorSlice()).isTrue();
+ }
+
+ @Test
+ public void getSlice_newSession_notAvailable_returnErrorSlice() {
// previous displayed: yes
mDarkThemeSlice.sKeepSliceShow = true;
// Session: use original value + 1 to become a new session
mDarkThemeSlice.sActiveUiSession =
mFeatureFactory.slicesFeatureProvider.getUiSessionToken() + 1;
- when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_YES);
+ doReturn(true).when(mDarkThemeSlice).isDarkThemeMode(mContext);
- assertThat(mDarkThemeSlice.getSlice()).isNull();
+ final Slice mediaSlice = mDarkThemeSlice.getSlice();
+ final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice);
+ assertThat(metadata.isErrorSlice()).isTrue();
}
@Test
@@ -149,7 +163,7 @@
}
private void setBatteryCapacityLevel(int power_level) {
- when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_NO);
+ doReturn(false).when(mDarkThemeSlice).isDarkThemeMode(mContext);
doReturn(mBatteryManager).when(mContext).getSystemService(BatteryManager.class);
when(mBatteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY))
.thenReturn(power_level);
diff --git a/tests/robotests/src/com/android/settings/wallpaper/WallpaperSuggestionActivityTest.java b/tests/robotests/src/com/android/settings/wallpaper/WallpaperSuggestionActivityTest.java
index 54a41a3..73f12c2 100644
--- a/tests/robotests/src/com/android/settings/wallpaper/WallpaperSuggestionActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wallpaper/WallpaperSuggestionActivityTest.java
@@ -22,15 +22,20 @@
import android.app.Application;
import android.app.WallpaperManager;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
+import com.google.android.setupcompat.util.WizardManagerHelper;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
@@ -48,6 +53,10 @@
@Mock
private Resources mResources;
+ private static final String PACKAGE_WALLPAPER_ACTIVITY =
+ "com.android.settings.wallpaper.WallpaperSuggestionActivity";
+ private static final String WALLPAPER_FLAVOR = "com.android.launcher3.WALLPAPER_FLAVOR";
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -90,6 +99,34 @@
.isTrue();
}
+ @Test
+ public void addExtras_intentFromSetupWizard_extrasHasWallpaperOnly() {
+ WallpaperSuggestionActivity activity =
+ Robolectric.buildActivity(WallpaperSuggestionActivity.class, new Intent(
+ Intent.ACTION_MAIN).setComponent(
+ new ComponentName(RuntimeEnvironment.application,
+ PACKAGE_WALLPAPER_ACTIVITY)).putExtra(
+ WizardManagerHelper.EXTRA_IS_FIRST_RUN, true).putExtra(
+ WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)).setup().get();
+ Intent intent = Shadows.shadowOf(activity).getNextStartedActivity();
+
+ assertThat(intent).isNotNull();
+ assertThat(intent.getStringExtra(WALLPAPER_FLAVOR)).isEqualTo("wallpaper_only");
+ }
+
+ @Test
+ public void addExtras_intentNotFromSetupWizard_extrasHasFocusWallpaper() {
+ WallpaperSuggestionActivity activity = Robolectric.buildActivity(
+ WallpaperSuggestionActivity.class, new Intent(Intent.ACTION_MAIN).setComponent(
+ new ComponentName(RuntimeEnvironment.application,
+ PACKAGE_WALLPAPER_ACTIVITY))).setup().get();
+ Intent intent = Shadows.shadowOf(activity).getNextStartedActivity();
+
+ assertThat(intent).isNotNull();
+ assertThat(intent.getStringExtra(WALLPAPER_FLAVOR)).isEqualTo("focus_wallpaper");
+ }
+
+
@Implements(WallpaperManager.class)
public static class ShadowWallpaperManager extends
org.robolectric.shadows.ShadowWallpaperManager {