Merge "Update accessibility button and gesture footer text for usability" into tm-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index be4810f..214d32a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -9,7 +9,7 @@
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.READ_MEDIA_IMAGE" />
+ <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
@@ -1517,6 +1517,8 @@
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
+ <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+ android:value="@string/menu_key_apps"/>
</activity-alias>
<activity android:name=".applications.InstalledAppOpenByDefaultActivity"
@@ -1529,6 +1531,8 @@
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
+ <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+ android:value="@string/menu_key_apps"/>
</activity>
<!-- Provide direct entry into manage apps showing running services. -->
@@ -1947,8 +1951,7 @@
<activity android:name=".accessibility.AccessibilitySettingsForSetupWizardActivity"
android:icon="@drawable/ic_accessibility_suggestion"
android:label="@string/vision_settings_title"
- android:exported="true"
- android:theme="@style/GlifV3Theme.Light">
+ android:exported="true">
<intent-filter android:priority="1">
<action android:name="android.settings.ACCESSIBILITY_SETTINGS_FOR_SUW" />
<category android:name="android.intent.category.DEFAULT" />
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index ba4d2f6..96f0210 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -21,38 +21,6 @@
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=" <solid android:color="#BCEDDF"/>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/drawable/accessibility_qs_tooltips_background.xml"
- line="22"
- column="20"/>
- </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=" <solid android:color="#BCEDDF"/>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/drawable/accessibility_qs_tooltips_background.xml"
- line="35"
- column="20"/>
- </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:startColor="#4D000000""
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -117,6 +85,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=" <color name="divider_color">#20ffffff</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="20"
+ 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="homepage_accessibility_background">#783BE5</color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -149,8 +133,40 @@
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="divider_color">#20ffffff</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" <color name="setup_wizard_wifi_color_dark">#89ffffff</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="22"
+ 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="setup_wizard_wifi_color_light">#89000000</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="23"
+ 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="lock_pattern_background">#00000000</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="25"
@@ -181,22 +197,6 @@
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="setup_wizard_wifi_color_dark">#89ffffff</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="27"
- 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="notification_importance_button_unselected">#5F6368</color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -213,8 +213,8 @@
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="setup_wizard_wifi_color_light">#89000000</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" <color name="fingerprint_title_color">#ffffffff</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="28"
@@ -245,43 +245,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=" <color name="lock_pattern_background">#00000000</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="30"
- 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="fingerprint_title_color">#ffffffff</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="33"
- 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="fingerprint_message_color">#de000000</color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="34"
+ line="29"
column="5"/>
</issue>
@@ -297,7 +265,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="36"
+ line="31"
column="5"/>
</issue>
@@ -313,7 +281,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="37"
+ line="32"
column="5"/>
</issue>
@@ -329,7 +297,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="41"
+ line="36"
column="5"/>
</issue>
@@ -345,6 +313,54 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
+ line="39"
+ 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="material_blue_500">#4285F4</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="42"
+ 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="material_blue_700">#3367D6</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="43"
+ 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="material_grey_100">#f5f5f5</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
line="44"
column="5"/>
</issue>
@@ -373,10 +389,26 @@
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="material_blue_500">#4285F4</color>"
+ errorLine1=" <color name="material_grey_200">#ffffff</color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
+ line="45"
+ 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="message_text_incoming">#ffffffff</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
line="47"
column="5"/>
</issue>
@@ -405,8 +437,8 @@
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="material_blue_700">#3367D6</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" <color name="message_text_outgoing">#ff323232</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="48"
@@ -437,8 +469,8 @@
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="material_grey_100">#f5f5f5</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" <color name="timestamp_text_outgoing">#99323232</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="49"
@@ -469,8 +501,8 @@
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="material_grey_200">#ffffff</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" <color name="timestamp_text_incoming">#99ffffff</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="50"
@@ -501,75 +533,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=" <color name="message_text_incoming">#ffffffff</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="52"
- 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="message_text_outgoing">#ff323232</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="53"
- 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="timestamp_text_outgoing">#99323232</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="54"
- 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="timestamp_text_incoming">#99ffffff</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="55"
- 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="message_bubble_incoming">#689f38</color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="56"
+ line="51"
column="5"/>
</issue>
@@ -585,7 +553,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="57"
+ line="52"
column="5"/>
</issue>
@@ -601,7 +569,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="58"
+ line="53"
column="5"/>
</issue>
@@ -617,7 +585,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="59"
+ line="54"
column="5"/>
</issue>
@@ -633,7 +601,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="60"
+ line="55"
column="5"/>
</issue>
@@ -649,7 +617,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="61"
+ line="56"
column="5"/>
</issue>
@@ -665,7 +633,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="63"
+ line="58"
column="5"/>
</issue>
@@ -681,7 +649,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="66"
+ line="61"
column="5"/>
</issue>
@@ -697,7 +665,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="69"
+ line="64"
column="5"/>
</issue>
@@ -713,7 +681,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="72"
+ line="67"
column="5"/>
</issue>
@@ -729,7 +697,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="75"
+ line="70"
column="5"/>
</issue>
@@ -745,7 +713,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="76"
+ line="71"
column="5"/>
</issue>
@@ -761,7 +729,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="77"
+ line="72"
column="5"/>
</issue>
@@ -777,7 +745,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="78"
+ line="73"
column="5"/>
</issue>
@@ -793,7 +761,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="79"
+ line="74"
column="5"/>
</issue>
@@ -809,7 +777,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="80"
+ line="75"
column="5"/>
</issue>
@@ -825,7 +793,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="81"
+ line="76"
column="5"/>
</issue>
@@ -841,7 +809,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="82"
+ line="77"
column="5"/>
</issue>
@@ -857,7 +825,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="83"
+ line="78"
column="5"/>
</issue>
@@ -873,7 +841,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="84"
+ line="79"
column="5"/>
</issue>
@@ -889,7 +857,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="85"
+ line="80"
column="5"/>
</issue>
@@ -905,7 +873,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="86"
+ line="81"
column="5"/>
</issue>
@@ -921,7 +889,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="87"
+ line="82"
column="5"/>
</issue>
@@ -937,7 +905,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="88"
+ line="83"
column="5"/>
</issue>
@@ -953,7 +921,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="89"
+ line="84"
column="5"/>
</issue>
@@ -969,7 +937,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="90"
+ line="85"
column="5"/>
</issue>
@@ -985,7 +953,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="91"
+ line="86"
column="5"/>
</issue>
@@ -1001,7 +969,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="92"
+ line="87"
column="5"/>
</issue>
@@ -1017,7 +985,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="93"
+ line="88"
column="5"/>
</issue>
@@ -1033,7 +1001,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="100"
+ line="95"
column="5"/>
</issue>
@@ -1049,7 +1017,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="103"
+ line="98"
column="5"/>
</issue>
@@ -1065,7 +1033,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="104"
+ line="99"
column="5"/>
</issue>
@@ -1081,7 +1049,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="105"
+ line="100"
column="5"/>
</issue>
@@ -1097,7 +1065,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="106"
+ line="101"
column="5"/>
</issue>
@@ -1113,7 +1081,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="107"
+ line="102"
column="5"/>
</issue>
@@ -1129,7 +1097,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="108"
+ line="103"
column="5"/>
</issue>
@@ -1145,7 +1113,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="111"
+ line="106"
column="5"/>
</issue>
@@ -1161,7 +1129,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="112"
+ line="107"
column="5"/>
</issue>
@@ -1177,7 +1145,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="113"
+ line="108"
column="5"/>
</issue>
@@ -1193,7 +1161,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="114"
+ line="109"
column="5"/>
</issue>
@@ -1209,7 +1177,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="115"
+ line="110"
column="5"/>
</issue>
@@ -1225,7 +1193,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="118"
+ line="113"
column="5"/>
</issue>
@@ -1241,7 +1209,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="119"
+ line="114"
column="5"/>
</issue>
@@ -1257,7 +1225,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="120"
+ line="115"
column="5"/>
</issue>
@@ -1273,7 +1241,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="123"
+ line="118"
column="5"/>
</issue>
@@ -1289,7 +1257,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="124"
+ line="119"
column="5"/>
</issue>
@@ -1305,7 +1273,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="125"
+ line="120"
column="5"/>
</issue>
@@ -1321,7 +1289,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="126"
+ line="121"
column="5"/>
</issue>
@@ -1337,7 +1305,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="127"
+ line="122"
column="5"/>
</issue>
@@ -1353,7 +1321,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="128"
+ line="123"
column="5"/>
</issue>
@@ -1369,7 +1337,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="135"
+ line="130"
column="5"/>
</issue>
@@ -1385,7 +1353,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="136"
+ line="131"
column="5"/>
</issue>
@@ -1401,7 +1369,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="137"
+ line="132"
column="5"/>
</issue>
@@ -1417,7 +1385,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="143"
+ line="138"
column="5"/>
</issue>
@@ -1433,7 +1401,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="145"
+ line="140"
column="5"/>
</issue>
@@ -1449,7 +1417,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="149"
+ line="144"
column="5"/>
</issue>
@@ -1465,7 +1433,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="150"
+ line="145"
column="5"/>
</issue>
@@ -1481,7 +1449,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="151"
+ line="146"
column="5"/>
</issue>
@@ -1497,7 +1465,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="152"
+ line="147"
column="5"/>
</issue>
@@ -1513,7 +1481,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="153"
+ line="148"
column="5"/>
</issue>
@@ -1529,7 +1497,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="154"
+ line="149"
column="5"/>
</issue>
@@ -1545,7 +1513,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="155"
+ line="150"
column="5"/>
</issue>
@@ -1561,7 +1529,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="156"
+ line="151"
column="5"/>
</issue>
@@ -1577,7 +1545,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="159"
+ line="154"
column="5"/>
</issue>
@@ -1593,7 +1561,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="160"
+ line="155"
column="5"/>
</issue>
@@ -1609,7 +1577,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="161"
+ line="156"
column="5"/>
</issue>
@@ -1625,7 +1593,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="162"
+ line="157"
column="5"/>
</issue>
@@ -1641,7 +1609,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="163"
+ line="158"
column="5"/>
</issue>
@@ -1657,7 +1625,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="164"
+ line="159"
column="5"/>
</issue>
@@ -1673,7 +1641,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="165"
+ line="160"
column="5"/>
</issue>
@@ -1689,7 +1657,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="166"
+ line="161"
column="5"/>
</issue>
@@ -1705,7 +1673,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="169"
+ line="164"
column="5"/>
</issue>
@@ -1721,7 +1689,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="170"
+ line="165"
column="5"/>
</issue>
@@ -1737,7 +1705,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="171"
+ line="166"
column="5"/>
</issue>
@@ -1753,7 +1721,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="172"
+ line="167"
column="5"/>
</issue>
@@ -1769,7 +1737,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="173"
+ line="168"
column="5"/>
</issue>
@@ -1785,7 +1753,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="174"
+ line="169"
column="5"/>
</issue>
@@ -1801,7 +1769,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="177"
+ line="172"
column="5"/>
</issue>
@@ -1817,7 +1785,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="178"
+ line="173"
column="5"/>
</issue>
@@ -1833,7 +1801,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="179"
+ line="174"
column="5"/>
</issue>
@@ -1849,7 +1817,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="180"
+ line="175"
column="5"/>
</issue>
@@ -1865,7 +1833,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="181"
+ line="176"
column="5"/>
</issue>
@@ -1881,7 +1849,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="182"
+ line="177"
column="5"/>
</issue>
@@ -1897,7 +1865,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="185"
+ line="180"
column="5"/>
</issue>
@@ -1913,7 +1881,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="186"
+ line="181"
column="5"/>
</issue>
@@ -1929,7 +1897,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="187"
+ line="182"
column="5"/>
</issue>
@@ -1945,7 +1913,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="188"
+ line="183"
column="5"/>
</issue>
@@ -1961,7 +1929,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="189"
+ line="184"
column="5"/>
</issue>
@@ -1977,7 +1945,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="190"
+ line="185"
column="5"/>
</issue>
@@ -1993,7 +1961,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="196"
+ line="191"
column="5"/>
</issue>
@@ -2009,7 +1977,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="197"
+ line="192"
column="5"/>
</issue>
@@ -2025,7 +1993,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="198"
+ line="193"
column="5"/>
</issue>
@@ -2041,7 +2009,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="199"
+ line="194"
column="5"/>
</issue>
@@ -2057,7 +2025,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="201"
+ line="196"
column="5"/>
</issue>
@@ -2073,7 +2041,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="203"
+ line="198"
column="5"/>
</issue>
@@ -2089,7 +2057,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="206"
+ line="201"
column="5"/>
</issue>
@@ -2837,6 +2805,22 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+ errorLine1=" android:color="@color/accessibility_feature_background"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/drawable/ic_accessibility_animation.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="HardCodedColor"
+ severity="Error"
+ message="Avoid using hardcoded color"
+ category="Correctness"
+ priority="4"
+ summary="Using hardcoded color"
+ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color="@color/accessibility_magnification_background"/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -2949,6 +2933,22 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+ errorLine1=" android:color="@color/accessibility_feature_background"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/drawable/ic_color_and_motion.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="HardCodedColor"
+ severity="Error"
+ message="Avoid using hardcoded color"
+ category="Correctness"
+ priority="4"
+ summary="Using hardcoded color"
+ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color="@color/accessibility_color_inversion_background"/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -3736,22 +3736,6 @@
errorLine1=" android:color="@color/accessibility_feature_background"/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="res/drawable/ic_color_and_motion.xml"
- line="22"
- column="13"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" android:color="@color/accessibility_feature_background"/>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
file="res/drawable/ic_vibration.xml"
line="22"
column="13"/>
@@ -4533,11 +4517,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="3108"
+ 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" 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="3104"
+ line="3112"
column="64"/>
</issue>
@@ -4553,7 +4553,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rCA/strings.xml"
- line="3104"
+ line="3112"
column="64"/>
</issue>
@@ -4569,7 +4569,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rGB/strings.xml"
- line="3104"
+ line="3112"
column="64"/>
</issue>
@@ -4585,7 +4585,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rIN/strings.xml"
- line="3104"
+ line="3112"
column="64"/>
</issue>
@@ -4597,27 +4597,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="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="3104"
- 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="7142"
+ line="7103"
column="36"/>
</issue>
@@ -4629,22 +4613,6 @@
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=" <item name="android:background">#ff000000</item>"
- errorLine2=" ^">
- <location
- file="res/values/styles.xml"
- line="202"
- column="41"/>
- </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=" <item name="android:colorError">@color/settings_dialog_colorError</item>"
errorLine2=" ^">
<location
@@ -4713,7 +4681,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
- line="135"
+ line="126"
column="41"/>
</issue>
@@ -4729,7 +4697,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
- line="135"
+ line="126"
column="41"/>
</issue>
@@ -4745,6 +4713,38 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
+ line="183"
+ column="45"/>
+ </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=" <item name="android:navigationBarColor">#00000000</item>"
+ errorLine2=" ^">
+ <location
+ file="res/values/themes.xml"
+ line="184"
+ column="49"/>
+ </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=" <item name="android:statusBarColor">#00000000</item>"
+ errorLine2=" ^">
+ <location
+ file="res/values/themes.xml"
line="192"
column="45"/>
</issue>
@@ -4773,38 +4773,6 @@
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=" <item name="android:statusBarColor">#00000000</item>"
- errorLine2=" ^">
- <location
- file="res/values/themes.xml"
- line="201"
- column="45"/>
- </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=" <item name="android:navigationBarColor">#00000000</item>"
- errorLine2=" ^">
- <location
- file="res/values/themes.xml"
- line="202"
- column="49"/>
- </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=" <item name="wifi_signal_color">@color/setup_wizard_wifi_color_dark</item>"
errorLine2=" ^">
<location
diff --git a/res/color/dream_card_color_state_list.xml b/res/color/dream_card_color_state_list.xml
index b0c86bb..0799dc6 100644
--- a/res/color/dream_card_color_state_list.xml
+++ b/res/color/dream_card_color_state_list.xml
@@ -17,6 +17,8 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:state_enabled="false" android:color="?androidprv:attr/colorSurface"
+ android:alpha="?android:attr/disabledAlpha"/>
<item android:state_selected="true" android:color="?androidprv:attr/colorAccentPrimary"/>
<item android:color="?androidprv:attr/colorSurface"/>
</selector>
\ No newline at end of file
diff --git a/res/color/dream_card_text_color_state_list.xml b/res/color/dream_card_text_color_state_list.xml
index 438855f..2ca7a0f 100644
--- a/res/color/dream_card_text_color_state_list.xml
+++ b/res/color/dream_card_text_color_state_list.xml
@@ -17,6 +17,8 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:state_enabled="false" android:color="?android:attr/textColorPrimary"
+ android:alpha="?android:attr/disabledAlpha"/>
<item android:state_selected="true" android:color="?androidprv:attr/textColorOnAccent"/>
<item android:color="?android:attr/textColorPrimary"/>
</selector>
\ No newline at end of file
diff --git a/res/drawable/accessibility_auto_added_qs_tooltips_illustration.xml b/res/drawable/accessibility_auto_added_qs_tooltip_illustration.xml
similarity index 100%
rename from res/drawable/accessibility_auto_added_qs_tooltips_illustration.xml
rename to res/drawable/accessibility_auto_added_qs_tooltip_illustration.xml
diff --git a/res/drawable/accessibility_qs_tooltips_background.xml b/res/drawable/accessibility_qs_tooltip_background.xml
similarity index 100%
rename from res/drawable/accessibility_qs_tooltips_background.xml
rename to res/drawable/accessibility_qs_tooltip_background.xml
diff --git a/res/drawable/accessibility_qs_tooltips_illustration.xml b/res/drawable/accessibility_qs_tooltip_illustration.xml
similarity index 100%
rename from res/drawable/accessibility_qs_tooltips_illustration.xml
rename to res/drawable/accessibility_qs_tooltip_illustration.xml
diff --git a/res/drawable/accessibility_text_reading_reset_button_background.xml b/res/drawable/accessibility_text_reading_reset_button_background.xml
deleted file mode 100644
index b86facf..0000000
--- a/res/drawable/accessibility_text_reading_reset_button_background.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2022 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<shape
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
-
- <corners android:radius="100dp" />
- <solid android:color="?androidprv:attr/colorAccentPrimary" />
-</shape>
diff --git a/res/layout-land/udfps_enroll_enrolling_land.xml b/res/layout-land/udfps_enroll_enrolling_land.xml
index 7ccd396..776f8a9 100644
--- a/res/layout-land/udfps_enroll_enrolling_land.xml
+++ b/res/layout-land/udfps_enroll_enrolling_land.xml
@@ -61,10 +61,10 @@
style="@style/SudGlifIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="?attr/sudGlifHeaderGravity"
+ android:scaleType="fitStart"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
- android:src="@drawable/ic_fingerprint_header" />
+ android:src="@drawable/ic_lock" />
<TextView
android:id="@+id/suc_layout_title"
diff --git a/res/layout/accessibility_qs_tooltips.xml b/res/layout/accessibility_qs_tooltip.xml
similarity index 86%
rename from res/layout/accessibility_qs_tooltips.xml
rename to res/layout/accessibility_qs_tooltip.xml
index 2bc9f5f..41501aa 100644
--- a/res/layout/accessibility_qs_tooltips.xml
+++ b/res/layout/accessibility_qs_tooltip.xml
@@ -20,13 +20,13 @@
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
- android:background="@drawable/accessibility_qs_tooltips_background">
+ android:background="@drawable/accessibility_qs_tooltip_background">
<ImageView
android:id="@+id/qs_illustration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingTop="@dimen/accessibility_qs_tooltips_margin_top"
+ android:paddingTop="@dimen/accessibility_qs_tooltip_margin_top"
android:layout_gravity="center_horizontal"
android:contentDescription="@null" />
@@ -34,7 +34,7 @@
android:id="@+id/qs_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:padding="@dimen/accessibility_qs_tooltips_margin"
+ android:padding="@dimen/accessibility_qs_tooltip_margin"
android:textColor="@android:color/black"
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:textSize="16sp" />
diff --git a/res/layout/accessibility_text_reading_preview_mail_content.xml b/res/layout/accessibility_text_reading_preview_mail_content.xml
index 7b50ac1..a8d4e52 100644
--- a/res/layout/accessibility_text_reading_preview_mail_content.xml
+++ b/res/layout/accessibility_text_reading_preview_mail_content.xml
@@ -25,6 +25,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accessibility_text_reading_preview_mail_subject"
+ android:textSize="14sp"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
@@ -33,6 +34,7 @@
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:paddingTop="11dp"
+ android:textSize="12sp"
android:text="@string/accessibility_text_reading_preview_mail_from"
android:textColor="?android:attr/textColorSecondary" />
@@ -40,6 +42,7 @@
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:textSize="13sp"
android:text="@string/accessibility_text_reading_preview_mail_content"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
diff --git a/res/layout/accessibility_text_reading_reset_button.xml b/res/layout/accessibility_text_reading_reset_button.xml
index 43800df..dd9128b 100644
--- a/res/layout/accessibility_text_reading_reset_button.xml
+++ b/res/layout/accessibility_text_reading_reset_button.xml
@@ -28,9 +28,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:background="@drawable/accessibility_text_reading_reset_button_background"
android:paddingHorizontal="24dp"
android:paddingVertical="14dp"
android:text="@string/accessibility_text_reading_reset_button_title"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ style="@style/ActionPrimaryButton"/>
</FrameLayout>
diff --git a/res/layout/profile_select_tablayout.xml b/res/layout/profile_select_tablayout.xml
deleted file mode 100644
index 3e83bb9..0000000
--- a/res/layout/profile_select_tablayout.xml
+++ /dev/null
@@ -1,49 +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.
- -->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:theme="@style/Theme.MaterialComponents.DayNight"
- android:clipToPadding="true"
- android:clipChildren="true"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <com.google.android.material.tabs.TabLayout
- android:background="@android:color/transparent"
- android:id="@+id/tabs"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:tabMaxWidth="0dp"
- app:tabGravity="fill"
- app:tabMode="fixed"
- app:tabIndicatorColor="@*android:color/accent_device_default"
- app:tabSelectedTextColor="@*android:color/accent_device_default"
- app:tabTextColor="?android:attr/textColorSecondary" />
- <View
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:background="?android:attr/listDivider"/>
-
- <androidx.viewpager.widget.ViewPager
- android:id="@+id/view_pager"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- </androidx.viewpager.widget.ViewPager>
-</LinearLayout>
diff --git a/res/layout/support_details_dialog.xml b/res/layout/support_details_dialog.xml
index 0233a1b..2390f90 100644
--- a/res/layout/support_details_dialog.xml
+++ b/res/layout/support_details_dialog.xml
@@ -33,6 +33,8 @@
android:layout_width="@dimen/admin_details_dialog_icon_size"
android:layout_height="@dimen/admin_details_dialog_icon_size"
android:scaleType="fitCenter"
+ android:src="@drawable/ic_lock_closed"
+ android:tint="?android:attr/colorAccent"
android:contentDescription="@null"/>
<TextView
android:id="@+id/admin_support_dialog_title"
diff --git a/res/raw/lottie_button_nav_menu.json b/res/raw/lottie_button_nav_menu.json
new file mode 100644
index 0000000..9581e46
--- /dev/null
+++ b/res/raw/lottie_button_nav_menu.json
@@ -0,0 +1 @@
+{"v":"5.7.6","fr":60,"ip":0,"op":300,"w":412,"h":300,"nm":"Home Button - Digital Assistant V01","ddd":0,"assets":[{"id":"image_0","w":803,"h":479,"u":"","p":"data:image/png;base64,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","e":1}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Gesture Tap","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,264.812,0],"ix":2,"l":2},"a":{"a":0,"k":[273.205,92.869,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-5.226],[-5.226,0],[0,5.226],[5.226,0]],"o":[[0,5.226],[5.226,0],[0,-5.226],[-5.226,0]],"v":[[-9.463,0],[0,9.463],[9.463,0],[0,-9.463]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[273.205,92.869],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.239,0.239],"y":[0.677,0.677]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":40,"s":[0,0]},{"i":{"x":[0.596,0.596],"y":[1,1]},"o":{"x":[0.182,0.182],"y":[0.207,0.207]},"t":55,"s":[80,80]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.793,0.793],"y":[0,0]},"t":75,"s":[120,120]},{"t":85,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":40,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-8.26],[-8.26,0],[0,8.26],[8.26,0]],"o":[[0,8.26],[8.26,0],[0,-8.26],[-8.26,0]],"v":[[-14.957,0],[0,14.957],[14.957,0],[0,-14.957]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[273.205,92.869],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.304,0.304],"y":[0.802,0.802]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":30,"s":[0,0]},{"i":{"x":[0.709,0.709],"y":[0.997,0.997]},"o":{"x":[0.196,0.196],"y":[0.446,0.446]},"t":45,"s":[80,80]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.609,0.609],"y":[0,0]},"t":75,"s":[100,100]},{"t":85,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":40,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Home Button","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":206.025,"ix":3},"y":{"a":0,"k":264.925,"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[34.95,34.95,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.6,0.6],"y":[0,0]},"t":80,"s":[16,16]},{"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0.6,0.6],"y":[0,0]},"t":90,"s":[12,12]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":95,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":107,"s":[0,0]},{"t":116,"s":[16,16]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.563568115234,0.598419189453,0.6806640625,1],"ix":4,"x":"var $bm_rt;\nvar rayColorPalette, rayColorSwatch;\ntry {\n rayColorPalette = 'Ray - palette 01';\n rayColorSwatch = Math.floor($bm_mul(value[2], 255));\n $bm_rt = comp(rayColorPalette).layer(1)(4)(rayColorSwatch)(1);\n} catch (e) {\n $bm_rt = value;\n}"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":516,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Blue_Dot","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":80,"s":[206.025]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[200.782]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":102,"s":[190.298]},{"t":111,"s":[206.025]}],"ix":3},"y":{"a":0,"k":264.925,"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[34.95,34.95,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":80,"s":[10,10]},{"t":93,"s":[8,8]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.101960785687,0.450980395079,0.909803926945,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":118,"st":10,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Yellow_Dot","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[206.025]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":102,"s":[211.267]},{"t":110,"s":[206.025]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":80,"s":[264.925]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[270.168]},{"t":98,"s":[264.925]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[34.95,34.95,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":80,"s":[10,10]},{"t":93,"s":[8,8]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.976470589638,0.670588254929,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":112,"st":10,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Red_Dot","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[206.025]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":102,"s":[200.782]},{"t":110,"s":[206.025]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":80,"s":[264.925]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[259.683]},{"t":98,"s":[264.925]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[34.95,34.95,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":80,"s":[10,10]},{"t":93,"s":[8,8]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.850980401039,0.188235297799,0.145098045468,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":111,"st":10,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Green_Dot","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":80,"s":[206.025]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":90,"s":[211.267]},{"i":{"x":[0.999],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":102,"s":[221.752]},{"t":111,"s":[206.025]}],"ix":3},"y":{"a":0,"k":264.925,"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[34.95,34.95,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":80,"s":[10,10]},{"t":93,"s":[8,8]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.117647059262,0.556862771511,0.243137255311,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":112,"st":10,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[208.25,164,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[113.25,113.25,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":1500,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Matte 2","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1.987,3.029,0],"ix":2,"l":2},"a":{"a":0,"k":[-1.918,38.018,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[113,35],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-1.918,97.68],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":116,"op":395,"st":35,"bm":0},{"ddd":0,"ind":9,"ty":2,"nm":"Glow","parent":7,"tt":1,"refId":"image_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":139,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":155,"s":[35]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":210,"s":[35]},{"t":235,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":-1.987,"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.795],"y":[1]},"o":{"x":[0.176],"y":[0.073]},"t":139,"s":[108.726]},{"i":{"x":[0.807],"y":[1]},"o":{"x":[0.307],"y":[0]},"t":155,"s":[81]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":210,"s":[81]},{"t":235,"s":[109]}],"ix":4}},"a":{"a":0,"k":[401.5,239.5,0],"ix":1,"l":2},"s":{"a":0,"k":[36.111,36.222,100],"ix":6,"l":2}},"ao":0,"ip":116,"op":395,"st":35,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Matte","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1.918,38.518,0],"ix":2,"l":2},"a":{"a":0,"k":[-1.918,38.018,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[112.836,115.964],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-1.918,38.393],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":116,"op":395,"st":35,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"NGA Line Outlines","parent":7,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1.5,80.379,0],"ix":2,"l":2},"a":{"a":0,"k":[45.896,0.896,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.4,"y":0},"t":115,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[96.146,1.016],[118.646,1.016]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.6,"y":0},"t":139,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[42.387,0.911],[63.59,0.911]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":155,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[42.385,0.887],[70.714,0.923]],"c":false}]},{"i":{"x":1,"y":1},"o":{"x":0.849,"y":0},"t":210,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[42.416,0.911],[70.714,0.923]],"c":false}]},{"t":235,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[96.146,1.016],[118.646,1.016]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.259000003338,0.522000014782,0.957000017166,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.793,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Yellow","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.4,"y":0},"t":115,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[118.646,1.016],[141.146,1.016]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.6,"y":0},"t":139,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[63.59,0.911],[87.443,0.911]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":155,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[70.714,0.923],[98.844,0.923]],"c":false}]},{"i":{"x":1,"y":1},"o":{"x":0.85,"y":0},"t":210,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[70.714,0.923],[98.844,0.923]],"c":false}]},{"t":235,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[118.646,1.016],[141.146,1.016]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.259000003338,0.522000014782,0.957000017166,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.793,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Green","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.4,"y":0},"t":115,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-32.104,1.016],[-9.604,1.016]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.6,"y":0},"t":139,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[21.184,0.911],[42.387,0.911]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":155,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[14.13,0.887],[42.385,0.887]],"c":false}]},{"i":{"x":1,"y":1},"o":{"x":0.85,"y":0},"t":210,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[14.13,0.887],[42.416,0.911]],"c":false}]},{"t":235,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-32.104,1.016],[-9.604,1.016]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.259000003338,0.522000014782,0.957000017166,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.793,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Red","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.4,"y":0},"t":115,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-54.604,1.016],[-32.104,1.016]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.6,"y":0},"t":139,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.972,0.911],[21.184,0.911]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":155,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-14.06,0.911],[14.13,0.887]],"c":false}]},{"i":{"x":1,"y":1},"o":{"x":0.85,"y":0},"t":210,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-14.06,0.911],[14.13,0.887]],"c":false}]},{"t":235,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-54.604,1.016],[-32.104,1.016]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.258999992819,0.522000002394,0.957000014361,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.793,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Blue","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":115,"op":236,"st":35,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Nav Bar Icons_Grey500","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,264.863,0],"ix":2,"l":2},"a":{"a":0,"k":[206,264.863,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.506,0],[0,0],[0,0.506],[0,0],[-0.506,0],[0,0],[0,-0.506],[0,0]],"o":[[0,0],[-0.506,0],[0,0],[0,-0.506],[0,0],[0.506,0],[0,0],[0,0.506]],"v":[[1.932,2.848],[-1.932,2.848],[-2.848,1.932],[-2.848,-1.932],[-1.932,-2.848],[1.932,-2.848],[2.848,-1.932],[2.848,1.932]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.603921592236,0.627451002598,0.65098041296,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[244.825,264.863],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.372],[0,0],[0.314,-0.2],[0,0],[-0.291,-0.185],[0,0]],"o":[[0,0],[0,-0.372],[0,0],[-0.291,0.185],[0,0],[0.314,0.2]],"v":[[2.338,2.376],[2.338,-2.376],[1.613,-2.773],[-2.12,-0.398],[-2.12,0.398],[1.613,2.773]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.603921592236,0.627451002598,0.65098041296,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[166.665,264.863],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[166.665,264.863],"ix":2},"a":{"a":0,"k":[166.665,264.863],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Nav Bar_White","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,264.863,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.1,0],[0,0],[0,4.1],[0,0],[0,0],[0,0]],"o":[[0,0],[-4.1,0],[0,0],[0,0],[0,0],[0,4.1]],"v":[[56.764,8.872],[-56.764,8.872],[-64.188,1.448],[-64.188,-8.872],[64.188,-8.872],[64.188,1.448]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Mic","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":122,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":129,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":228,"s":[100]},{"t":235,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":115,"s":[206,240.5,0],"to":[0,-15.083,0],"ti":[0,15.083,0]},{"i":{"x":1,"y":1},"o":{"x":0.167,"y":0.167},"t":155,"s":[206,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.65,"y":0},"t":210,"s":[206,150,0],"to":[0,7.667,0],"ti":[0,-7.667,0]},{"t":235,"s":[206,196,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.636,0],[0,4.636],[0,0],[-5.694,-0.823],[0,0],[0,0],[0,0],[0,5.93]],"o":[[0,4.636],[-4.636,0],[0,0],[0,5.93],[0,0],[0,0],[0,0],[5.694,-0.823],[0,0]],"v":[[8.399,61.968],[0,70.367],[-8.399,61.968],[-11.758,61.968],[-1.68,73.592],[-1.68,78.766],[1.68,78.766],[1.68,73.592],[11.758,61.968]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-2.788,0],[0,2.788],[0,0],[2.788,0],[0,-2.788],[0,0]],"o":[[2.788,0],[0,0],[0,-2.788],[-2.788,0],[0,0],[0,2.788]],"v":[[0,67.007],[5.039,61.968],[5.039,51.89],[0,46.85],[-5.039,51.89],[-5.039,61.968]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.101960785687,0.450980395079,0.909803926945,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":70,"op":1534,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Bottom Sheet","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":110,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":118.334,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":231.666,"s":[100]},{"t":240,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,273.699,0],"ix":2,"l":2},"a":{"a":0,"k":[0,48,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.4,"y":0},"t":110,"s":[{"i":[[0,0],[5.243,0],[0,0],[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045]],"o":[[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045],[0,0],[5.243,0],[0,0]],"v":[[64.188,38.773],[54.679,47.923],[-54.679,47.923],[-64.188,38.773],[-64.25,38.727],[-54.741,29.577],[54.617,29.577],[64.126,38.727]],"c":true}]},{"i":{"x":1,"y":1},"o":{"x":0.167,"y":0},"t":143,"s":[{"i":[[0,0],[5.243,0],[0,0],[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045]],"o":[[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045],[0,0],[5.243,0],[0,0]],"v":[[64.188,38.773],[54.679,47.923],[-54.679,47.923],[-64.188,38.773],[-64.188,-38.773],[-54.679,-47.923],[54.679,-47.923],[64.188,-38.773]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.65,"y":0},"t":215,"s":[{"i":[[0,0],[5.243,0],[0,0],[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045]],"o":[[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045],[0,0],[5.243,0],[0,0]],"v":[[64.188,38.773],[54.679,47.923],[-54.679,47.923],[-64.188,38.773],[-64.188,-38.773],[-54.679,-47.923],[54.679,-47.923],[64.188,-38.773]],"c":true}]},{"t":240,"s":[{"i":[[0,0],[5.243,0],[0,0],[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045]],"o":[[0,5.045],[0,0],[-5.243,0],[0,0],[0,-5.045],[0,0],[5.243,0],[0,0]],"v":[[64.188,38.773],[54.679,47.923],[-54.679,47.923],[-64.188,38.773],[-64.25,38.727],[-54.741,29.577],[54.617,29.577],[64.126,38.727]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":70,"op":1534,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"Device Frame","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[5.243,0],[0,0],[0,5.244],[0,0],[-5.243,0],[0,0],[0,-5.244]],"o":[[0,5.244],[0,0],[-5.243,0],[0,0],[0,-5.244],[0,0],[5.243,0],[0,0]],"v":[[64.188,114.112],[54.679,123.622],[-54.679,123.622],[-64.188,114.112],[-64.188,-114.112],[-54.679,-123.622],[54.679,-123.622],[64.188,-114.112]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[6.554,0],[0,0],[0,-6.555],[0,0],[-6.554,0],[0,0],[0,6.555],[0,0],[0,1.313],[0,0],[1.313,0]],"o":[[0,-6.555],[0,0],[-6.554,0],[0,0],[0,6.555],[0,0],[6.554,0],[0,0],[1.313,0],[0,0],[0,-1.313],[0,0]],"v":[[66.566,-114.112],[54.679,-126],[-54.679,-126],[-66.566,-114.112],[-66.566,114.112],[-54.679,126],[54.679,126],[66.566,114.112],[66.566,-2.378],[68.943,-4.755],[68.943,-28.528],[66.566,-30.906]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901969433,0.86274510622,0.878431379795,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"Power Button","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":206,"ix":3},"y":{"a":0,"k":150,"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,1.313],[0,0],[1.313,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,-1.313],[0,0],[0,0],[0,0],[1.313,0]],"v":[[68.943,-52.302],[68.943,-61.811],[66.566,-64.188],[65.456,-64.188],[65.55,-49.906],[66.566,-49.924]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901969433,0.86274510622,0.878431379795,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1534,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"Device Screen","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[5.243,0],[0,0],[0,5.244],[0,0],[-5.243,0],[0,0],[0,-5.244]],"o":[[0,5.244],[0,0],[-5.243,0],[0,0],[0,-5.244],[0,0],[5.243,0],[0,0]],"v":[[64.188,114.112],[54.679,123.622],[-54.679,123.622],[-64.188,114.112],[-64.188,-114.112],[-54.679,-123.622],[54.679,-123.622],[64.188,-114.112]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 5ebaeed..469f201 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1220,14 +1220,12 @@
<item>@string/screensaver_settings_summary_sleep</item>
<item>@string/screensaver_settings_summary_dock</item>
<item>@string/screensaver_settings_summary_either_long</item>
- <item>@string/screensaver_settings_summary_never</item>
</string-array>
<string-array name="when_to_start_screensaver_values" translatable="false">
<item>while_charging_only</item>
<item>while_docked_only</item>
<item>either_charging_or_docked</item>
- <item>never</item>
</string-array>
<string-array name="zen_mode_contacts_messages_entries" translatable="false">
diff --git a/res/values/colors.xml b/res/values/colors.xml
index fef8419..f972e29 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -205,4 +205,7 @@
<!-- Battery error text color -->
<color name="battery_info_error_color_black">@*android:color/primary_text_default_material_light</color>
+
+ <!-- Background for multiple user settings page avatars -->
+ <color name="user_avatar_color_bg">?androidprv:attr/colorSurface</color>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 4f2dd93..c44a1cb 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -134,6 +134,7 @@
<dimen name="avatar_length">48dp</dimen>
<dimen name="avatar_margin_top">56dp</dimen>
<dimen name="avatar_margin_end">24dp</dimen>
+ <dimen name="multiple_users_avatar_size">20dp</dimen>
<!-- Homepage title -->
<dimen name="homepage_title_margin_bottom">8dp</dimen>
@@ -275,9 +276,9 @@
<dimen name="accessibility_icon_size">32dp</dimen>
<dimen name="accessibility_icon_foreground_size">18dp</dimen>
- <!-- Accessibility quick settings tooltips -->
- <dimen name="accessibility_qs_tooltips_margin">20dp</dimen>
- <dimen name="accessibility_qs_tooltips_margin_top">27dp</dimen>
+ <!-- Accessibility quick settings tooltip -->
+ <dimen name="accessibility_qs_tooltip_margin">20dp</dimen>
+ <dimen name="accessibility_qs_tooltip_margin_top">27dp</dimen>
<!-- Restricted icon in switch bar -->
<dimen name="restricted_icon_margin_end">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0ae2b40..bd9cbbd 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3168,6 +3168,8 @@
<string name="style_suggestion_summary">Try different styles, wallpapers, and more</string>
<!-- Display settings screen, trigger for screen saver options -->
<string name="screensaver_settings_title">Screen saver</string>
+ <!-- The title for the toggle which disables/enables screen savers [CHAR_LIMIT=30] -->
+ <string name="screensaver_settings_toggle_title">Use screen saver</string>
<!-- Display settings screen, summary fragment for screen saver options, activated when docked or asleep and charging -->
<string name="screensaver_settings_summary_either_long">While charging or docked</string>
<!-- Dream settings screen, dialog option, activated when docked or asleep and charging -->
@@ -5552,12 +5554,28 @@
<string name="accessibility_service_primary_switch_title">Use <xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g></string>
<!-- Used in the accessibility service settings to open the activity. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_primary_open_title">Open <xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g></string>
- <!-- Used in the accessibility service settings to show quick settings tooltips for auto-added feature. [CHAR LIMIT=NONE] -->
- <string name="accessibility_service_auto_added_qs_tooltips_content"><xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g> added to Quick Settings. Swipe down to turn it on or off anytime.</string>
- <!-- Used in the accessibility service settings to show quick settings tooltips. [CHAR LIMIT=NONE] -->
- <string name="accessibility_service_qs_tooltips_content">You can also add <xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g> to Quick Settings from the top of your screen</string>
- <!-- Used in the accessibility action for accessibility quick settings tooltips to dismiss. [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_tooltips_dismiss">Dismiss</string>
+ <!-- Used in the accessibility service settings to show quick settings tooltip for auto-added feature. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_service_auto_added_qs_tooltip_content"><xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g> added to Quick Settings. Swipe down to turn it on or off anytime.</string>
+ <!-- Used in the accessibility service settings to show quick settings tooltip. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_service_qs_tooltip_content">You can also add <xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g> to Quick Settings from the top of your screen</string>
+ <!-- Used in the color correction settings to show quick settings tooltip for auto-added feature. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_color_correction_auto_added_qs_tooltip_content">Color correction added to Quick Settings. Swipe down to turn it on or off anytime.</string>
+ <!-- Used in the color correction settings to show quick settings tooltip. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_color_correction_qs_tooltip_content">You can also add color correction to Quick Settings from the top of your screen</string>
+ <!-- Used in the color inversion settings to show quick settings tooltip for auto-added feature. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_color_inversion_auto_added_qs_tooltip_content">Color inversion added to Quick Settings. Swipe down to turn it on or off anytime.</string>
+ <!-- Used in the color inversion settings to show quick settings tooltip. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_color_inversion_qs_tooltip_content">You can also add color inversion to Quick Settings from the top of your screen</string>
+ <!-- Used in the reduce bright colors settings to show quick settings tooltip for auto-added feature. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_reduce_bright_colors_auto_added_qs_tooltip_content">Extra dim added to Quick Settings. Swipe down to turn it on or off anytime.</string>
+ <!-- Used in the reduce bright colors settings to show quick settings tooltip. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_reduce_bright_colors_qs_tooltip_content">You can also add extra dim to Quick Settings from the top of your screen</string>
+ <!-- Used in the One-hand mode color to show quick settings tooltip for auto-added feature. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_one_handed_mode_auto_added_qs_tooltip_content">One-handed mode added to Quick Settings. Swipe down to turn it on or off anytime.</string>
+ <!-- Used in the One-hand mode settings to show quick settings tooltip. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_one_handed_mode_qs_tooltip_content">You can also add one-handed mode to Quick Settings from the top of your screen</string>
+ <!-- Used in the accessibility action for accessibility quick settings tooltip to dismiss. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_tooltip_dismiss">Dismiss</string>
<!-- Intro for color correction settings screen to control turning on/off the feature entirely. [CHAR LIMIT=NONE] -->
<string name="accessibility_daltonizer_about_intro_text" product="default">Adjust how colors display on your phone</string>
<!-- Intro for color correction settings screen to control turning on/off the feature entirely. [CHAR LIMIT=NONE] -->
@@ -5617,10 +5635,10 @@
<!-- Title for the accessibility audio adjustment page. [CHAR LIMIT=50] -->
<string name="accessibility_audio_adjustment_title">Audio adjustment</string>
<!-- Title for control audio description preference. [CHAR LIMIT=50] -->
- <string name="accessibility_toggle_audio_description_preference_title">Audio Description</string>
+ <string name="accessibility_toggle_audio_description_preference_title">Audio description</string>
<!-- Summary for accessibility preference for audio description when need
audio description in adopted apps. [CHAR_LIMIT=NONE] -->
- <string name="accessibility_audio_description_summary">Select audio sound track with audio description by default</string>
+ <string name="accessibility_audio_description_summary">Hear a description of what\u2019s happening on screen in supported movies and shows</string>
<!-- List of synonyms used in the settings search bar to find the "Audio Description. [CHAR LIMIT=NONE] -->
<string name="keywords_audio_description">audio description, audio, description, low vision,</string>
@@ -10619,7 +10637,7 @@
<!-- Body text of prompt dialog app can invoke to turn off optimization [CHAR LIMIT=NONE] -->
<string name="high_power_prompt_body">
Allowing <xliff:g id="app_name" example="Settings">%1$s</xliff:g> to always run in the background may reduce battery life.
- \n\nYou can change this later from Settings > Apps & notifications.</string>
+ \n\nYou can change this later from Settings > Apps.</string>
<!-- Summary of power usage for an app [CHAR LIMIT=NONE] -->
<string name="battery_summary"><xliff:g id="percentage" example="2">%1$s</xliff:g> use since last full charge</string>
<!-- Summary of power usage for an app within past 24 hr[CHAR LIMIT=NONE] -->
@@ -11791,7 +11809,7 @@
<string name="assistant_corner_gesture_summary">Swipe up from a bottom corner to invoke digital assistant app.</string>
<!-- Title text for holding a long press on Home button to invoke the digital assistant app. [CHAR LIMIT=60] -->
- <string name="assistant_long_press_home_gesture_title">Hold Home to invoke assistant</string>
+ <string name="assistant_long_press_home_gesture_title">Hold Home for Assistant</string>
<!-- Summary text for holding a long press on Home button to invoke the digital assistant app. [CHAR LIMIT=NONE] -->
<string name="assistant_long_press_home_gesture_summary">Press and hold the Home button to invoke digital assistant app.</string>
@@ -13625,7 +13643,7 @@
<!-- Title for default print service main switch. [CHAR LIMIT=50] -->
<string name="default_print_service_main_switch_title">Use print service</string>
<!-- Title for multiple users main switch. [CHAR LIMIT=50] -->
- <string name="multiple_users_main_switch_title">Use multiple users</string>
+ <string name="multiple_users_main_switch_title">Enable multiple users</string>
<!-- Title for wireless debugging main switch. [CHAR LIMIT=50] -->
<string name="wireless_debugging_main_switch_title">Use wireless debugging</string>
<!-- Title for graphics driver main switch. [CHAR LIMIT=50] -->
@@ -14008,4 +14026,13 @@
<!-- Text to explain an activity is a temporary placeholder [CHAR LIMIT=none] -->
<string name="placeholder_activity" translatable="false">*This is a temporary placeholder fallback activity.</string>
+
+ <!-- The title of the spatial audio [CHAR LIMIT=none] -->
+ <string name="bluetooth_details_spatial_audio_title">Spatial audio</string>
+ <!-- The summary of the spatial audio [CHAR LIMIT=none] -->
+ <string name="bluetooth_details_spatial_audio_summary">Immersive audio seems like it\u0027s coming from all around you. Only works with some media.</string>
+ <!-- The title of the head tracking [CHAR LIMIT=none] -->
+ <string name="bluetooth_details_head_tracking_title">Make audio more realistic</string>
+ <!-- The summary of the head tracking [CHAR LIMIT=none] -->
+ <string name="bluetooth_details_head_tracking_summary">Shift positioning of audio so it sounds more natural.</string>
</resources>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 2e253e2..509aed6 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -69,16 +69,6 @@
settings:keywords="@string/keywords_magnification"
settings:controller="com.android.settings.accessibility.MagnificationPreferenceController"/>
- <SwitchPreference
- android:key="toggle_audio_description"
- android:persistent="false"
- android:icon="@drawable/ic_audio_description"
- android:summary="@string/accessibility_audio_description_summary"
- android:title="@string/accessibility_toggle_audio_description_preference_title"
- settings:keywords="@string/keywords_audio_description"
- settings:searchable="true"
- settings:controller="com.android.settings.accessibility.AudioDescriptionPreferenceController"/>
-
</PreferenceCategory>
<PreferenceCategory
@@ -150,6 +140,16 @@
android:persistent="false"
android:title="@string/audio_category_title">
+ <SwitchPreference
+ android:key="toggle_audio_description"
+ android:persistent="false"
+ android:icon="@drawable/ic_audio_description"
+ android:summary="@string/accessibility_audio_description_summary"
+ android:title="@string/accessibility_toggle_audio_description_preference_title"
+ settings:keywords="@string/keywords_audio_description"
+ settings:searchable="true"
+ settings:controller="com.android.settings.accessibility.AudioDescriptionPreferenceController"/>
+
<Preference
android:key="hearing_aid_preference"
android:icon="@drawable/ic_hearing_aid"
diff --git a/res/xml/battery_saver_settings.xml b/res/xml/battery_saver_settings.xml
index e105920..862bcd7 100644
--- a/res/xml/battery_saver_settings.xml
+++ b/res/xml/battery_saver_settings.xml
@@ -23,6 +23,7 @@
<com.android.settingslib.widget.MainSwitchPreference
android:order="-100"
android:key="battery_saver"
+ android:title="@string/battery_saver_master_switch_title"
settings:controller="com.android.settings.fuelgauge.batterysaver.BatterySaverButtonPreferenceController"/>
<Preference
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index 9df1955..b21d5c9 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -53,6 +53,9 @@
android:key="device_companion_apps"/>
<PreferenceCategory
+ android:key="spatial_audio_group"/>
+
+ <PreferenceCategory
android:key="bluetooth_profiles"/>
<com.android.settingslib.widget.FooterPreference
diff --git a/res/xml/button_navigation_settings.xml b/res/xml/button_navigation_settings.xml
index d42f020..1153c67 100644
--- a/res/xml/button_navigation_settings.xml
+++ b/res/xml/button_navigation_settings.xml
@@ -21,19 +21,20 @@
android:title="@string/button_navigation_settings_activity_title"
settings:keywords="@string/keywords_button_navigation_settings">
- <PreferenceCategory
- android:key="assistant_button_navigation_category"
- android:persistent="false"
- android:title="@string/assistant_gesture_category_title">
+ <!-- Animation uses embedded PNGs and lottie requires asset folder to be set despite
+ embedding. -->
+ <com.android.settingslib.widget.IllustrationPreference
+ android:key="gesture_power_menu_video"
+ settings:searchable="false"
+ settings:lottie_imageAssetsFolder="button_nav_menu"
+ settings:lottie_rawRes="@raw/lottie_button_nav_menu"/>
- <SwitchPreference
- android:key="assistant_long_press_home_gesture"
- android:title="@string/assistant_long_press_home_gesture_title"
- android:summary="@string/assistant_long_press_home_gesture_summary"
- settings:controller="com.android.settings.gestures.ButtonNavigationSettingsAssistController"
- />
-
- </PreferenceCategory>
+ <SwitchPreference
+ android:key="assistant_long_press_home_gesture"
+ android:title="@string/assistant_long_press_home_gesture_title"
+ android:summary="@string/assistant_long_press_home_gesture_summary"
+ settings:controller="com.android.settings.gestures.ButtonNavigationSettingsAssistController"
+ />
</PreferenceScreen>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index cbf7704..ed1b4d2 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -297,7 +297,7 @@
android:title="@string/tethering_hardware_offload"
android:summary="@string/tethering_hardware_offload_summary" />
- <com.android.settingslib.RestrictedSwitchPreference
+ <com.android.settingslib.RestrictedPreference
android:key="default_usb_configuration"
android:fragment="com.android.settings.connecteddevice.usb.UsbDefaultFragment"
android:title="@string/usb_default_label"/>
diff --git a/res/xml/dream_fragment_overview.xml b/res/xml/dream_fragment_overview.xml
index 105cec4..0ca4869 100644
--- a/res/xml/dream_fragment_overview.xml
+++ b/res/xml/dream_fragment_overview.xml
@@ -19,26 +19,35 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/screensaver_settings_title">
- <PreferenceCategory
- android:title="@string/dream_picker_category">
- <com.android.settingslib.widget.LayoutPreference
- android:key="dream_picker"
- android:selectable="false"
- android:layout="@layout/dream_picker_layout"
- settings:controller="com.android.settings.dream.DreamPickerController"/>
- </PreferenceCategory>
+ <com.android.settingslib.widget.MainSwitchPreference
+ android:key="dream_main_settings_switch"
+ android:title="@string/screensaver_settings_toggle_title"
+ settings:controller="com.android.settings.dream.DreamMainSwitchPreferenceController"
+ settings:searchable="false"/>
<PreferenceCategory
- android:title="@string/dream_more_settings_category">
- <SwitchPreference
- android:key="dream_complications_toggle"
- android:title="@string/dream_complications_toggle_title"
- android:summary="@string/dream_complications_toggle_summary"
- settings:controller="com.android.settings.dream.DreamComplicationPreferenceController"/>
- <Preference
- android:key="when_to_start"
- android:title="@string/screensaver_settings_when_to_dream"
- android:fragment="com.android.settings.dream.WhenToDreamPicker"/>
+ android:key="dream_main_category">
+ <PreferenceCategory
+ android:title="@string/dream_picker_category">
+ <com.android.settingslib.widget.LayoutPreference
+ android:key="dream_picker"
+ android:selectable="false"
+ android:layout="@layout/dream_picker_layout"
+ settings:controller="com.android.settings.dream.DreamPickerController"/>
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/dream_more_settings_category">
+ <SwitchPreference
+ android:key="dream_complications_toggle"
+ android:title="@string/dream_complications_toggle_title"
+ android:summary="@string/dream_complications_toggle_summary"
+ settings:controller="com.android.settings.dream.DreamComplicationPreferenceController"/>
+ <Preference
+ android:key="when_to_start"
+ android:title="@string/screensaver_settings_when_to_dream"
+ android:fragment="com.android.settings.dream.WhenToDreamPicker"/>
+ </PreferenceCategory>
</PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/notification_access_permission_details.xml b/res/xml/notification_access_permission_details.xml
index cec383c..9867b6d 100644
--- a/res/xml/notification_access_permission_details.xml
+++ b/res/xml/notification_access_permission_details.xml
@@ -26,7 +26,7 @@
android:layout="@layout/settings_entity_header"
settings:controller="com.android.settings.applications.specialaccess.notificationaccess.HeaderPreferenceController"/>
- <com.android.settings.widget.FilterTouchesSwitchPreference
+ <com.android.settingslib.RestrictedSwitchPreference
android:key="notification_access_switch"
android:title="@string/notification_access_detail_switch"
settings:controller="com.android.settings.applications.specialaccess.notificationaccess.ApprovalPreferenceController"/>
diff --git a/res/xml/one_handed_settings.xml b/res/xml/one_handed_settings.xml
index 7406993..ab4d6f7 100644
--- a/res/xml/one_handed_settings.xml
+++ b/res/xml/one_handed_settings.xml
@@ -46,7 +46,7 @@
android:key="gesture_one_handed_action_pull_screen_down"
android:title="@string/one_handed_action_pull_down_screen_title"
android:summary="@string/one_handed_action_pull_down_screen_summary"
- settings:controller="com.android.settings.gesture_one_handed_mode_footer_textgestures.OneHandedActionPullDownPrefController"/>
+ settings:controller="com.android.settings.gestures.OneHandedActionPullDownPrefController"/>
<com.android.settingslib.widget.SelectorWithWidgetPreference
android:key="gesture_one_handed_action_show_notification"
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index d5e61d0..ab54989 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -40,13 +40,11 @@
<com.android.settingslib.RestrictedPreference
android:key="user_add"
android:title="@string/user_add_user_or_profile_menu"
- android:icon="@drawable/ic_add_40dp"
android:order="20"/>
<com.android.settingslib.RestrictedPreference
android:key="supervised_user_add"
android:title="@*android:string/supervised_user_creation_label"
- android:icon="@*android:drawable/ic_add_supervised_user"
android:order="25"/>
<com.android.settingslib.RestrictedSwitchPreference
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 37d4a4e..d258cc2 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -144,8 +144,7 @@
public static final String EXTRA_SHOW_FRAGMENT_AS_SUBSETTING =
":settings:show_fragment_as_subsetting";
- public static final String EXTRA_IS_SECONDARY_LAYER_PAGE =
- ":settings:is_secondary_layer_page";
+ public static final String EXTRA_IS_SECOND_LAYER_PAGE = ":settings:is_second_layer_page";
/**
* Additional extra of Settings#ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK.
@@ -372,12 +371,12 @@
if (WizardManagerHelper.isAnySetupWizard(intent)) {
return false;
}
- final boolean isSecondaryLayerPage =
- intent.getBooleanExtra(EXTRA_IS_SECONDARY_LAYER_PAGE, false);
+ final boolean isSecondLayerPage =
+ intent.getBooleanExtra(EXTRA_IS_SECOND_LAYER_PAGE, false);
// TODO: move Settings's ActivityEmbeddingUtils to SettingsLib.
return !com.android.settingslib.activityembedding.ActivityEmbeddingUtils
- .shouldHideBackButton(this, isSecondaryLayerPage);
+ .shouldHideNavigateUpButton(this, isSecondLayerPage);
}
private boolean isSubSettings(Intent intent) {
diff --git a/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java
new file mode 100644
index 0000000..d272a0b
--- /dev/null
+++ b/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.PrimarySwitchPreference;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnCreate;
+import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
+
+/** PrimarySwitchPreferenceController that shows quick settings tooltip on first use. */
+public abstract class AccessibilityQuickSettingsPrimarySwitchPreferenceController
+ extends TogglePreferenceController
+ implements LifecycleObserver, OnCreate, OnSaveInstanceState {
+ private static final String KEY_SAVED_QS_TOOLTIP_RESHOW = "qs_tooltip_reshow";
+ private final Handler mHandler;
+ private PrimarySwitchPreference mPreference;
+ private AccessibilityQuickSettingsTooltipWindow mTooltipWindow;
+ private boolean mNeedsQSTooltipReshow = false;
+
+ /** Returns the accessibility tile component name. */
+ abstract ComponentName getTileComponentName();
+
+ /** Returns the accessibility tile tooltip content. */
+ abstract CharSequence getTileTooltipContent();
+
+ public AccessibilityQuickSettingsPrimarySwitchPreferenceController(Context context,
+ String preferenceKey) {
+ super(context, preferenceKey);
+ mHandler = new Handler(context.getMainLooper());
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ // Restore the tooltip.
+ if (savedInstanceState != null) {
+ if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_RESHOW)) {
+ mNeedsQSTooltipReshow = savedInstanceState.getBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW);
+ }
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ if (mTooltipWindow != null) {
+ outState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, mTooltipWindow.isShowing());
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ if (mNeedsQSTooltipReshow) {
+ mHandler.post(this::showQuickSettingsTooltipIfNeeded);
+ }
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ if (isChecked) {
+ showQuickSettingsTooltipIfNeeded();
+ }
+ return isChecked;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return false;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public int getSliceHighlightMenuRes() {
+ return R.string.menu_key_accessibility;
+ }
+
+ private void showQuickSettingsTooltipIfNeeded() {
+ final ComponentName tileComponentName = getTileComponentName();
+ if (tileComponentName == null) {
+ // Returns if no tile service assigned.
+ return;
+ }
+
+ if (!mNeedsQSTooltipReshow && AccessibilityQuickSettingUtils.hasValueInSharedPreferences(
+ mContext, tileComponentName)) {
+ // Returns if quick settings tooltip only show once.
+ return;
+ }
+
+ mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(mContext);
+ mTooltipWindow.setup(getTileTooltipContent(),
+ R.drawable.accessibility_auto_added_qs_tooltip_illustration);
+ mTooltipWindow.showAtTopCenter(mPreference.getSwitch());
+ AccessibilityQuickSettingUtils.optInValueToSharedPreferences(mContext, tileComponentName);
+ mNeedsQSTooltipReshow = false;
+ }
+}
diff --git a/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java b/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java
index 2c77102..bb6dba8 100644
--- a/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java
+++ b/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java
@@ -61,7 +61,7 @@
super.onInitializeAccessibilityNodeInfo(host, info);
final AccessibilityAction clickAction = new AccessibilityAction(
AccessibilityNodeInfo.ACTION_CLICK,
- mContext.getString(R.string.accessibility_quick_settings_tooltips_dismiss));
+ mContext.getString(R.string.accessibility_quick_settings_tooltip_dismiss));
info.addAction(clickAction);
}
@@ -80,7 +80,7 @@
* @param text text to be displayed
* @param imageResId the resource ID of the image drawable
*/
- public void setup(String text, @DrawableRes int imageResId) {
+ public void setup(CharSequence text, @DrawableRes int imageResId) {
this.setup(text, imageResId, /* closeDelayTimeMillis= */ 0);
}
@@ -94,13 +94,13 @@
* @param imageResId the resource ID of the image drawable
* @param closeDelayTimeMillis how long the popup window be auto-closed
*/
- public void setup(String text, @DrawableRes int imageResId, long closeDelayTimeMillis) {
+ public void setup(CharSequence text, @DrawableRes int imageResId, long closeDelayTimeMillis) {
this.mCloseDelayTimeMillis = closeDelayTimeMillis;
setBackgroundDrawable(new ColorDrawable(mContext.getColor(android.R.color.transparent)));
final LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
final View popupView =
- inflater.inflate(R.layout.accessibility_qs_tooltips, /* root= */ null);
+ inflater.inflate(R.layout.accessibility_qs_tooltip, /* root= */ null);
popupView.setFocusable(/* focusable= */ true);
popupView.setAccessibilityDelegate(mAccessibilityDelegate);
setContentView(popupView);
@@ -179,7 +179,7 @@
@VisibleForTesting
int getAvailableWindowWidth() {
final Resources res = mContext.getResources();
- final int padding = res.getDimensionPixelSize(R.dimen.accessibility_qs_tooltips_margin);
+ final int padding = res.getDimensionPixelSize(R.dimen.accessibility_qs_tooltip_margin);
final int screenWidth = res.getDisplayMetrics().widthPixels;
return screenWidth - padding * 2;
}
diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
index 59618d6..a25c4a6 100644
--- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
@@ -83,8 +83,8 @@
/** Returns the accessibility tile component name. */
protected abstract ComponentName getTileComponentName();
- /** Returns the accessibility tile feature name. */
- protected abstract CharSequence getTileName();
+ /** Returns the accessibility tile tooltip content. */
+ protected abstract CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type);
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -148,7 +148,7 @@
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- // Reshow tooltips when activity recreate, such as rotate device.
+ // Reshow tooltip when activity recreate, such as rotate device.
if (mNeedsQSTooltipReshow) {
getView().post(this::showQuickSettingsTooltipIfNeeded);
}
@@ -499,21 +499,17 @@
return;
}
- final CharSequence tileName = getTileName();
- if (TextUtils.isEmpty(tileName)) {
- // Returns if no title of tile service assigned.
+ final CharSequence content = getTileTooltipContent(mNeedsQSTooltipType);
+ if (TextUtils.isEmpty(content)) {
+ // Returns if no content of tile tooltip assigned.
return;
}
- final int titleResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT
- ? R.string.accessibility_service_qs_tooltips_content
- : R.string.accessibility_service_auto_added_qs_tooltips_content;
- final String title = getString(titleResId, tileName);
final int imageResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT
- ? R.drawable.accessibility_qs_tooltips_illustration
- : R.drawable.accessibility_auto_added_qs_tooltips_illustration;
+ ? R.drawable.accessibility_qs_tooltip_illustration
+ : R.drawable.accessibility_auto_added_qs_tooltip_illustration;
mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext());
- mTooltipWindow.setup(title, imageResId);
+ mTooltipWindow.setup(content, imageResId);
mTooltipWindow.showAtTopCenter(getView());
AccessibilityQuickSettingUtils.optInValueToSharedPreferences(getContext(),
tileComponentName);
diff --git a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
index b04582f..3adef6d 100644
--- a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
@@ -41,6 +41,7 @@
import androidx.preference.Preference;
import com.android.settings.R;
+import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.overlay.FeatureFactory;
import java.util.ArrayList;
@@ -128,12 +129,21 @@
}
@Override
- CharSequence getTileName() {
+ CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
final ComponentName componentName = getTileComponentName();
if (componentName == null) {
return null;
}
- return loadTileLabel(getPrefContext(), componentName);
+
+ final CharSequence tileName = loadTileLabel(getPrefContext(), componentName);
+ if (tileName == null) {
+ return null;
+ }
+
+ final int titleResId = type == QuickSettingsTooltipType.GUIDE_TO_EDIT
+ ? R.string.accessibility_service_qs_tooltip_content
+ : R.string.accessibility_service_auto_added_qs_tooltip_content;
+ return getString(titleResId, tileName);
}
@Override
diff --git a/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java b/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java
index 2018e05..7b40024 100644
--- a/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java
+++ b/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java
@@ -16,6 +16,9 @@
package com.android.settings.accessibility;
+import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_TILE_SERVICE_COMPONENT_NAME;
+
+import android.content.ComponentName;
import android.content.Context;
import android.database.ContentObserver;
import android.hardware.display.ColorDisplayManager;
@@ -30,14 +33,14 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
-import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
/** PreferenceController that shows the Reduce Bright Colors summary */
-public class ReduceBrightColorsPreferenceController extends TogglePreferenceController
+public class ReduceBrightColorsPreferenceController
+ extends AccessibilityQuickSettingsPrimarySwitchPreferenceController
implements LifecycleObserver, OnStart, OnStop {
private ContentObserver mSettingsContentObserver;
private PrimarySwitchPreference mPreference;
@@ -67,6 +70,7 @@
@Override
public boolean setChecked(boolean isChecked) {
+ super.setChecked(isChecked);
return mColorDisplayManager.setReduceBrightColorsActivated(isChecked);
}
@@ -105,8 +109,20 @@
Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED),
false, mSettingsContentObserver, UserHandle.USER_CURRENT);
}
+
@Override
public void onStop() {
mContext.getContentResolver().unregisterContentObserver(mSettingsContentObserver);
}
+
+ @Override
+ protected ComponentName getTileComponentName() {
+ return REDUCE_BRIGHT_COLORS_TILE_SERVICE_COMPONENT_NAME;
+ }
+
+ @Override
+ CharSequence getTileTooltipContent() {
+ return mContext.getText(
+ R.string.accessibility_reduce_bright_colors_auto_added_qs_tooltip_content);
+ }
}
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index 02da51e..e314036 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -47,6 +47,7 @@
import androidx.annotation.Nullable;
import com.android.settings.R;
+import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.accessibility.AccessibilityUtils;
@@ -239,12 +240,21 @@
}
@Override
- CharSequence getTileName() {
+ CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
final ComponentName componentName = getTileComponentName();
if (componentName == null) {
return null;
}
- return loadTileLabel(getPrefContext(), componentName);
+
+ final CharSequence tileName = loadTileLabel(getPrefContext(), componentName);
+ if (tileName == null) {
+ return null;
+ }
+
+ final int titleResId = type == QuickSettingsTooltipType.GUIDE_TO_EDIT
+ ? R.string.accessibility_service_qs_tooltip_content
+ : R.string.accessibility_service_auto_added_qs_tooltip_content;
+ return getString(titleResId, tileName);
}
@Override
diff --git a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
index 1f498d6..5883714 100644
--- a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
@@ -144,8 +144,10 @@
}
@Override
- CharSequence getTileName() {
- return getText(R.string.accessibility_display_inversion_preference_title);
+ CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
+ return getText(type == QuickSettingsTooltipType.GUIDE_TO_EDIT
+ ? R.string.accessibility_color_inversion_qs_tooltip_content
+ : R.string.accessibility_color_inversion_auto_added_qs_tooltip_content);
}
@Override
diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
index c4df5bf..183da96 100644
--- a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
@@ -201,8 +201,10 @@
}
@Override
- CharSequence getTileName() {
- return getText(R.string.accessibility_display_daltonizer_preference_title);
+ CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
+ return getText(type == QuickSettingsTooltipType.GUIDE_TO_EDIT
+ ? R.string.accessibility_color_correction_qs_tooltip_content
+ : R.string.accessibility_color_correction_auto_added_qs_tooltip_content);
}
@Override
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 69b8f75..ccdc78b 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -222,7 +222,7 @@
updatePreferenceOrder();
- // Reshow tooltips when activity recreate, such as rotate device.
+ // Reshow tooltip when activity recreate, such as rotate device.
if (mNeedsQSTooltipReshow) {
getView().post(this::showQuickSettingsTooltipIfNeeded);
}
@@ -331,8 +331,8 @@
/** Returns the accessibility tile component name. */
abstract ComponentName getTileComponentName();
- /** Returns the accessibility tile feature name. */
- abstract CharSequence getTileName();
+ /** Returns the accessibility tile tooltip content. */
+ abstract CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type);
protected void updateToggleServiceTitle(SettingsMainSwitchPreference switchPreference) {
final CharSequence title =
@@ -870,21 +870,17 @@
return;
}
- final CharSequence tileName = getTileName();
- if (TextUtils.isEmpty(tileName)) {
- // Returns if no title of tile service assigned.
+ final CharSequence content = getTileTooltipContent(mNeedsQSTooltipType);
+ if (TextUtils.isEmpty(content)) {
+ // Returns if no content of tile tooltip assigned.
return;
}
- final int titleResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT
- ? R.string.accessibility_service_qs_tooltips_content
- : R.string.accessibility_service_auto_added_qs_tooltips_content;
- final String title = getString(titleResId, tileName);
final int imageResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT
- ? R.drawable.accessibility_qs_tooltips_illustration
- : R.drawable.accessibility_auto_added_qs_tooltips_illustration;
+ ? R.drawable.accessibility_qs_tooltip_illustration
+ : R.drawable.accessibility_auto_added_qs_tooltip_illustration;
mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext());
- mTooltipWindow.setup(title, imageResId);
+ mTooltipWindow.setup(content, imageResId);
mTooltipWindow.showAtTopCenter(getView());
AccessibilityQuickSettingUtils.optInValueToSharedPreferences(getContext(),
tileComponentName);
diff --git a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java
index fb9c4a8..93884b7 100644
--- a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java
@@ -184,8 +184,10 @@
}
@Override
- CharSequence getTileName() {
- return getText(R.string.reduce_bright_colors_preference_title);
+ CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
+ return getText(type == QuickSettingsTooltipType.GUIDE_TO_EDIT
+ ? R.string.accessibility_reduce_bright_colors_qs_tooltip_content
+ : R.string.accessibility_reduce_bright_colors_auto_added_qs_tooltip_content);
}
@Override
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index 62f4282..1176fa4 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -47,6 +47,7 @@
import com.android.settings.DialogCreatable;
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType;
+import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import com.android.settings.utils.LocaleUtils;
@@ -405,7 +406,7 @@
}
@Override
- CharSequence getTileName() {
+ CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
return null;
}
diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java
index dee24df..124bb4f 100644
--- a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java
+++ b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java
@@ -197,7 +197,7 @@
addActivityFilter(activityFilters, Settings.class);
final Intent intent = new Intent(mContext, Settings.NetworkDashboardActivity.class);
- intent.putExtra(SettingsActivity.EXTRA_IS_SECONDARY_LAYER_PAGE, true);
+ intent.putExtra(SettingsActivity.EXTRA_IS_SECOND_LAYER_PAGE, true);
final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule(
activityFilters,
intent,
diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
index a43b9fd..0767e65 100644
--- a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
+++ b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
@@ -27,10 +27,10 @@
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.SwitchPreference;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.RestrictedSwitchPreference;
public class ApprovalPreferenceController extends BasePreferenceController {
@@ -78,9 +78,11 @@
@Override
public void updateState(Preference pref) {
- final SwitchPreference preference = (SwitchPreference) pref;
+ final RestrictedSwitchPreference preference =
+ (RestrictedSwitchPreference) pref;
final CharSequence label = mPkgInfo.applicationInfo.loadLabel(mPm);
- preference.setChecked(isServiceEnabled(mCn));
+ final boolean isEnabled = isServiceEnabled(mCn);
+ preference.setChecked(isEnabled);
preference.setOnPreferenceChangeListener((p, newValue) -> {
final boolean access = (Boolean) newValue;
if (!access) {
@@ -103,6 +105,7 @@
return false;
}
});
+ preference.updateState(mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isEnabled);
}
public void disable(final ComponentName cn) {
diff --git a/src/com/android/settings/biometrics/BiometricNavigationUtils.java b/src/com/android/settings/biometrics/BiometricNavigationUtils.java
index b747faf..32d3a32 100644
--- a/src/com/android/settings/biometrics/BiometricNavigationUtils.java
+++ b/src/com/android/settings/biometrics/BiometricNavigationUtils.java
@@ -37,7 +37,11 @@
*/
public class BiometricNavigationUtils {
- private final int mUserId = UserHandle.myUserId();
+ private final int mUserId;
+
+ public BiometricNavigationUtils(int userId) {
+ mUserId = userId;
+ }
/**
* Tries to launch the Settings screen if Quiet Mode is not enabled
diff --git a/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java b/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java
index 617529f..f61f99c 100644
--- a/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java
@@ -60,7 +60,7 @@
.getSecurityFeatureProvider()
.getLockPatternUtils(context);
mProfileChallengeUserId = Utils.getManagedProfileId(mUm, mUserId);
- mBiometricNavigationUtils = new BiometricNavigationUtils();
+ mBiometricNavigationUtils = new BiometricNavigationUtils(getUserId());
}
@Override
diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java
index 27e3ae7..ba09e5f 100644
--- a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java
@@ -56,7 +56,7 @@
public CombinedBiometricStatusPreferenceController(
Context context, String key, Lifecycle lifecycle) {
super(context, key);
- mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(context);
+ mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(context, getUserId());
if (lifecycle != null) {
lifecycle.addObserver(this);
diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java
index a7554c8..f5ad76b 100644
--- a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java
+++ b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java
@@ -20,7 +20,6 @@
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
-import android.os.UserHandle;
import androidx.annotation.Nullable;
@@ -35,17 +34,18 @@
*/
public class CombinedBiometricStatusUtils {
- private final int mUserId = UserHandle.myUserId();
+ private final int mUserId;
private final Context mContext;
@Nullable
FingerprintManager mFingerprintManager;
@Nullable
FaceManager mFaceManager;
- public CombinedBiometricStatusUtils(Context context) {
+ public CombinedBiometricStatusUtils(Context context, int userId) {
mContext = context;
mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
mFaceManager = Utils.getFaceManagerOrNull(context);
+ mUserId = userId;
}
/**
@@ -56,6 +56,13 @@
}
/**
+ * Returns whether at least one face template or fingerprint has been enrolled.
+ */
+ public boolean hasEnrolled() {
+ return hasEnrolledFingerprints() || hasEnrolledFace();
+ }
+
+ /**
* Returns the {@link EnforcedAdmin} in case parental consent is required to change both
* face and fingerprint settings.
*
@@ -84,8 +91,7 @@
public String getSummary() {
final int numFingerprintsEnrolled = mFingerprintManager != null
? mFingerprintManager.getEnrolledFingerprints(mUserId).size() : 0;
- final boolean faceEnrolled = mFaceManager != null
- && mFaceManager.hasEnrolledTemplates(mUserId);
+ final boolean faceEnrolled = hasEnrolledFace();
if (faceEnrolled && numFingerprintsEnrolled > 1) {
return mContext.getString(
@@ -105,6 +111,14 @@
}
}
+ private boolean hasEnrolledFingerprints() {
+ return mFingerprintManager != null && mFingerprintManager.hasEnrolledFingerprints(mUserId);
+ }
+
+ private boolean hasEnrolledFace() {
+ return mFaceManager != null && mFaceManager.hasEnrolledTemplates(mUserId);
+ }
+
/**
* Returns the class name of the Settings page corresponding to combined biometric settings.
*/
diff --git a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
index cd0bc15..9b4b433 100644
--- a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
@@ -57,7 +57,7 @@
public FaceStatusPreferenceController(Context context, String key, Lifecycle lifecycle) {
super(context, key);
mFaceManager = Utils.getFaceManagerOrNull(context);
- mFaceStatusUtils = new FaceStatusUtils(context, mFaceManager);
+ mFaceStatusUtils = new FaceStatusUtils(context, mFaceManager, getUserId());
if (lifecycle != null) {
lifecycle.addObserver(this);
diff --git a/src/com/android/settings/biometrics/face/FaceStatusUtils.java b/src/com/android/settings/biometrics/face/FaceStatusUtils.java
index dd32708..1749aca 100644
--- a/src/com/android/settings/biometrics/face/FaceStatusUtils.java
+++ b/src/com/android/settings/biometrics/face/FaceStatusUtils.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.face.FaceManager;
-import android.os.UserHandle;
import com.android.settings.R;
import com.android.settings.Settings;
@@ -32,13 +31,14 @@
*/
public class FaceStatusUtils {
- private final int mUserId = UserHandle.myUserId();
+ private final int mUserId;
private final Context mContext;
private final FaceManager mFaceManager;
- public FaceStatusUtils(Context context, FaceManager faceManager) {
+ public FaceStatusUtils(Context context, FaceManager faceManager, int userId) {
mContext = context;
mFaceManager = faceManager;
+ mUserId = userId;
}
/**
@@ -75,7 +75,10 @@
: FaceEnrollIntroduction.class.getName();
}
- private boolean hasEnrolled() {
+ /**
+ * Returns whether at least one face template has been enrolled.
+ */
+ public boolean hasEnrolled() {
return mFaceManager.hasEnrolledTemplates(mUserId);
}
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java
index 646af4d..62edcf0 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java
@@ -58,7 +58,7 @@
super(context, key);
mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
mFingerprintStatusUtils =
- new FingerprintStatusUtils(context, mFingerprintManager);
+ new FingerprintStatusUtils(context, mFingerprintManager, getUserId());
if (lifecycle != null) {
lifecycle.addObserver(this);
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java
index 36edd2e..5707f32 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.fingerprint.FingerprintManager;
-import android.os.UserHandle;
import com.android.settings.R;
import com.android.settings.Utils;
@@ -31,13 +30,15 @@
*/
public class FingerprintStatusUtils {
- private final int mUserId = UserHandle.myUserId();
+ private final int mUserId;
private final Context mContext;
private final FingerprintManager mFingerprintManager;
- public FingerprintStatusUtils(Context context, FingerprintManager fingerprintManager) {
+ public FingerprintStatusUtils(Context context, FingerprintManager fingerprintManager,
+ int userId) {
mContext = context;
mFingerprintManager = fingerprintManager;
+ mUserId = userId;
}
/**
@@ -81,7 +82,10 @@
: FingerprintEnrollIntroduction.class.getName();
}
- private boolean hasEnrolled() {
+ /**
+ * Returns whether at least one fingerprint has been enrolled.
+ */
+ public boolean hasEnrolled() {
return mFingerprintManager.hasEnrolledFingerprints(mUserId);
}
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
new file mode 100644
index 0000000..89d923d
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.content.Context;
+import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.Spatializer;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.R;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+/**
+ * The controller of the Spatial audio setting in the bluetooth detail settings.
+ */
+public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsController
+ implements Preference.OnPreferenceClickListener {
+
+ private static final String TAG = "BluetoothSpatialAudioController";
+ private static final String KEY_SPATIAL_AUDIO_GROUP = "spatial_audio_group";
+ private static final String KEY_SPATIAL_AUDIO = "spatial_audio";
+ private static final String KEY_HEAD_TRACKING = "head_tracking";
+
+ private final Spatializer mSpatializer;
+
+ @VisibleForTesting
+ PreferenceCategory mProfilesContainer;
+ @VisibleForTesting
+ AudioDeviceAttributes mAudioDevice;
+
+ public BluetoothDetailsSpatialAudioController(
+ Context context,
+ PreferenceFragmentCompat fragment,
+ CachedBluetoothDevice device,
+ Lifecycle lifecycle) {
+ super(context, fragment, device, lifecycle);
+ AudioManager audioManager = context.getSystemService(AudioManager.class);
+ mSpatializer = audioManager.getSpatializer();
+ mAudioDevice = new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_OUTPUT,
+ AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
+ mCachedDevice.getAddress());
+
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mSpatializer.isAvailableForDevice(mAudioDevice) ? true : false;
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ SwitchPreference switchPreference = (SwitchPreference) preference;
+ String key = switchPreference.getKey();
+ if (TextUtils.equals(key, KEY_SPATIAL_AUDIO)) {
+ if (switchPreference.isChecked()) {
+ mSpatializer.addCompatibleAudioDevice(mAudioDevice);
+ } else {
+ mSpatializer.removeCompatibleAudioDevice(mAudioDevice);
+ }
+ refresh();
+ return true;
+ } else if (TextUtils.equals(key, KEY_HEAD_TRACKING)) {
+ mSpatializer.setHeadTrackerEnabled(switchPreference.isChecked(), mAudioDevice);
+ return true;
+ } else {
+ Log.w(TAG, "invalid key name.");
+ return false;
+ }
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_SPATIAL_AUDIO_GROUP;
+ }
+
+ @Override
+ protected void init(PreferenceScreen screen) {
+ mProfilesContainer = screen.findPreference(getPreferenceKey());
+ mProfilesContainer.setLayoutResource(R.layout.preference_bluetooth_profile_category);
+ refresh();
+ }
+
+ @Override
+ protected void refresh() {
+ SwitchPreference spatialAudioPref = mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO);
+ if (spatialAudioPref == null) {
+ spatialAudioPref = createSpatialAudioPreference(mProfilesContainer.getContext());
+ mProfilesContainer.addPreference(spatialAudioPref);
+ }
+
+ boolean isSpatialAudioOn = mSpatializer.getCompatibleAudioDevices().contains(mAudioDevice);
+ Log.d(TAG, "refresh() isSpatialAudioOn : " + isSpatialAudioOn);
+ spatialAudioPref.setChecked(isSpatialAudioOn);
+
+ SwitchPreference headTrackingPref = mProfilesContainer.findPreference(KEY_HEAD_TRACKING);
+ if (headTrackingPref == null) {
+ headTrackingPref = createHeadTrackingPreference(mProfilesContainer.getContext());
+ mProfilesContainer.addPreference(headTrackingPref);
+ }
+
+ boolean isHeadTrackingAvailable =
+ isSpatialAudioOn && mSpatializer.hasHeadTracker(mAudioDevice);
+ Log.d(TAG, "refresh() has head tracker : " + mSpatializer.hasHeadTracker(mAudioDevice));
+ headTrackingPref.setVisible(isHeadTrackingAvailable);
+ if (isHeadTrackingAvailable) {
+ headTrackingPref.setChecked(mSpatializer.isHeadTrackerEnabled(mAudioDevice));
+ }
+ }
+
+ @VisibleForTesting
+ SwitchPreference createSpatialAudioPreference(Context context) {
+ SwitchPreference pref = new SwitchPreference(context);
+ pref.setKey(KEY_SPATIAL_AUDIO);
+ pref.setTitle(context.getString(R.string.bluetooth_details_spatial_audio_title));
+ pref.setSummary(context.getString(R.string.bluetooth_details_spatial_audio_summary));
+ pref.setOnPreferenceClickListener(this);
+ return pref;
+ }
+
+ @VisibleForTesting
+ SwitchPreference createHeadTrackingPreference(Context context) {
+ SwitchPreference pref = new SwitchPreference(context);
+ pref.setKey(KEY_HEAD_TRACKING);
+ pref.setTitle(context.getString(R.string.bluetooth_details_head_tracking_title));
+ pref.setSummary(context.getString(R.string.bluetooth_details_head_tracking_summary));
+ pref.setOnPreferenceClickListener(this);
+ return pref;
+ }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 4980ba3..6532482 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -187,6 +187,8 @@
lifecycle));
controllers.add(new BluetoothDetailsCompanionAppsController(context, this,
mCachedDevice, lifecycle));
+ controllers.add(new BluetoothDetailsSpatialAudioController(context, this, mCachedDevice,
+ lifecycle));
controllers.add(new BluetoothDetailsProfilesController(context, this, mManager,
mCachedDevice, lifecycle));
controllers.add(new BluetoothDetailsMacAddressController(context, this, mCachedDevice,
diff --git a/src/com/android/settings/core/SubSettingLauncher.java b/src/com/android/settings/core/SubSettingLauncher.java
index 93a939f..e8c4219 100644
--- a/src/com/android/settings/core/SubSettingLauncher.java
+++ b/src/com/android/settings/core/SubSettingLauncher.java
@@ -122,9 +122,9 @@
return this;
}
- /** Decide whether the next page is secondary layer page or not. */
- public SubSettingLauncher setIsSecondaryLayerPage(boolean isSecondaryLayerPage) {
- mLaunchRequest.mIsSecondaryLayerPage = isSecondaryLayerPage;
+ /** Decide whether the next page is second layer page or not. */
+ public SubSettingLauncher setIsSecondLayerPage(boolean isSecondLayerPage) {
+ mLaunchRequest.mIsSecondLayerPage = isSecondLayerPage;
return this;
}
@@ -176,8 +176,8 @@
intent.addFlags(mLaunchRequest.mFlags);
intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
mLaunchRequest.mTransitionType);
- intent.putExtra(SettingsActivity.EXTRA_IS_SECONDARY_LAYER_PAGE,
- mLaunchRequest.mIsSecondaryLayerPage);
+ intent.putExtra(SettingsActivity.EXTRA_IS_SECOND_LAYER_PAGE,
+ mLaunchRequest.mIsSecondLayerPage);
return intent;
}
@@ -225,6 +225,6 @@
int mTransitionType;
Bundle mArguments;
Bundle mExtras;
- boolean mIsSecondaryLayerPage;
+ boolean mIsSecondLayerPage;
}
}
diff --git a/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java b/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java
index 87ca40f..bbe46b3 100644
--- a/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java
+++ b/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java
@@ -25,7 +25,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
public class DefaultUsbConfigurationPreferenceController extends
@@ -33,7 +33,7 @@
private static final String PREFERENCE_KEY = "default_usb_configuration";
- private RestrictedSwitchPreference mPreference;
+ private RestrictedPreference mPreference;
public DefaultUsbConfigurationPreferenceController(Context context) {
super(context);
diff --git a/src/com/android/settings/development/compat/PlatformCompatDashboard.java b/src/com/android/settings/development/compat/PlatformCompatDashboard.java
index c617e17..f8cbf21 100644
--- a/src/com/android/settings/development/compat/PlatformCompatDashboard.java
+++ b/src/com/android/settings/development/compat/PlatformCompatDashboard.java
@@ -31,6 +31,7 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.text.TextUtils;
import android.util.ArraySet;
import androidx.annotation.VisibleForTesting;
@@ -66,6 +67,8 @@
private AndroidBuildClassifier mAndroidBuildClassifier = new AndroidBuildClassifier();
+ private boolean mShouldStartAppPickerOnResume = true;
+
@VisibleForTesting
String mSelectedApp;
@@ -98,13 +101,67 @@
}
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
try {
mChanges = getPlatformCompat().listUIChanges();
} catch (RemoteException e) {
throw new RuntimeException("Could not list changes!", e);
}
+ if (icicle != null) {
+ mShouldStartAppPickerOnResume = false;
+ mSelectedApp = icicle.getString(COMPAT_APP);
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_COMPAT_CHANGE_APP) {
+ mShouldStartAppPickerOnResume = false;
+ switch (resultCode) {
+ case Activity.RESULT_OK:
+ mSelectedApp = data.getAction();
+ break;
+ case Activity.RESULT_CANCELED:
+ if (TextUtils.isEmpty(mSelectedApp)) {
+ finish();
+ }
+ break;
+ case AppPicker.RESULT_NO_MATCHING_APPS:
+ mSelectedApp = null;
+ break;
+ }
+ return;
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (isFinishingOrDestroyed()) {
+ return;
+ }
+ if (!mShouldStartAppPickerOnResume) {
+ if (TextUtils.isEmpty(mSelectedApp)) {
+ new AlertDialog.Builder(getContext())
+ .setTitle(R.string.platform_compat_dialog_title_no_apps)
+ .setMessage(R.string.platform_compat_dialog_text_no_apps)
+ .setPositiveButton(R.string.okay, (dialog, which) -> finish())
+ .setOnDismissListener(dialog -> finish())
+ .setCancelable(false)
+ .show();
+ return;
+ }
+ try {
+ final ApplicationInfo applicationInfo = getApplicationInfo();
+ addPreferences(applicationInfo);
+ return;
+ } catch (PackageManager.NameNotFoundException e) {
+ mShouldStartAppPickerOnResume = true;
+ mSelectedApp = null;
+ }
+ }
startAppPicker();
}
@@ -114,31 +171,6 @@
outState.putString(COMPAT_APP, mSelectedApp);
}
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == REQUEST_COMPAT_CHANGE_APP) {
- if (resultCode == Activity.RESULT_OK) {
- mSelectedApp = data.getAction();
- try {
- final ApplicationInfo applicationInfo = getApplicationInfo();
- addPreferences(applicationInfo);
- } catch (PackageManager.NameNotFoundException e) {
- startAppPicker();
- }
- } else if (resultCode == AppPicker.RESULT_NO_MATCHING_APPS) {
- new AlertDialog.Builder(getContext())
- .setTitle(R.string.platform_compat_dialog_title_no_apps)
- .setMessage(R.string.platform_compat_dialog_text_no_apps)
- .setPositiveButton(R.string.okay, (dialog, which) -> finish())
- .setOnDismissListener(dialog -> finish())
- .setCancelable(false)
- .show();
- }
- return;
- }
- super.onActivityResult(requestCode, resultCode, data);
- }
-
private void addPreferences(ApplicationInfo applicationInfo) {
getPreferenceScreen().removeAll();
getPreferenceScreen().addPreference(createAppPreference(applicationInfo));
diff --git a/src/com/android/settings/development/featureflags/FeatureFlagPreference.java b/src/com/android/settings/development/featureflags/FeatureFlagPreference.java
index 992aa0f..08ae760 100644
--- a/src/com/android/settings/development/featureflags/FeatureFlagPreference.java
+++ b/src/com/android/settings/development/featureflags/FeatureFlagPreference.java
@@ -52,10 +52,10 @@
FeatureFlagUtils.setEnabled(getContext(), mKey, isChecked);
}
- // A temporary logic for settings_hide_secondary_page_back_button_in_two_pane
+ // A temporary logic for settings_hide_second_layer_page_navigate_up_button_in_two_pane
// Remove it before Android T release.
if (TextUtils.equals(mKey,
- FeatureFlagUtils.SETTINGS_HIDE_SECONDARY_PAGE_BACK_BUTTON_IN_TWO_PANE)) {
+ FeatureFlagUtils.SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE)) {
Settings.Global.putString(getContext().getContentResolver(),
mKey, String.valueOf(isChecked));
}
diff --git a/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java b/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java
index c8f6280..beefc05 100644
--- a/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java
+++ b/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java
@@ -22,6 +22,7 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
+import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
@@ -51,16 +52,24 @@
private final String mDeviceStateDescription;
private final MetricsFeatureProvider mMetricsFeatureProvider;
- public DeviceStateAutoRotateSettingController(Context context, int deviceState,
- String deviceStateDescription, int order) {
+ @VisibleForTesting
+ DeviceStateAutoRotateSettingController(Context context, int deviceState,
+ String deviceStateDescription, int order,
+ MetricsFeatureProvider metricsFeatureProvider) {
super(context, getPreferenceKeyForDeviceState(deviceState));
- mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+ mMetricsFeatureProvider = metricsFeatureProvider;
mDeviceState = deviceState;
mDeviceStateDescription = deviceStateDescription;
mAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(context);
mOrder = order;
}
+ public DeviceStateAutoRotateSettingController(Context context, int deviceState,
+ String deviceStateDescription, int order) {
+ this(context, deviceState, deviceStateDescription, order,
+ FeatureFactory.getFactory(context).getMetricsFeatureProvider());
+ }
+
void init(Lifecycle lifecycle) {
lifecycle.addObserver(this);
}
@@ -108,12 +117,22 @@
@Override
public boolean setChecked(boolean isChecked) {
boolean isRotationLocked = !isChecked;
- mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK,
- isRotationLocked);
+ logSettingChanged(isChecked);
mAutoRotateSettingsManager.updateSetting(mDeviceState, isRotationLocked);
return true;
}
+ private void logSettingChanged(boolean isChecked) {
+ boolean isRotationLocked = !isChecked;
+ mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK,
+ isRotationLocked);
+
+ int actionCategory = isChecked
+ ? SettingsEnums.ACTION_ENABLE_AUTO_ROTATION_DEVICE_STATE
+ : SettingsEnums.ACTION_DISABLE_AUTO_ROTATION_DEVICE_STATE;
+ mMetricsFeatureProvider.action(mContext, actionCategory, /* value= */ mDeviceState);
+ }
+
@Override
public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) {
SearchIndexableRaw indexable = new SearchIndexableRaw(mContext);
diff --git a/src/com/android/settings/dream/DreamAdapter.java b/src/com/android/settings/dream/DreamAdapter.java
index f196500..27c32df 100644
--- a/src/com/android/settings/dream/DreamAdapter.java
+++ b/src/com/android/settings/dream/DreamAdapter.java
@@ -32,6 +32,7 @@
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R;
+import com.android.settingslib.utils.ColorUtil;
import java.util.List;
@@ -43,17 +44,20 @@
@LayoutRes
private final int mLayoutRes;
private int mLastSelectedPos = -1;
+ private boolean mEnabled = true;
/**
* View holder for each {@link IDreamItem}.
*/
private class DreamViewHolder extends RecyclerView.ViewHolder {
+ private static final int VALUE_ENABLED_ALPHA = 255;
private final TextView mTitleView;
private final TextView mSummaryView;
private final ImageView mPreviewView;
private final ImageView mPreviewPlaceholderView;
private final Button mCustomizeButton;
private final Context mContext;
+ private final int mDisabledAlphaValue;
DreamViewHolder(View view, Context context) {
super(view);
@@ -63,6 +67,7 @@
mTitleView = view.findViewById(R.id.title_text);
mSummaryView = view.findViewById(R.id.summary_text);
mCustomizeButton = view.findViewById(R.id.customize_button);
+ mDisabledAlphaValue = (int) (ColorUtil.getDisabledAlpha(context) * VALUE_ENABLED_ALPHA);
}
/**
@@ -88,10 +93,11 @@
mPreviewView.setImageDrawable(null);
mPreviewPlaceholderView.setVisibility(View.VISIBLE);
}
+ mPreviewView.setImageAlpha(getAlpha());
final Drawable icon = item.isActive()
? mContext.getDrawable(R.drawable.ic_dream_check_circle)
- : item.getIcon();
+ : item.getIcon().mutate();
if (icon instanceof VectorDrawable) {
icon.setTintList(
mContext.getColorStateList(R.color.dream_card_icon_color_state_list));
@@ -99,6 +105,7 @@
final int iconSize = mContext.getResources().getDimensionPixelSize(
R.dimen.dream_item_icon_size);
icon.setBounds(0, 0, iconSize, iconSize);
+ icon.setAlpha(getAlpha());
mTitleView.setCompoundDrawablesRelative(icon, null, null, null);
if (item.isActive()) {
@@ -109,7 +116,8 @@
}
mCustomizeButton.setOnClickListener(v -> item.onCustomizeClicked());
- mCustomizeButton.setVisibility(item.allowCustomization() ? View.VISIBLE : View.GONE);
+ mCustomizeButton.setVisibility(
+ item.allowCustomization() && mEnabled ? View.VISIBLE : View.GONE);
itemView.setOnClickListener(v -> {
item.onItemClicked();
@@ -118,6 +126,26 @@
}
notifyItemChanged(position);
});
+
+ setEnabledStateOnViews(itemView, mEnabled);
+ }
+
+ private int getAlpha() {
+ return mEnabled ? VALUE_ENABLED_ALPHA : mDisabledAlphaValue;
+ }
+
+ /**
+ * Makes sure the view (and any children) get the enabled state changed.
+ */
+ private void setEnabledStateOnViews(@NonNull View v, boolean enabled) {
+ v.setEnabled(enabled);
+
+ if (v instanceof ViewGroup) {
+ final ViewGroup vg = (ViewGroup) v;
+ for (int i = vg.getChildCount() - 1; i >= 0; i--) {
+ setEnabledStateOnViews(vg.getChildAt(i), enabled);
+ }
+ }
}
}
@@ -143,4 +171,14 @@
public int getItemCount() {
return mItemList.size();
}
+
+ /**
+ * Sets the enabled state of all items.
+ */
+ public void setEnabled(boolean enabled) {
+ if (mEnabled != enabled) {
+ mEnabled = enabled;
+ notifyDataSetChanged();
+ }
+ }
}
diff --git a/src/com/android/settings/dream/DreamMainSwitchPreferenceController.java b/src/com/android/settings/dream/DreamMainSwitchPreferenceController.java
new file mode 100644
index 0000000..1425d3a
--- /dev/null
+++ b/src/com/android/settings/dream/DreamMainSwitchPreferenceController.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.dream;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+
+import androidx.lifecycle.OnLifecycleEvent;
+
+import com.android.settings.widget.SettingsMainSwitchPreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.dream.DreamBackend;
+
+/**
+ * Preference controller for switching dreams on/off.
+ */
+public class DreamMainSwitchPreferenceController extends
+ SettingsMainSwitchPreferenceController implements LifecycleObserver {
+ static final String MAIN_SWITCH_PREF_KEY = "dream_main_settings_switch";
+ private final DreamBackend mBackend;
+
+ private final ContentObserver mObserver = new ContentObserver(
+ new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateState(mSwitchPreference);
+ }
+ };
+
+ public DreamMainSwitchPreferenceController(Context context, String key) {
+ super(context, key);
+ mBackend = DreamBackend.getInstance(context);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mBackend.isEnabled();
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ mBackend.setEnabled(isChecked);
+ return true;
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return false;
+ }
+
+ @Override
+ public int getSliceHighlightMenuRes() {
+ // not needed since it's not sliceable
+ return NO_RES;
+ }
+
+ @OnLifecycleEvent(ON_START)
+ void onStart() {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED),
+ /* notifyForDescendants= */ false, mObserver);
+ }
+
+ @OnLifecycleEvent(ON_STOP)
+ void onStop() {
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
+ }
+}
diff --git a/src/com/android/settings/dream/DreamPickerController.java b/src/com/android/settings/dream/DreamPickerController.java
index 201d6de..5afc492 100644
--- a/src/com/android/settings/dream/DreamPickerController.java
+++ b/src/com/android/settings/dream/DreamPickerController.java
@@ -16,11 +16,15 @@
package com.android.settings.dream;
+import static com.android.settings.dream.DreamMainSwitchPreferenceController.MAIN_SWITCH_PREF_KEY;
+
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.graphics.drawable.Drawable;
+import android.widget.Switch;
import androidx.annotation.Nullable;
+import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.recyclerview.widget.RecyclerView;
@@ -31,6 +35,8 @@
import com.android.settingslib.dream.DreamBackend;
import com.android.settingslib.dream.DreamBackend.DreamInfo;
import com.android.settingslib.widget.LayoutPreference;
+import com.android.settingslib.widget.MainSwitchPreference;
+import com.android.settingslib.widget.OnMainSwitchChangeListener;
import java.util.List;
import java.util.stream.Collectors;
@@ -38,8 +44,8 @@
/**
* Controller for the dream picker where the user can select a screensaver.
*/
-public class DreamPickerController extends BasePreferenceController {
- private static final String KEY = "dream_picker";
+public class DreamPickerController extends BasePreferenceController implements
+ OnMainSwitchChangeListener {
private final DreamBackend mBackend;
private final MetricsFeatureProvider mMetricsFeatureProvider;
@@ -48,12 +54,12 @@
private DreamInfo mActiveDream;
private DreamAdapter mAdapter;
- public DreamPickerController(Context context) {
- this(context, DreamBackend.getInstance(context));
+ public DreamPickerController(Context context, String key) {
+ this(context, key, DreamBackend.getInstance(context));
}
- public DreamPickerController(Context context, DreamBackend backend) {
- super(context, KEY);
+ public DreamPickerController(Context context, String key, DreamBackend backend) {
+ super(context, key);
mBackend = backend;
mDreamInfos = mBackend.getDreamInfos();
mActiveDream = getActiveDreamInfo(mDreamInfos);
@@ -61,11 +67,6 @@
}
@Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
public int getAvailabilityStatus() {
return mDreamInfos.size() > 0 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@@ -79,6 +80,8 @@
.map(DreamItem::new)
.collect(Collectors.toList()));
+ mAdapter.setEnabled(mBackend.isEnabled());
+
final LayoutPreference pref = screen.findPreference(getPreferenceKey());
if (pref == null) {
return;
@@ -89,6 +92,11 @@
new GridSpacingItemDecoration(mContext, R.dimen.dream_preference_card_padding));
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(mAdapter);
+
+ final Preference mainSwitchPref = screen.findPreference(MAIN_SWITCH_PREF_KEY);
+ if (mainSwitchPref instanceof MainSwitchPreference) {
+ ((MainSwitchPreference) mainSwitchPref).addOnSwitchChangeListener(this);
+ }
}
@Nullable
@@ -100,6 +108,13 @@
.orElse(null);
}
+ @Override
+ public void onSwitchChanged(Switch switchView, boolean isChecked) {
+ if (mAdapter != null) {
+ mAdapter.setEnabled(isChecked);
+ }
+ }
+
private class DreamItem implements IDreamItem {
DreamInfo mDreamInfo;
diff --git a/src/com/android/settings/dream/DreamSettings.java b/src/com/android/settings/dream/DreamSettings.java
index bfa19a9..d30f50f 100644
--- a/src/com/android/settings/dream/DreamSettings.java
+++ b/src/com/android/settings/dream/DreamSettings.java
@@ -16,6 +16,7 @@
package com.android.settings.dream;
+import static com.android.settings.dream.DreamMainSwitchPreferenceController.MAIN_SWITCH_PREF_KEY;
import static com.android.settingslib.dream.DreamBackend.EITHER;
import static com.android.settingslib.dream.DreamBackend.NEVER;
import static com.android.settingslib.dream.DreamBackend.WHILE_CHARGING;
@@ -25,10 +26,13 @@
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
+import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.Switch;
import androidx.annotation.VisibleForTesting;
+import androidx.preference.PreferenceCategory;
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R;
@@ -38,12 +42,14 @@
import com.android.settingslib.dream.DreamBackend;
import com.android.settingslib.dream.DreamBackend.WhenToDream;
import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.MainSwitchPreference;
+import com.android.settingslib.widget.OnMainSwitchChangeListener;
import java.util.ArrayList;
import java.util.List;
@SearchIndexable
-public class DreamSettings extends DashboardFragment {
+public class DreamSettings extends DashboardFragment implements OnMainSwitchChangeListener {
private static final String TAG = "DreamSettings";
static final String WHILE_CHARGING_ONLY = "while_charging_only";
@@ -51,6 +57,13 @@
static final String EITHER_CHARGING_OR_DOCKED = "either_charging_or_docked";
static final String NEVER_DREAM = "never";
+ private static final String MAIN_PREF_CATEGORY = "dream_main_category";
+
+ private MainSwitchPreference mMainSwitchPreference;
+ private PreferenceCategory mMainPrefCategory;
+ private Button mPreviewButton;
+ private RecyclerView mRecyclerView;
+
@WhenToDream
static int getSettingFromPrefKey(String key) {
switch (key) {
@@ -135,37 +148,58 @@
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new DreamPickerController(context));
controllers.add(new WhenToDreamPreferenceController(context));
return controllers;
}
@Override
- public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
- Bundle bundle) {
-
- final ViewGroup root = getActivity().findViewById(android.R.id.content);
- final Button previewButton = (Button) getActivity().getLayoutInflater().inflate(
- R.layout.dream_preview_button, root, false);
- root.addView(previewButton);
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
final DreamBackend dreamBackend = DreamBackend.getInstance(getContext());
- previewButton.setOnClickListener(v -> dreamBackend.preview(dreamBackend.getActiveDream()));
- final RecyclerView recyclerView = super.onCreateRecyclerView(inflater, parent, bundle);
- previewButton.post(() -> {
- recyclerView.setPadding(0, 0, 0, previewButton.getMeasuredHeight());
- });
- return recyclerView;
+ mMainSwitchPreference = findPreference(MAIN_SWITCH_PREF_KEY);
+ if (mMainSwitchPreference != null) {
+ mMainSwitchPreference.addOnSwitchChangeListener(this);
+ }
+
+ mMainPrefCategory = findPreference(MAIN_PREF_CATEGORY);
+ if (mMainPrefCategory != null) {
+ mMainPrefCategory.setEnabled(dreamBackend.isEnabled());
+ }
}
- public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER
- = new BaseSearchIndexProvider(R.xml.dream_fragment_overview) {
+ @Override
+ public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
+ Bundle bundle) {
+ final DreamBackend dreamBackend = DreamBackend.getInstance(getContext());
- @Override
- public List<AbstractPreferenceController> createPreferenceControllers(Context context) {
- return buildPreferenceControllers(context);
- }
- };
+ final ViewGroup root = getActivity().findViewById(android.R.id.content);
+ mPreviewButton = (Button) getActivity().getLayoutInflater().inflate(
+ R.layout.dream_preview_button, root, false);
+ mPreviewButton.setVisibility(dreamBackend.isEnabled() ? View.VISIBLE : View.GONE);
+ root.addView(mPreviewButton);
+ mPreviewButton.setOnClickListener(v -> dreamBackend.preview(dreamBackend.getActiveDream()));
+
+ mRecyclerView = super.onCreateRecyclerView(inflater, parent, bundle);
+ updatePaddingForPreviewButton();
+ return mRecyclerView;
+ }
+
+ private void updatePaddingForPreviewButton() {
+ mPreviewButton.post(() -> {
+ mRecyclerView.setPadding(0, 0, 0, mPreviewButton.getMeasuredHeight());
+ });
+ }
+
+ @Override
+ public void onSwitchChanged(Switch switchView, boolean isChecked) {
+ mMainPrefCategory.setEnabled(isChecked);
+ mPreviewButton.setVisibility(isChecked ? View.VISIBLE : View.GONE);
+ updatePaddingForPreviewButton();
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.dream_fragment_overview);
}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceController.java
index 2979151..d24f1b2 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceController.java
@@ -95,7 +95,6 @@
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
- mPreference.setTitle(mContext.getString(R.string.battery_saver_master_switch_title));
mPreference.addOnSwitchChangeListener(this);
mPreference.updateStatus(isChecked());
}
@@ -113,7 +112,6 @@
@Override
public boolean setChecked(boolean stateOn) {
// This screen already shows a warning, so we don't need another warning.
- mPreference.updateStatus(isChecked());
return BatterySaverUtils.setPowerSaveMode(mContext, stateOn,
false /* needFirstTimeWarning */);
}
diff --git a/src/com/android/settings/gestures/OneHandedSettings.java b/src/com/android/settings/gestures/OneHandedSettings.java
index 0e6b402..13ccbd6 100644
--- a/src/com/android/settings/gestures/OneHandedSettings.java
+++ b/src/com/android/settings/gestures/OneHandedSettings.java
@@ -131,8 +131,10 @@
}
@Override
- protected CharSequence getTileName() {
- return mFeatureName;
+ protected CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
+ return type == QuickSettingsTooltipType.GUIDE_TO_EDIT
+ ? getText(R.string.accessibility_one_handed_mode_qs_tooltip_content)
+ : getText(R.string.accessibility_one_handed_mode_auto_added_qs_tooltip_content);
}
@Override
diff --git a/src/com/android/settings/homepage/TopLevelSettings.java b/src/com/android/settings/homepage/TopLevelSettings.java
index 734e079..7d57834 100644
--- a/src/com/android/settings/homepage/TopLevelSettings.java
+++ b/src/com/android/settings/homepage/TopLevelSettings.java
@@ -119,7 +119,7 @@
? ((Instrumentable) caller).getMetricsCategory()
: Instrumentable.METRICS_CATEGORY_UNKNOWN)
.setTitleRes(-1)
- .setIsSecondaryLayerPage(true)
+ .setIsSecondLayerPage(true)
.launch();
return true;
}
diff --git a/src/com/android/settings/nearby/FastPairSettingsFragment.java b/src/com/android/settings/nearby/FastPairSettingsFragment.java
index f605cf1..702e90a 100644
--- a/src/com/android/settings/nearby/FastPairSettingsFragment.java
+++ b/src/com/android/settings/nearby/FastPairSettingsFragment.java
@@ -21,6 +21,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.nearby.NearbyManager;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -56,9 +57,9 @@
findPreference(SCAN_SWITCH_KEY));
mainSwitchPreference.addOnSwitchChangeListener(
(switchView, isChecked) ->
- Settings.Secure.putInt(getContentResolver(),
- Settings.Secure.FAST_PAIR_SCAN_ENABLED, isChecked ? 1 : 0));
- mainSwitchPreference.setChecked(isFastPairScanAvailable());
+ NearbyManager.setFastPairScanEnabled(getContext(), isChecked));
+ mainSwitchPreference.setChecked(
+ NearbyManager.getFastPairScanEnabled(getContext(), false));
Preference savedDevicePref = Objects.requireNonNull(
findPreference(SAVED_DEVICES_PREF_KEY));
@@ -89,11 +90,6 @@
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.fast_pair_settings);
- private boolean isFastPairScanAvailable() {
- return Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.FAST_PAIR_SCAN_ENABLED, 1) != 0;
- }
-
@Nullable
private ComponentName getSavedDevicesComponent() {
String savedDevicesComponent = Settings.Secure.getString(
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index ea864ea..faf5010 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -628,15 +628,7 @@
}
if (preference instanceof LongPressWifiEntryPreference) {
- final WifiEntry selectedEntry =
- ((LongPressWifiEntryPreference) preference).getWifiEntry();
-
- if (selectedEntry.shouldEditBeforeConnect()) {
- launchConfigNewNetworkFragment(selectedEntry);
- return true;
- }
-
- connect(selectedEntry, true /* editIfNoConfig */, true /* fullScreenEdit */);
+ onSelectedWifiPreferenceClick((LongPressWifiEntryPreference) preference);
} else if (preference == mAddWifiNetworkPreference) {
onAddNetworkPressed();
} else {
@@ -645,6 +637,25 @@
return true;
}
+ @VisibleForTesting
+ void onSelectedWifiPreferenceClick(LongPressWifiEntryPreference preference) {
+ final WifiEntry selectedEntry = preference.getWifiEntry();
+
+ if (selectedEntry.shouldEditBeforeConnect()) {
+ launchConfigNewNetworkFragment(selectedEntry);
+ return;
+ }
+
+ if (selectedEntry.canConnect()) {
+ connect(selectedEntry, true /* editIfNoConfig */, true /* fullScreenEdit */);
+ return;
+ }
+
+ if (selectedEntry.isSaved()) {
+ launchNetworkDetailsFragment(preference);
+ }
+ }
+
private void launchWifiDppConfiguratorActivity(WifiEntry wifiEntry) {
final Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntentOrNull(getContext(),
mWifiManager, wifiEntry);
@@ -984,7 +995,8 @@
return new FirstWifiEntryPreference(getPrefContext(), wifiEntry, this);
}
- private void launchNetworkDetailsFragment(LongPressWifiEntryPreference pref) {
+ @VisibleForTesting
+ void launchNetworkDetailsFragment(LongPressWifiEntryPreference pref) {
final WifiEntry wifiEntry = pref.getWifiEntry();
final Context context = getContext();
final CharSequence title =
@@ -1253,7 +1265,8 @@
}
}
- private void launchConfigNewNetworkFragment(WifiEntry wifiEntry) {
+ @VisibleForTesting
+ void launchConfigNewNetworkFragment(WifiEntry wifiEntry) {
final Bundle bundle = new Bundle();
bundle.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY,
wifiEntry.getKey());
diff --git a/src/com/android/settings/network/PrivateDnsPreferenceController.java b/src/com/android/settings/network/PrivateDnsPreferenceController.java
index 07d5714..ed6f9ed 100644
--- a/src/com/android/settings/network/PrivateDnsPreferenceController.java
+++ b/src/com/android/settings/network/PrivateDnsPreferenceController.java
@@ -85,9 +85,12 @@
@Override
public int getAvailabilityStatus() {
- return mContext.getResources().getBoolean(R.bool.config_show_private_dns_settings)
- ? AVAILABLE
- : UNSUPPORTED_ON_DEVICE;
+ if (!mContext.getResources().getBoolean(R.bool.config_show_private_dns_settings)) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ final UserManager userManager = mContext.getSystemService(UserManager.class);
+ if (userManager.isGuestUser()) return DISABLED_FOR_USER;
+ return AVAILABLE;
}
@Override
diff --git a/src/com/android/settings/notification/app/NotificationSettings.java b/src/com/android/settings/notification/app/NotificationSettings.java
index 9dc0b59..afc9a66 100644
--- a/src/com/android/settings/notification/app/NotificationSettings.java
+++ b/src/com/android/settings/notification/app/NotificationSettings.java
@@ -362,7 +362,8 @@
final String p = packages[i];
if (pkg.equals(p)) {
try {
- return mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
+ return mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES
+ | PackageManager.GET_PERMISSIONS);
} catch (NameNotFoundException e) {
Log.w(TAG, "Failed to load package " + pkg, e);
}
diff --git a/src/com/android/settings/notification/zen/ZenModeAddBypassingAppsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeAddBypassingAppsPreferenceController.java
index e752913..5cffb9c 100644
--- a/src/com/android/settings/notification/zen/ZenModeAddBypassingAppsPreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModeAddBypassingAppsPreferenceController.java
@@ -19,6 +19,7 @@
import android.app.Application;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
@@ -35,8 +36,10 @@
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.app.AppChannelsBypassingDndSettings;
+import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.AppPreference;
import java.util.ArrayList;
@@ -120,6 +123,24 @@
updateAppList(apps);
}
+ // Set the icon for the given preference to the entry icon from cache if available, or look
+ // it up.
+ private void updateIcon(Preference pref, ApplicationsState.AppEntry entry) {
+ synchronized (entry) {
+ final Drawable cachedIcon = AppUtils.getIconFromCache(entry);
+ if (cachedIcon != null && entry.mounted) {
+ pref.setIcon(cachedIcon);
+ } else {
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final Drawable icon = AppUtils.getIcon(mPrefContext, entry);
+ if (icon != null) {
+ ThreadUtils.postOnMainThread(() -> pref.setIcon(icon));
+ }
+ });
+ }
+ }
+ }
+
@VisibleForTesting
void updateAppList(List<ApplicationsState.AppEntry> apps) {
if (apps == null) {
@@ -135,7 +156,6 @@
List<Preference> appsWithNoBypassingDndNotificationChannels = new ArrayList<>();
for (ApplicationsState.AppEntry entry : apps) {
String pkg = entry.info.packageName;
- mApplicationsState.ensureIcon(entry);
final int appChannels = mNotificationBackend.getChannelCount(pkg, entry.info.uid);
final int appChannelsBypassingDnd = mNotificationBackend
.getNotificationChannelsBypassingDnd(pkg, entry.info.uid).getList().size();
@@ -161,7 +181,7 @@
});
}
pref.setTitle(BidiFormatter.getInstance().unicodeWrap(entry.label));
- pref.setIcon(entry.icon);
+ updateIcon(pref, entry);
appsWithNoBypassingDndNotificationChannels.add(pref);
}
}
diff --git a/src/com/android/settings/notification/zen/ZenModeAllBypassingAppsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeAllBypassingAppsPreferenceController.java
index b036d8f..4cbfacb 100644
--- a/src/com/android/settings/notification/zen/ZenModeAllBypassingAppsPreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModeAllBypassingAppsPreferenceController.java
@@ -19,6 +19,7 @@
import android.app.Application;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
@@ -35,8 +36,10 @@
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.app.AppChannelsBypassingDndSettings;
+import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.AppPreference;
import java.util.ArrayList;
@@ -111,6 +114,24 @@
updateAppList(apps);
}
+ // Set the icon for the given preference to the entry icon from cache if available, or look
+ // it up.
+ private void updateIcon(Preference pref, ApplicationsState.AppEntry entry) {
+ synchronized (entry) {
+ final Drawable cachedIcon = AppUtils.getIconFromCache(entry);
+ if (cachedIcon != null && entry.mounted) {
+ pref.setIcon(cachedIcon);
+ } else {
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final Drawable icon = AppUtils.getIcon(mPrefContext, entry);
+ if (icon != null) {
+ ThreadUtils.postOnMainThread(() -> pref.setIcon(icon));
+ }
+ });
+ }
+ }
+ }
+
@VisibleForTesting
void updateAppList(List<ApplicationsState.AppEntry> apps) {
if (mPreferenceCategory == null || apps == null) {
@@ -120,7 +141,6 @@
List<Preference> appsBypassingDnd = new ArrayList<>();
for (ApplicationsState.AppEntry app : apps) {
String pkg = app.info.packageName;
- mApplicationsState.ensureIcon(app);
final int appChannels = mNotificationBackend.getChannelCount(pkg, app.info.uid);
final int appChannelsBypassingDnd = mNotificationBackend
.getNotificationChannelsBypassingDnd(pkg, app.info.uid).getList().size();
@@ -147,7 +167,7 @@
});
}
pref.setTitle(BidiFormatter.getInstance().unicodeWrap(app.label));
- pref.setIcon(app.icon);
+ updateIcon(pref, app);
if (appChannels > appChannelsBypassingDnd) {
pref.setSummary(R.string.zen_mode_bypassing_apps_summary_some);
} else {
diff --git a/src/com/android/settings/safetycenter/BiometricsSafetySource.java b/src/com/android/settings/safetycenter/BiometricsSafetySource.java
index 59408c7..74d8e01 100644
--- a/src/com/android/settings/safetycenter/BiometricsSafetySource.java
+++ b/src/com/android/settings/safetycenter/BiometricsSafetySource.java
@@ -22,6 +22,7 @@
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
+import android.os.UserHandle;
import android.safetycenter.SafetyEvent;
import android.safetycenter.SafetySourceData;
import android.safetycenter.SafetySourceStatus;
@@ -47,9 +48,12 @@
return;
}
- final BiometricNavigationUtils biometricNavigationUtils = new BiometricNavigationUtils();
+ final int userId = UserHandle.myUserId();
+
+ final BiometricNavigationUtils biometricNavigationUtils = new BiometricNavigationUtils(
+ userId);
final CombinedBiometricStatusUtils combinedBiometricStatusUtils =
- new CombinedBiometricStatusUtils(context);
+ new CombinedBiometricStatusUtils(context, userId);
if (combinedBiometricStatusUtils.isAvailable()) {
final RestrictedLockUtils.EnforcedAdmin disablingAdmin =
@@ -61,12 +65,13 @@
combinedBiometricStatusUtils.getSettingsClassName(), disablingAdmin,
Bundle.EMPTY),
disablingAdmin == null /* enabled */,
+ combinedBiometricStatusUtils.hasEnrolled(),
safetyEvent);
return;
}
final FaceManager faceManager = Utils.getFaceManagerOrNull(context);
- final FaceStatusUtils faceStatusUtils = new FaceStatusUtils(context, faceManager);
+ final FaceStatusUtils faceStatusUtils = new FaceStatusUtils(context, faceManager, userId);
if (faceStatusUtils.isAvailable()) {
final RestrictedLockUtils.EnforcedAdmin disablingAdmin =
@@ -78,6 +83,7 @@
faceStatusUtils.getSettingsClassName(), disablingAdmin,
Bundle.EMPTY),
disablingAdmin == null /* enabled */,
+ faceStatusUtils.hasEnrolled(),
safetyEvent);
return;
@@ -85,7 +91,7 @@
final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context);
final FingerprintStatusUtils fingerprintStatusUtils = new FingerprintStatusUtils(context,
- fingerprintManager);
+ fingerprintManager, userId);
if (fingerprintStatusUtils.isAvailable()) {
final RestrictedLockUtils.EnforcedAdmin disablingAdmin =
@@ -97,6 +103,7 @@
fingerprintStatusUtils.getSettingsClassName(), disablingAdmin,
Bundle.EMPTY),
disablingAdmin == null /* enabled */,
+ fingerprintStatusUtils.hasEnrolled(),
safetyEvent);
}
}
@@ -110,12 +117,14 @@
}
private static void setBiometricSafetySourceData(Context context, String title, String summary,
- Intent clickIntent, boolean enabled, SafetyEvent safetyEvent) {
+ Intent clickIntent, boolean enabled, boolean hasEnrolled, SafetyEvent safetyEvent) {
final PendingIntent pendingIntent = createPendingIntent(context, clickIntent);
+ final int statusLevel =
+ enabled && hasEnrolled ? SafetySourceStatus.STATUS_LEVEL_OK
+ : SafetySourceStatus.STATUS_LEVEL_NONE;
- final SafetySourceStatus status = new SafetySourceStatus.Builder(title, summary,
- SafetySourceStatus.STATUS_LEVEL_NONE, pendingIntent)
- .setEnabled(enabled).build();
+ final SafetySourceStatus status = new SafetySourceStatus.Builder(
+ title, summary, statusLevel, pendingIntent).setEnabled(enabled).build();
final SafetySourceData safetySourceData =
new SafetySourceData.Builder().setStatus(status).build();
diff --git a/src/com/android/settings/safetycenter/LockScreenSafetySource.java b/src/com/android/settings/safetycenter/LockScreenSafetySource.java
index ad0bd3a..6cd7fa5 100644
--- a/src/com/android/settings/safetycenter/LockScreenSafetySource.java
+++ b/src/com/android/settings/safetycenter/LockScreenSafetySource.java
@@ -96,6 +96,10 @@
context,
new ScreenLockPreferenceDetailsUtils(context, SettingsEnums.SAFETY_CENTER),
new SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build());
+
+ // Also send refreshed safety center data for biometrics, since changing lockscreen settings
+ // can unset biometrics.
+ BiometricsSafetySource.onBiometricsChanged(context);
}
private static IconAction createGearMenuIconAction(Context context,
@@ -126,7 +130,7 @@
NO_SCREEN_LOCK_ISSUE_ID,
context.getString(R.string.no_screen_lock_issue_title),
context.getString(R.string.no_screen_lock_issue_summary),
- SafetySourceStatus.STATUS_LEVEL_RECOMMENDATION,
+ SafetySourceIssue.SEVERITY_LEVEL_RECOMMENDATION,
NO_SCREEN_LOCK_ISSUE_TYPE_ID)
.setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
.addAction(action).build();
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 64a65a4..8614c53 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -16,6 +16,8 @@
package com.android.settings.users;
+import static com.android.settingslib.Utils.getColorAttrDefaultColor;
+
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Dialog;
@@ -31,7 +33,9 @@
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.BlendMode;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -46,6 +50,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
+import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -523,6 +528,30 @@
startActivity(intent);
}
+ private void onAddGuestClicked() {
+ final UserCreatingDialog guestCreatingDialog =
+ new UserCreatingDialog(getActivity(), /* isGuest= */ true);
+ guestCreatingDialog.show();
+
+ ThreadUtils.postOnBackgroundThread(() -> {
+ mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_USER_GUEST_ADD);
+ Trace.beginSection("UserSettings.addGuest");
+ final UserInfo guest = mUserManager.createGuest(getContext());
+ Trace.endSection();
+
+ ThreadUtils.postOnMainThread(() -> {
+ guestCreatingDialog.dismiss();
+ if (guest == null) {
+ Toast.makeText(getContext(),
+ com.android.settingslib.R.string.add_guest_failed,
+ Toast.LENGTH_SHORT).show();
+ return;
+ }
+ openUserDetails(guest, true);
+ });
+ });
+ }
+
private void onRemoveUserClicked(int userId) {
synchronized (mUserLock) {
if (mRemovingUserId == -1 && !mAddingUser) {
@@ -1123,7 +1152,8 @@
&& WizardManagerHelper.isDeviceProvisioned(context)
&& mUserCaps.mUserSwitcherEnabled) {
mAddGuest.setVisible(true);
- mAddGuest.setIcon(getEncircledDefaultIcon());
+ Drawable icon = context.getDrawable(R.drawable.ic_account_circle);
+ mAddGuest.setIcon(centerAndTint(icon));
mAddGuest.setSelectable(true);
if (mGuestUserAutoCreated && mGuestCreationScheduled.get()) {
mAddGuest.setTitle(com.android.settingslib.R.string.user_guest);
@@ -1140,11 +1170,15 @@
private void updateAddUser(Context context) {
updateAddUserCommon(context, mAddUser, mUserCaps.mCanAddRestrictedProfile);
+ Drawable icon = context.getDrawable(R.drawable.ic_account_circle_filled);
+ mAddUser.setIcon(centerAndTint(icon));
}
private void updateAddSupervisedUser(Context context) {
if (!TextUtils.isEmpty(mConfigSupervisedUserCreationPackage)) {
updateAddUserCommon(context, mAddSupervisedUser, false);
+ Drawable icon = context.getDrawable(R.drawable.ic_add_supervised_user);
+ mAddSupervisedUser.setIcon(centerAndTint(icon));
} else {
mAddSupervisedUser.setVisible(false);
}
@@ -1162,6 +1196,7 @@
|| (canAddRestrictedProfile
&& mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_RESTRICTED));
addUser.setEnabled(canAddMoreUsers && !mAddingUser && canSwitchUserNow());
+
if (!canAddMoreUsers) {
addUser.setSummary(
getString(R.string.user_add_max_count, getRealUsersCount()));
@@ -1177,6 +1212,20 @@
}
}
+ private Drawable centerAndTint(Drawable icon) {
+ icon.setTintBlendMode(BlendMode.SRC_IN);
+ icon.setTint(getColorAttrDefaultColor(getContext(), android.R.attr.textColorPrimary));
+
+ Drawable bg = getContext().getDrawable(R.drawable.user_avatar_bg).mutate();
+ LayerDrawable ld = new LayerDrawable(new Drawable[] {bg, icon});
+ int size = getContext().getResources().getDimensionPixelSize(
+ R.dimen.multiple_users_avatar_size);
+ ld.setLayerSize(1, size, size);
+ ld.setLayerGravity(1, Gravity.CENTER);
+
+ return ld;
+ }
+
/**
* @return number of non-guest non-managed users
*/
@@ -1258,17 +1307,7 @@
return true;
} else if (pref == mAddGuest) {
mAddGuest.setEnabled(false); // prevent multiple tap issue
- mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_USER_GUEST_ADD);
- Trace.beginSection("UserSettings.addGuest");
- UserInfo guest = mUserManager.createGuest(getContext());
- Trace.endSection();
- if (guest == null) {
- Toast.makeText(getContext(),
- com.android.settingslib.R.string.add_user_failed,
- Toast.LENGTH_SHORT).show();
- return true;
- }
- openUserDetails(guest, true);
+ onAddGuestClicked();
return true;
}
return false;
diff --git a/src/com/android/settings/wifi/LongPressWifiEntryPreference.java b/src/com/android/settings/wifi/LongPressWifiEntryPreference.java
index bee92cf..c509f1a 100644
--- a/src/com/android/settings/wifi/LongPressWifiEntryPreference.java
+++ b/src/com/android/settings/wifi/LongPressWifiEntryPreference.java
@@ -17,6 +17,7 @@
import android.content.Context;
+import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceViewHolder;
@@ -43,4 +44,23 @@
view.itemView.setLongClickable(true);
}
}
+
+ @Override
+ public void refresh() {
+ super.refresh();
+ setEnabled(shouldEnabled());
+ }
+
+ @VisibleForTesting
+ boolean shouldEnabled() {
+ WifiEntry wifiEntry = getWifiEntry();
+ if (wifiEntry == null) return false;
+
+ boolean enabled = wifiEntry.canConnect();
+ // If Wi-Fi is connected or saved network, leave it enabled to disconnect or configure.
+ if (!enabled && (wifiEntry.canDisconnect() || wifiEntry.isSaved())) {
+ enabled = true;
+ }
+ return enabled;
+ }
}
diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java
index 6f955b2..1027792 100644
--- a/src/com/android/settings/wifi/WifiUtils.java
+++ b/src/com/android/settings/wifi/WifiUtils.java
@@ -41,6 +41,8 @@
private static final int SSID_ASCII_MIN_LENGTH = 1;
private static final int SSID_ASCII_MAX_LENGTH = 32;
+ private static final int PSK_PASSPHRASE_ASCII_MIN_LENGTH = 8;
+ private static final int PSK_PASSPHRASE_ASCII_MAX_LENGTH = 63;
public static boolean isSSIDTooLong(String ssid) {
if (TextUtils.isEmpty(ssid)) {
@@ -62,6 +64,13 @@
public static boolean isHotspotPasswordValid(String password, int securityType) {
final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
try {
+ if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK
+ || securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) {
+ if (password.length() < PSK_PASSPHRASE_ASCII_MIN_LENGTH
+ || password.length() > PSK_PASSPHRASE_ASCII_MAX_LENGTH) {
+ return false;
+ }
+ }
configBuilder.setPassphrase(password, securityType);
} catch (IllegalArgumentException e) {
return false;
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest.java
new file mode 100644
index 0000000..89c9120
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_SAVED_QS_TOOLTIP_RESHOW;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
+
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.PreferenceViewHolder;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.testutils.shadow.ShadowFragment;
+import com.android.settingslib.PrimarySwitchPreference;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowApplication;
+
+/**
+ * Tests for {@link AccessibilityQuickSettingsPrimarySwitchPreferenceController}.
+ */
+@RunWith(RobolectricTestRunner.class)
+public class AccessibilityQuickSettingsPrimarySwitchPreferenceControllerTest {
+
+ private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example";
+ private static final String PLACEHOLDER_TILE_CLASS_NAME =
+ PLACEHOLDER_PACKAGE_NAME + "tile.placeholder";
+ private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName(
+ PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME);
+ private static final CharSequence PLACEHOLDER_TILE_CONTENT =
+ PLACEHOLDER_TILE_CLASS_NAME + ".tile.content";
+ private static final String TEST_KEY = "test_pref_key";
+ private static final String TEST_TITLE = "test_title";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Spy
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+
+ private TestAccessibilityQuickSettingsPrimarySwitchPreferenceController mController;
+ private PrimarySwitchPreference mPreference;
+ private TestFragment mFragment;
+ private PreferenceScreen mScreen;
+ private PreferenceViewHolder mHolder;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private PreferenceManager mPreferenceManager;
+
+ private static PopupWindow getLatestPopupWindow() {
+ final ShadowApplication shadowApplication =
+ Shadow.extract(ApplicationProvider.getApplicationContext());
+ return shadowApplication.getLatestPopupWindow();
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext.setTheme(R.style.Theme_AppCompat);
+ mFragment = spy(new TestFragment());
+ when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
+ when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
+ when(mFragment.getContext()).thenReturn(mContext);
+ mScreen = spy(new PreferenceScreen(mContext, /* attrs= */ null));
+ when(mScreen.getPreferenceManager()).thenReturn(mPreferenceManager);
+ doReturn(mScreen).when(mFragment).getPreferenceScreen();
+
+ mPreference = new PrimarySwitchPreference(mContext);
+ mPreference.setKey(TEST_KEY);
+ mPreference.setTitle(TEST_TITLE);
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ mHolder = PreferenceViewHolder.createInstanceForTests(inflater.inflate(
+ com.android.settingslib.R.layout.preference_two_target, null));
+ LinearLayout mWidgetView = mHolder.itemView.findViewById(android.R.id.widget_frame);
+ inflater.inflate(R.layout.preference_widget_primary_switch, mWidgetView, true);
+ mPreference.onBindViewHolder(mHolder);
+
+ mController = new TestAccessibilityQuickSettingsPrimarySwitchPreferenceController(mContext,
+ TEST_KEY);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void setChecked_showTooltipView() {
+ mController.setChecked(true);
+
+ assertThat(getLatestPopupWindow().isShowing()).isTrue();
+ }
+
+ @Test
+ public void setChecked_tooltipViewShown_notShowTooltipView() {
+ mController.setChecked(true);
+ getLatestPopupWindow().dismiss();
+ mController.setChecked(false);
+
+ mController.setChecked(true);
+
+ assertThat(getLatestPopupWindow().isShowing()).isFalse();
+ }
+
+ @Test
+ @Config(shadows = ShadowFragment.class)
+ public void restoreValueFromSavedInstanceState_showTooltipView() {
+ mController.setChecked(true);
+ final Bundle savedInstanceState = new Bundle();
+ savedInstanceState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true);
+
+ mFragment.onCreate(savedInstanceState);
+ mController.displayPreference(mScreen);
+
+ assertThat(getLatestPopupWindow().isShowing()).isTrue();
+ }
+
+ public static class TestAccessibilityQuickSettingsPrimarySwitchPreferenceController
+ extends AccessibilityQuickSettingsPrimarySwitchPreferenceController {
+
+ public TestAccessibilityQuickSettingsPrimarySwitchPreferenceController(Context context,
+ String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ ComponentName getTileComponentName() {
+ return PLACEHOLDER_TILE_COMPONENT_NAME;
+ }
+
+ @Override
+ CharSequence getTileTooltipContent() {
+ return PLACEHOLDER_TILE_CONTENT;
+ }
+ }
+
+ private static class TestFragment extends SettingsPreferenceFragment {
+
+ @Override
+ protected boolean shouldSkipForInitialSUW() {
+ return false;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return 0;
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java
index 3fec81a..49602bc 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java
@@ -67,7 +67,7 @@
@Test
public void initTooltipView_atMostAvailableTextWidth() {
final String quickSettingsTooltipsContent = mContext.getString(
- R.string.accessibility_service_qs_tooltips_content, TEST_PACKAGE_NAME);
+ R.string.accessibility_service_qs_tooltip_content, TEST_PACKAGE_NAME);
mTooltipView.setup(quickSettingsTooltipsContent, TEST_RES_ID);
final int getMaxWidth = mTooltipView.getAvailableWindowWidth();
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivityTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivityTest.java
deleted file mode 100644
index 65b0647..0000000
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivityTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.settings.accessibility;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Intent;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.settings.R;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-@SmallTest
-public class AccessibilitySettingsForSetupWizardActivityTest {
-
- @Test
- public void createSetupAccessibilityActivity_shouldBeSUWTheme() {
- final Intent intent = new Intent();
- AccessibilitySettingsForSetupWizardActivity activity =
- Robolectric.buildActivity(AccessibilitySettingsForSetupWizardActivity.class,
- intent).get();
-
- assertThat(activity.getThemeResId()).isEqualTo(R.style.GlifV3Theme_Light);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index f7c546f..c1950be 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -20,6 +20,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeast;
@@ -31,6 +33,7 @@
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityShortcutInfo;
+import android.app.AppOpsManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -110,6 +113,8 @@
@Mock
private PreferenceManager mPreferenceManager;
private ShadowAccessibilityManager mShadowAccessibilityManager;
+ @Mock
+ private AppOpsManager mAppOpsManager;
@Before
public void setup() {
@@ -121,6 +126,9 @@
when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
mContext.setTheme(R.style.Theme_AppCompat);
+ when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
+ when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS),
+ anyInt(), anyString())).thenReturn(AppOpsManager.MODE_ALLOWED);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
index d05600a..c7a5884 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
@@ -73,6 +73,8 @@
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CLASS_NAME);
private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName(
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME);
+ private static final String PLACEHOLDER_TILE_TOOLTIP_CONTENT =
+ PLACEHOLDER_PACKAGE_NAME + "tooltip_content";
private static final String PLACEHOLDER_DIALOG_TITLE = "title";
private static final String SOFTWARE_SHORTCUT_KEY =
@@ -281,8 +283,8 @@
}
@Override
- protected CharSequence getTileName() {
- return PLACEHOLDER_PACKAGE_NAME;
+ protected CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
+ return PLACEHOLDER_TILE_TOOLTIP_CONTENT;
}
@Override
diff --git a/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java
index c44352f..8d5724b 100644
--- a/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java
@@ -34,6 +34,9 @@
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
+import com.android.settings.R;
+import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,8 +47,6 @@
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
-import java.util.Arrays;
-
/** Tests for {@link LaunchAccessibilityActivityPreferenceFragment} */
@RunWith(RobolectricTestRunner.class)
public class LaunchAccessibilityActivityPreferenceFragmentTest {
@@ -83,53 +84,91 @@
}
@Test
- public void getTileName_noTileServiceAssigned_returnNull() {
- assertThat(mFragment.getTileName()).isNull();
+ public void getTileTooltipContent_noTileServiceAssigned_returnNull() {
+ final CharSequence tileTooltipContent =
+ mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT);
+
+ assertThat(tileTooltipContent).isNull();
}
@Test
- public void getTileName_hasOneTileService_haveMatchString() {
- final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE);
- final ResolveInfo info = new ResolveInfo();
- info.serviceInfo = new FakeServiceInfo();
- info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME;
- info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME;
- final ShadowPackageManager shadowPackageManager =
- Shadows.shadowOf(mContext.getPackageManager());
- shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info));
+ public void getTileTooltipContent_hasOneTileService_guideToEdit_haveMatchString() {
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME,
+ PLACEHOLDER_TILE_NAME);
- final CharSequence tileName = mFragment.getTileName();
- assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME);
+ final CharSequence tileTooltipContent =
+ mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT);
+ final CharSequence tileName =
+ mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
+ assertThat(tileTooltipContent.toString()).isEqualTo(
+ mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName));
}
@Test
- public void getTileName_hasTwoTileServices_haveMatchString() {
+ public void getTileTooltipContent_hasOneTileService_guideToDirectUse_haveMatchString() {
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME,
+ PLACEHOLDER_TILE_NAME);
+
+ final CharSequence tileTooltipContent =
+ mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE);
+ final CharSequence tileName =
+ mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
+ assertThat(tileTooltipContent.toString()).isEqualTo(
+ mContext.getString(
+ R.string.accessibility_service_auto_added_qs_tooltip_content, tileName));
+ }
+
+ @Test
+ public void getTileTooltipContent_hasTwoTileServices_guideToEdit_haveMatchString() {
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME,
+ PLACEHOLDER_TILE_NAME);
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME2,
+ PLACEHOLDER_TILE_NAME2);
+
+ final CharSequence tileTooltipContent =
+ mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT);
+ final CharSequence tileName =
+ mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
+ assertThat(tileTooltipContent.toString()).isEqualTo(
+ mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName));
+ }
+
+ @Test
+ public void getTileTooltipContent_hasTwoTileServices_guideToDirectUse_haveMatchString() {
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME,
+ PLACEHOLDER_TILE_NAME);
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME2,
+ PLACEHOLDER_TILE_NAME2);
+
+ final CharSequence tileTooltipContent =
+ mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE);
+ final CharSequence tileName =
+ mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
+ assertThat(tileTooltipContent.toString()).isEqualTo(
+ mContext.getString(
+ R.string.accessibility_service_auto_added_qs_tooltip_content, tileName));
+ }
+
+ private void setupTileService(String packageName, String name, String tileName) {
final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE);
final ResolveInfo info = new ResolveInfo();
- info.serviceInfo = new FakeServiceInfo();
- info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME;
- info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME;
- final ResolveInfo info2 = new ResolveInfo();
- info2.serviceInfo = new FakeServiceInfo2();
- info2.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME;
- info2.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME2;
+ info.serviceInfo = new FakeServiceInfo(packageName, name, tileName);
final ShadowPackageManager shadowPackageManager =
Shadows.shadowOf(mContext.getPackageManager());
- shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info, info2));
-
- final CharSequence tileName = mFragment.getTileName();
- assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME);
+ shadowPackageManager.addResolveInfoForIntent(tileProbe, info);
}
private static class FakeServiceInfo extends ServiceInfo {
- public String loadLabel(PackageManager mgr) {
- return PLACEHOLDER_TILE_NAME;
- }
- }
+ private String mTileName;
- private static class FakeServiceInfo2 extends ServiceInfo {
+ FakeServiceInfo(String packageName, String name, String tileName) {
+ this.packageName = packageName;
+ this.name = name;
+ mTileName = tileName;
+ }
+
public String loadLabel(PackageManager mgr) {
- return PLACEHOLDER_TILE_NAME2;
+ return mTileName;
}
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java
index 236f9f2..2269529 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java
@@ -34,6 +34,9 @@
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
+import com.android.settings.R;
+import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,8 +47,6 @@
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
-import java.util.Arrays;
-
/** Tests for {@link ToggleAccessibilityServicePreferenceFragment} */
@RunWith(RobolectricTestRunner.class)
public class ToggleAccessibilityServicePreferenceFragmentTest {
@@ -83,53 +84,91 @@
}
@Test
- public void getTileName_noTileServiceAssigned_returnNull() {
- assertThat(mFragment.getTileName()).isNull();
+ public void getTileTooltipContent_noTileServiceAssigned_returnNull() {
+ final CharSequence tileTooltipContent =
+ mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT);
+
+ assertThat(tileTooltipContent).isNull();
}
@Test
- public void getTileName_hasOneTileService_haveMatchString() {
- final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE);
- final ResolveInfo info = new ResolveInfo();
- info.serviceInfo = new FakeServiceInfo();
- info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME;
- info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME;
- final ShadowPackageManager shadowPackageManager =
- Shadows.shadowOf(mContext.getPackageManager());
- shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info));
+ public void getTileTooltipContent_hasOneTileService_guideToEdit_haveMatchString() {
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME,
+ PLACEHOLDER_TILE_NAME);
- final CharSequence tileName = mFragment.getTileName();
- assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME);
+ final CharSequence tileTooltipContent =
+ mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT);
+ final CharSequence tileName =
+ mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
+ assertThat(tileTooltipContent.toString()).isEqualTo(
+ mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName));
}
@Test
- public void getTileName_hasTwoTileServices_haveMatchString() {
+ public void getTileTooltipContent_hasOneTileService_guideToDirectUse_haveMatchString() {
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME,
+ PLACEHOLDER_TILE_NAME);
+
+ final CharSequence tileTooltipContent =
+ mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE);
+ final CharSequence tileName =
+ mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
+ assertThat(tileTooltipContent.toString()).isEqualTo(
+ mContext.getString(
+ R.string.accessibility_service_auto_added_qs_tooltip_content, tileName));
+ }
+
+ @Test
+ public void getTileTooltipContent_hasTwoTileServices_guideToEdit_haveMatchString() {
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME,
+ PLACEHOLDER_TILE_NAME);
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME2,
+ PLACEHOLDER_TILE_NAME2);
+
+ final CharSequence tileTooltipContent =
+ mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT);
+ final CharSequence tileName =
+ mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
+ assertThat(tileTooltipContent.toString()).isEqualTo(
+ mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName));
+ }
+
+ @Test
+ public void getTileTooltipContent_hasTwoTileServices_guideToDirectUse_haveMatchString() {
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME,
+ PLACEHOLDER_TILE_NAME);
+ setupTileService(PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME2,
+ PLACEHOLDER_TILE_NAME2);
+
+ final CharSequence tileTooltipContent =
+ mFragment.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE);
+ final CharSequence tileName =
+ mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
+ assertThat(tileTooltipContent.toString()).isEqualTo(
+ mContext.getString(
+ R.string.accessibility_service_auto_added_qs_tooltip_content, tileName));
+ }
+
+ private void setupTileService(String packageName, String name, String tileName) {
final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE);
final ResolveInfo info = new ResolveInfo();
- info.serviceInfo = new FakeServiceInfo();
- info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME;
- info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME;
- final ResolveInfo info2 = new ResolveInfo();
- info2.serviceInfo = new FakeServiceInfo2();
- info2.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME;
- info2.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME2;
+ info.serviceInfo = new FakeServiceInfo(packageName, name, tileName);
final ShadowPackageManager shadowPackageManager =
Shadows.shadowOf(mContext.getPackageManager());
- shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info, info2));
-
- final CharSequence tileName = mFragment.getTileName();
- assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME);
+ shadowPackageManager.addResolveInfoForIntent(tileProbe, info);
}
private static class FakeServiceInfo extends ServiceInfo {
- public String loadLabel(PackageManager mgr) {
- return PLACEHOLDER_TILE_NAME;
- }
- }
+ private String mTileName;
- private static class FakeServiceInfo2 extends ServiceInfo {
+ FakeServiceInfo(String packageName, String name, String tileName) {
+ this.packageName = packageName;
+ this.name = name;
+ mTileName = tileName;
+ }
+
public String loadLabel(PackageManager mgr) {
- return PLACEHOLDER_TILE_NAME2;
+ return mTileName;
}
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
index 34a2f5b..04018a6 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
@@ -49,6 +49,7 @@
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType;
+import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settingslib.widget.TopIntroPreference;
@@ -77,8 +78,8 @@
PLACEHOLDER_PACKAGE_NAME + "tile.placeholder";
private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName(
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME);
- private static final String PLACEHOLDER_TILE_NAME =
- PLACEHOLDER_PACKAGE_NAME + "tile.placeholder";
+ private static final String PLACEHOLDER_TILE_TOOLTIP_CONTENT =
+ PLACEHOLDER_PACKAGE_NAME + "tooltip_content";
private static final String PLACEHOLDER_DIALOG_TITLE = "title";
private static final String DEFAULT_SUMMARY = "default summary";
private static final String DEFAULT_DESCRIPTION = "default description";
@@ -361,8 +362,8 @@
}
@Override
- CharSequence getTileName() {
- return PLACEHOLDER_TILE_NAME;
+ protected CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
+ return PLACEHOLDER_TILE_TOOLTIP_CONTENT;
}
@Override
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
new file mode 100644
index 0000000..ef81247
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.media.AudioDeviceAttributes;
+import android.media.AudioManager;
+import android.media.Spatializer;
+
+import androidx.preference.PreferenceCategory;
+import androidx.preference.SwitchPreference;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetailsControllerTestBase {
+
+ private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
+ private static final String KEY_SPATIAL_AUDIO = "spatial_audio";
+ private static final String KEY_HEAD_TRACKING = "head_tracking";
+
+ @Mock
+ private AudioManager mAudioManager;
+ @Mock
+ private Spatializer mSpatializer;
+ @Mock
+ private Lifecycle mSpatialAudioLifecycle;
+ @Mock
+ private PreferenceCategory mProfilesContainer;
+
+ private BluetoothDetailsSpatialAudioController mController;
+ private SwitchPreference mSpatialAudioPref;
+ private SwitchPreference mHeadTrackingPref;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
+ when(mAudioManager.getSpatializer()).thenReturn(mSpatializer);
+ when(mCachedDevice.getAddress()).thenReturn(MAC_ADDRESS);
+
+ mController = new BluetoothDetailsSpatialAudioController(mContext, mFragment,
+ mCachedDevice, mSpatialAudioLifecycle);
+ mController.mProfilesContainer = mProfilesContainer;
+
+ mSpatialAudioPref = mController.createSpatialAudioPreference(mContext);
+ mHeadTrackingPref = mController.createHeadTrackingPreference(mContext);
+
+ when(mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO)).thenReturn(mSpatialAudioPref);
+ when(mProfilesContainer.findPreference(KEY_HEAD_TRACKING)).thenReturn(mHeadTrackingPref);
+ }
+
+ @Test
+ public void isAvailable_spatialAudioIsAvailable_returnsTrue() {
+ when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(true);
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_spatialAudioIsNotAvailable_returnsFalse() {
+ when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(false);
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void refresh_spatialAudioIsTurnedOn_checksSpatialAudioPreference() {
+ List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
+ compatibleAudioDevices.add(mController.mAudioDevice);
+ when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
+
+ mController.refresh();
+
+ assertThat(mSpatialAudioPref.isChecked()).isTrue();
+ }
+
+ @Test
+ public void refresh_spatialAudioIsTurnedOff_unchecksSpatialAudioPreference() {
+ List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
+ when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
+
+ mController.refresh();
+
+ assertThat(mSpatialAudioPref.isChecked()).isFalse();
+ }
+
+ @Test
+ public void refresh_spatialAudioOnAndHeadTrackingIsAvailable_showsHeadTrackingPreference() {
+ List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
+ compatibleAudioDevices.add(mController.mAudioDevice);
+ when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
+ when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
+
+ mController.refresh();
+
+ assertThat(mHeadTrackingPref.isVisible()).isTrue();
+ }
+
+ @Test
+ public void
+ refresh_spatialAudioOnAndHeadTrackingIsNotAvailable_hidesHeadTrackingPreference() {
+ List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
+ compatibleAudioDevices.add(mController.mAudioDevice);
+ when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
+ when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(false);
+
+ mController.refresh();
+
+ assertThat(mHeadTrackingPref.isVisible()).isFalse();
+ }
+
+ @Test
+ public void refresh_spatialAudioOff_hidesHeadTrackingPreference() {
+ List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
+ when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
+
+ mController.refresh();
+
+ assertThat(mHeadTrackingPref.isVisible()).isFalse();
+ }
+
+ @Test
+ public void refresh_headTrackingIsTurnedOn_checksHeadTrackingPreference() {
+ List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
+ compatibleAudioDevices.add(mController.mAudioDevice);
+ when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
+ when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
+ when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(true);
+
+ mController.refresh();
+
+ assertThat(mHeadTrackingPref.isChecked()).isTrue();
+ }
+
+ @Test
+ public void refresh_headTrackingIsTurnedOff_unchecksHeadTrackingPreference() {
+ List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
+ compatibleAudioDevices.add(mController.mAudioDevice);
+ when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
+ when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
+ when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(false);
+
+ mController.refresh();
+
+ assertThat(mHeadTrackingPref.isChecked()).isFalse();
+ }
+
+ @Test
+ public void turnedOnSpatialAudio_invokesAddCompatibleAudioDevice() {
+ mSpatialAudioPref.setChecked(true);
+ mController.onPreferenceClick(mSpatialAudioPref);
+ verify(mSpatializer).addCompatibleAudioDevice(mController.mAudioDevice);
+ }
+
+ @Test
+ public void turnedOffSpatialAudio_invokesRemoveCompatibleAudioDevice() {
+ mSpatialAudioPref.setChecked(false);
+ mController.onPreferenceClick(mSpatialAudioPref);
+ verify(mSpatializer).removeCompatibleAudioDevice(mController.mAudioDevice);
+ }
+
+ @Test
+ public void turnedOnHeadTracking_invokesSetHeadTrackerEnabled_setsTrue() {
+ mHeadTrackingPref.setChecked(true);
+ mController.onPreferenceClick(mHeadTrackingPref);
+ verify(mSpatializer).setHeadTrackerEnabled(true, mController.mAudioDevice);
+ }
+
+ @Test
+ public void turnedOffHeadTracking_invokesSetHeadTrackerEnabled_setsFalse() {
+ mHeadTrackingPref.setChecked(false);
+ mController.onPreferenceClick(mHeadTrackingPref);
+ verify(mSpatializer).setHeadTrackerEnabled(false, mController.mAudioDevice);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java
index c9b13e27..a386473 100644
--- a/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java
@@ -32,7 +32,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.RestrictedPreference;
import org.junit.Before;
import org.junit.Test;
@@ -48,7 +48,7 @@
private static final ComponentName TEST_COMPONENT_NAME = new ComponentName("test", "test");
@Mock
- private RestrictedSwitchPreference mPreference;
+ private RestrictedPreference mPreference;
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java
index d16a507..42b889c 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/AbstractBluetoothDialogPreferenceControllerTest.java
@@ -121,7 +121,7 @@
@Test
public void onIndexUpdated_checkFlow() {
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, null);
+ mCodecStatus = new BluetoothCodecStatus.Builder().setCodecConfig(mCodecConfigAAC).build();
when(mBluetoothA2dp.getCodecStatus(
mActiveDevice)).thenReturn(mCodecStatus);
when(mBluetoothA2dpConfigStore.createCodecConfig()).thenReturn(mCodecConfigAAC);
@@ -161,7 +161,7 @@
@Test
public void getCurrentCodecConfig_verifyConfig() {
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, null);
+ mCodecStatus = new BluetoothCodecStatus.Builder().setCodecConfig(mCodecConfigAAC).build();
when(mBluetoothA2dp.getCodecStatus(
mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
@@ -171,8 +171,10 @@
@Test
public void getSelectableConfigs_verifyConfig() {
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(
mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
@@ -182,8 +184,10 @@
@Test
public void getSelectableByCodecType_verifyConfig() {
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(
mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
@@ -194,8 +198,10 @@
@Test
public void getSelectableByCodecType_unavailable() {
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(
mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
@@ -206,8 +212,10 @@
@Test
public void onBluetoothServiceConnected_verifyBluetoothA2dpConfigStore() {
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(
mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java
index 5a24c8e..dba1fbf 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothBitPerSampleDialogPreferenceControllerTest.java
@@ -102,8 +102,10 @@
@Test
public void writeConfigurationValues_selectDefault_setHighest() {
BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
@@ -132,8 +134,10 @@
@Test
public void getSelectableIndex_verifyList() {
BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
List<Integer> indexList = new ArrayList<>();
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java
index 3d94e2a..570257a 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothChannelModeDialogPreferenceControllerTest.java
@@ -102,8 +102,10 @@
@Test
public void writeConfigurationValues_selectDefault_setHighest() {
BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigSBC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigSBC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
@@ -129,8 +131,10 @@
@Test
public void getSelectableIndex_verifyList() {
BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigSBC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigSBC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
List<Integer> indexList = new ArrayList<>();
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java
index 21111cd..f04a80d 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothCodecDialogPreferenceControllerTest.java
@@ -126,8 +126,10 @@
@Test
public void writeConfigurationValues_selectDefault_setHighest() {
BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigSBC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigSBC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
when(mBluetoothA2dp.isOptionalCodecsEnabled(mActiveDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED);
@@ -141,8 +143,10 @@
public void writeConfigurationValues_checkCodec() {
BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC, mCodecConfigAPTX,
mCodecConfigAPTXHD, mCodecConfigLDAC, mCodecConfigAAC, mCodecConfigSBC};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigSBC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigSBC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
@@ -169,8 +173,10 @@
public void writeConfigurationValues_resetHighestConfig() {
BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC, mCodecConfigAPTX,
mCodecConfigAPTXHD, mCodecConfigLDAC, mCodecConfigAAC, mCodecConfigSBC};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
mController.writeConfigurationValues(2);
@@ -201,9 +207,10 @@
@Test
public void onHDAudioEnabled_optionalCodecEnabled_setsCodecTypeAsAAC() {
List<BluetoothCodecConfig> mCodecConfigs = Arrays.asList(mCodecConfigAAC, mCodecConfigSBC);
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC,
- /* codecsLocalCapabilities= */ null,
- mCodecConfigs);
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(mCodecConfigs)
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
when(mBluetoothA2dp.isOptionalCodecsEnabled(mActiveDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED);
@@ -217,9 +224,10 @@
@Test
public void onHDAudioEnabled_optionalCodecDisabled_setsCodecTypeAsSBC() {
List<BluetoothCodecConfig> mCodecConfigs = Arrays.asList(mCodecConfigAAC, mCodecConfigSBC);
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC,
- /* codecsLocalCapabilities= */ null,
- mCodecConfigs);
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(mCodecConfigs)
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
when(mBluetoothA2dp.isOptionalCodecsEnabled(mActiveDevice)).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED);
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java
index 1bd83f7..359d24e 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothQualityDialogPreferenceControllerTest.java
@@ -122,8 +122,10 @@
@Test
public void updateState_codeTypeIsLDAC_enablePreference() {
BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigLDAC};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigLDAC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigLDAC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
mController.updateState(mPreference);
@@ -134,8 +136,10 @@
@Test
public void updateState_codeTypeAAC_disablePreference() {
BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigLDAC};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
mController.updateState(mPreference);
diff --git a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java
index f7d010c..fa4a79c 100644
--- a/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/bluetooth/BluetoothSampleRateDialogPreferenceControllerTest.java
@@ -106,8 +106,10 @@
.setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC)
.build();
BluetoothCodecConfig[] mCodecConfigs = {mCodecConfigAAC, mCodecConfigSBC};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null,
- Arrays.asList(mCodecConfigs));
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(Arrays.asList(mCodecConfigs))
+ .build();
when(mBluetoothA2dp.getCodecStatus(
mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
@@ -143,7 +145,10 @@
add(mCodecConfigAAC);
add(mCodecConfigSBC);
}};
- mCodecStatus = new BluetoothCodecStatus(mCodecConfigAAC, null, mCodecConfigs);
+ mCodecStatus = new BluetoothCodecStatus.Builder()
+ .setCodecConfig(mCodecConfigAAC)
+ .setCodecsSelectableCapabilities(mCodecConfigs)
+ .build();
when(mBluetoothA2dp.getCodecStatus(
mActiveDevice)).thenReturn(mCodecStatus);
mController.onBluetoothServiceConnected(mBluetoothA2dp);
diff --git a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java
index 28a071a..d364a3b 100644
--- a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java
@@ -21,6 +21,9 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+
+import android.app.settings.SettingsEnums;
import android.content.Context;
import androidx.preference.Preference;
@@ -30,11 +33,15 @@
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager;
import com.android.settings.testutils.shadow.ShadowRotationPolicy;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
import com.android.settingslib.search.SearchIndexableRaw;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@@ -54,12 +61,26 @@
private static final int DEFAULT_ORDER = -10;
private final Context mContext = RuntimeEnvironment.application;
- private final DeviceStateAutoRotateSettingController mController =
- new DeviceStateAutoRotateSettingController(mContext, DEFAULT_DEVICE_STATE,
- DEFAULT_DEVICE_STATE_DESCRIPTION, DEFAULT_ORDER);
private final DeviceStateRotationLockSettingsManager mAutoRotateSettingsManager =
DeviceStateRotationLockSettingsManager.getInstance(mContext);
+ @Mock private MetricsFeatureProvider mMetricsFeatureProvider;
+
+ private DeviceStateAutoRotateSettingController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mController = new DeviceStateAutoRotateSettingController(
+ mContext,
+ DEFAULT_DEVICE_STATE,
+ DEFAULT_DEVICE_STATE_DESCRIPTION,
+ DEFAULT_ORDER,
+ mMetricsFeatureProvider
+ );
+ }
+
@Test
public void displayPreference_addsPreferenceToPreferenceScreen() {
PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
@@ -144,6 +165,22 @@
}
@Test
+ public void setChecked_true_logsDeviceStateBasedSettingOn() {
+ mController.setChecked(true);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ SettingsEnums.ACTION_ENABLE_AUTO_ROTATION_DEVICE_STATE, DEFAULT_DEVICE_STATE);
+ }
+
+ @Test
+ public void setChecked_false_logsDeviceStateBasedSettingOff() {
+ mController.setChecked(false);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ SettingsEnums.ACTION_DISABLE_AUTO_ROTATION_DEVICE_STATE, DEFAULT_DEVICE_STATE);
+ }
+
+ @Test
public void updateRawDataToIndex_addsItemToList() {
List<SearchIndexableRaw> rawData = new ArrayList<>();
diff --git a/tests/robotests/src/com/android/settings/dream/DreamMainSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/dream/DreamMainSwitchPreferenceControllerTest.java
new file mode 100644
index 0000000..fb55164
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/dream/DreamMainSwitchPreferenceControllerTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2020 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.dream;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settingslib.dream.DreamBackend;
+import com.android.settingslib.widget.MainSwitchPreference;
+import com.android.settingslib.widget.OnMainSwitchChangeListener;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowContentResolver;
+import org.robolectric.shadows.ShadowSettings;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowSettings.ShadowSecure.class})
+public class DreamMainSwitchPreferenceControllerTest {
+
+ private Context mContext;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private PreferenceScreen mScreen;
+ private DreamMainSwitchPreferenceController mController;
+ private MainSwitchPreference mPreference;
+ private DreamBackend mBackend;
+ @Mock
+ private OnMainSwitchChangeListener mChangeListener;
+ private ShadowContentResolver mShadowContentResolver;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = ApplicationProvider.getApplicationContext();
+ mShadowContentResolver = Shadow.extract(mContext.getContentResolver());
+ mBackend = DreamBackend.getInstance(mContext);
+ mController = new DreamMainSwitchPreferenceController(mContext, "key");
+ mPreference = new MainSwitchPreference(mContext);
+ mPreference.setKey(mController.getPreferenceKey());
+ when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference);
+ mController.displayPreference(mScreen);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowSettings.ShadowSecure.reset();
+ mController.onStop();
+ }
+
+ @Test
+ public void testIsChecked_returnsFalse() {
+ mBackend.setEnabled(false);
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void testIsChecked_returnsTrue() {
+ mBackend.setEnabled(true);
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testSetChecked_setFalse_disablesSetting() {
+ mBackend.setEnabled(true);
+ mController.setChecked(false);
+ assertThat(mBackend.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void testSetChecked_setTrue_enablesSetting() {
+ mBackend.setEnabled(false);
+ mController.setChecked(true);
+ assertThat(mBackend.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void testIsSliceable_returnsFalse() {
+ assertThat(mController.isSliceable()).isFalse();
+ }
+
+ @Test
+ public void testRegisterAndUnregister() {
+ mController.onStart();
+ assertThat(mShadowContentResolver.getContentObservers(
+ Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED))).hasSize(1);
+
+ mController.onStop();
+ assertThat(mShadowContentResolver.getContentObservers(
+ Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED))).isEmpty();
+ }
+
+ @Test
+ public void testUpdateState() {
+ mController.onStart();
+
+ mBackend.setEnabled(true);
+ triggerOnChangeListener();
+ assertThat(mPreference.isChecked()).isTrue();
+
+ mBackend.setEnabled(false);
+ triggerOnChangeListener();
+ assertThat(mPreference.isChecked()).isFalse();
+
+ mBackend.setEnabled(true);
+ triggerOnChangeListener();
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ private void triggerOnChangeListener() {
+ mShadowContentResolver.getContentObservers(
+ Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED))
+ .forEach(contentObserver -> contentObserver.onChange(false));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/dream/DreamPickerControllerTest.java b/tests/robotests/src/com/android/settings/dream/DreamPickerControllerTest.java
index 401ffe0..7a5299f 100644
--- a/tests/robotests/src/com/android/settings/dream/DreamPickerControllerTest.java
+++ b/tests/robotests/src/com/android/settings/dream/DreamPickerControllerTest.java
@@ -62,7 +62,8 @@
}
private DreamPickerController buildController() {
- final DreamPickerController controller = new DreamPickerController(mContext, mBackend);
+ final DreamPickerController controller = new DreamPickerController(mContext, "key",
+ mBackend);
controller.displayPreference(mScreen);
return controller;
}
diff --git a/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java b/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java
index fd0cf5f..16f8599 100644
--- a/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java
+++ b/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java
@@ -18,18 +18,19 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.Activity;
import android.content.Context;
import android.os.UserManager;
+import androidx.test.core.app.ApplicationProvider;
+
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.dream.DreamBackend;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -39,25 +40,24 @@
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
-@Ignore
public class WhenToDreamPickerTest {
private WhenToDreamPicker mPicker;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private DreamBackend mBackend;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Activity mActivity;
@Mock
private UserManager mUserManager;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ final Context context = spy(ApplicationProvider.getApplicationContext());
+
+ when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
FakeFeatureFactory.setupForTest();
mPicker = new WhenToDreamPicker();
- mPicker.onAttach((Context) mActivity);
+ mPicker.onAttach(context);
ReflectionHelpers.setField(mPicker, "mBackend", mBackend);
}
diff --git a/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java
index a0188f8..3305cde 100644
--- a/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java
@@ -23,26 +23,23 @@
import android.content.Context;
import androidx.preference.Preference;
+import androidx.test.core.app.ApplicationProvider;
import com.android.settingslib.dream.DreamBackend;
import com.android.settingslib.dream.DreamBackend.WhenToDream;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
-@Ignore
public class WhenToDreamPreferenceControllerTest {
private WhenToDreamPreferenceController mController;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock
private DreamBackend mBackend;
@@ -50,6 +47,7 @@
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ mContext = ApplicationProvider.getApplicationContext();
mController = new WhenToDreamPreferenceController(mContext);
ReflectionHelpers.setField(mController, "mBackend", mBackend);
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
index f9ccff9..7398e5c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
@@ -75,7 +75,7 @@
public void updateState_lowPowerOn_preferenceIsChecked() {
when(mPowerManager.isPowerSaveMode()).thenReturn(true);
- mController.onSwitchChanged(null, mPowerManager.isPowerSaveMode());
+ mPreference.updateStatus(mPowerManager.isPowerSaveMode());
assertThat(mPreference.isChecked()).isTrue();
}
@@ -84,7 +84,7 @@
public void testUpdateState_lowPowerOff_preferenceIsUnchecked() {
when(mPowerManager.isPowerSaveMode()).thenReturn(false);
- mController.onSwitchChanged(null, mPowerManager.isPowerSaveMode());
+ mPreference.updateStatus(mPowerManager.isPowerSaveMode());
assertThat(mPreference.isChecked()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java
index b014076..e85f713 100644
--- a/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java
@@ -43,19 +43,21 @@
}
@Test
- public void getNonIndexableKeys_twoButtonNavigationAvailable_allKeysIndexable() {
+ public void getNonIndexableKeys_twoButtonNavigationAvailable_allKeysExceptAnimIndexable() {
addPackageToPackageManager(ApplicationProvider.getApplicationContext(),
NAV_BAR_MODE_2BUTTON_OVERLAY);
assertThat(ButtonNavigationSettingsFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
- ApplicationProvider.getApplicationContext())).isEmpty();
+ ApplicationProvider.getApplicationContext())).containsExactly(
+ "gesture_power_menu_video");
}
@Test
- public void getNonIndexableKeys_threeButtonNavigationAvailable_allKeysIndexable() {
+ public void getNonIndexableKeys_threeButtonNavigationAvailable_allKeysExceptAnimIndexable() {
addPackageToPackageManager(ApplicationProvider.getApplicationContext(),
NAV_BAR_MODE_3BUTTON_OVERLAY);
assertThat(ButtonNavigationSettingsFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
- ApplicationProvider.getApplicationContext())).isEmpty();
+ ApplicationProvider.getApplicationContext())).containsExactly(
+ "gesture_power_menu_video");
}
private static void addPackageToPackageManager(Context context, String pkg) {
diff --git a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
index 9994876..3182cd0 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
@@ -108,6 +108,8 @@
@Mock
private WifiPickerTracker mMockWifiPickerTracker;
@Mock
+ private WifiEntry mWifiEntry;
+ @Mock
private PreferenceManager mPreferenceManager;
@Mock
private InternetResetHelper mInternetResetHelper;
@@ -309,14 +311,13 @@
when(activity.getApplicationContext()).thenReturn(mContext);
when(mNetworkProviderSettings.getActivity()).thenReturn(activity);
- final WifiEntry wifiEntry = mock(WifiEntry.class);
- when(wifiEntry.canDisconnect()).thenReturn(true);
- when(wifiEntry.canForget()).thenReturn(true);
- when(wifiEntry.isSaved()).thenReturn(true);
- when(wifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
+ when(mWifiEntry.canDisconnect()).thenReturn(true);
+ when(mWifiEntry.canForget()).thenReturn(true);
+ when(mWifiEntry.isSaved()).thenReturn(true);
+ when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
final LongPressWifiEntryPreference connectedWifiEntryPreference =
- mNetworkProviderSettings.createLongPressWifiEntryPreference(wifiEntry);
+ mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry);
final View view = mock(View.class);
when(view.getTag()).thenReturn(connectedWifiEntryPreference);
@@ -334,15 +335,14 @@
when(activity.getApplicationContext()).thenReturn(mContext);
when(mNetworkProviderSettings.getActivity()).thenReturn(activity);
- final WifiEntry wifiEntry = mock(WifiEntry.class);
- when(wifiEntry.canDisconnect()).thenReturn(true);
- when(wifiEntry.canShare()).thenReturn(true);
- when(wifiEntry.canForget()).thenReturn(true);
- when(wifiEntry.isSaved()).thenReturn(true);
- when(wifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
+ when(mWifiEntry.canDisconnect()).thenReturn(true);
+ when(mWifiEntry.canShare()).thenReturn(true);
+ when(mWifiEntry.canForget()).thenReturn(true);
+ when(mWifiEntry.isSaved()).thenReturn(true);
+ when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
final LongPressWifiEntryPreference connectedWifiEntryPreference =
- mNetworkProviderSettings.createLongPressWifiEntryPreference(wifiEntry);
+ mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry);
final View view = mock(View.class);
when(view.getTag()).thenReturn(connectedWifiEntryPreference);
@@ -358,15 +358,14 @@
when(activity.getApplicationContext()).thenReturn(mContext);
when(mNetworkProviderSettings.getActivity()).thenReturn(activity);
- final WifiEntry wifiEntry = mock(WifiEntry.class);
- when(wifiEntry.canDisconnect()).thenReturn(true);
- when(wifiEntry.canShare()).thenReturn(false);
- when(wifiEntry.canForget()).thenReturn(true);
- when(wifiEntry.isSaved()).thenReturn(true);
- when(wifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
+ when(mWifiEntry.canDisconnect()).thenReturn(true);
+ when(mWifiEntry.canShare()).thenReturn(false);
+ when(mWifiEntry.canForget()).thenReturn(true);
+ when(mWifiEntry.isSaved()).thenReturn(true);
+ when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
final LongPressWifiEntryPreference connectedWifiEntryPreference =
- mNetworkProviderSettings.createLongPressWifiEntryPreference(wifiEntry);
+ mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry);
final View view = mock(View.class);
when(view.getTag()).thenReturn(connectedWifiEntryPreference);
@@ -390,10 +389,9 @@
FAKE_URI_STRING);
doNothing().when(mNetworkProviderSettings).startActivityForResult(any(Intent.class),
anyInt());
- final WifiEntry mockWifiEntry = mock(WifiEntry.class);
- when(mockWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING);
+ when(mWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING);
- mNetworkProviderSettings.openSubscriptionHelpPage(mockWifiEntry);
+ mNetworkProviderSettings.openSubscriptionHelpPage(mWifiEntry);
verify(mNetworkProviderSettings, times(1)).startActivityForResult(any(), anyInt());
}
@@ -461,12 +459,11 @@
}
private WifiDialog2 createWifiDialog2(int mode, WifiConfiguration config) {
- final WifiEntry wifiEntry = mock(WifiEntry.class);
- when(wifiEntry.canConnect()).thenReturn(true);
+ when(mWifiEntry.canConnect()).thenReturn(true);
final WifiConfigController2 controller = mock(WifiConfigController2.class);
when(controller.getConfig()).thenReturn(config);
- final WifiDialog2 wifiDialog2 = spy(WifiDialog2.createModal(mContext, null /* listener */,
- wifiEntry, mode));
+ final WifiDialog2 wifiDialog2 = spy(WifiDialog2.createModal(mContext, null /* listener */,
+ mWifiEntry, mode));
when(wifiDialog2.getController()).thenReturn(controller);
return wifiDialog2;
}
@@ -537,20 +534,18 @@
@Test
public void createConnectedWifiEntryPreference_internetWiFi_createConnectedPreference() {
- final WifiEntry wifiEntry = mock(WifiEntry.class);
doReturn(InternetUpdater.INTERNET_WIFI).when(mInternetUpdater).getInternetType();
- final Preference p = mNetworkProviderSettings.createConnectedWifiEntryPreference(wifiEntry);
+ Preference p = mNetworkProviderSettings.createConnectedWifiEntryPreference(mWifiEntry);
assertThat(p instanceof ConnectedWifiEntryPreference).isTrue();
}
@Test
public void createConnectedWifiEntryPreference_internetCellular_createFirstWifiPreference() {
- final WifiEntry wifiEntry = mock(WifiEntry.class);
doReturn(InternetUpdater.INTERNET_CELLULAR).when(mInternetUpdater).getInternetType();
- final Preference p = mNetworkProviderSettings.createConnectedWifiEntryPreference(wifiEntry);
+ Preference p = mNetworkProviderSettings.createConnectedWifiEntryPreference(mWifiEntry);
assertThat(p instanceof NetworkProviderSettings.FirstWifiEntryPreference).isTrue();
}
@@ -635,6 +630,42 @@
}
@Test
+ public void onSelectedWifiPreferenceClick_shouldEditBeforeConnect_launchNewNetworkFragment() {
+ when(mWifiEntry.shouldEditBeforeConnect()).thenReturn(true);
+ final LongPressWifiEntryPreference preference =
+ mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry);
+ doNothing().when(mNetworkProviderSettings).launchConfigNewNetworkFragment(mWifiEntry);
+
+ mNetworkProviderSettings.onSelectedWifiPreferenceClick(preference);
+
+ verify(mNetworkProviderSettings).launchConfigNewNetworkFragment(mWifiEntry);
+ }
+
+ @Test
+ public void onSelectedWifiPreferenceClick_canConnect_connectWifi() {
+ when(mWifiEntry.canConnect()).thenReturn(true);
+ final LongPressWifiEntryPreference preference =
+ mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry);
+ doNothing().when(mNetworkProviderSettings).connect(any(), anyBoolean(), anyBoolean());
+
+ mNetworkProviderSettings.onSelectedWifiPreferenceClick(preference);
+
+ verify(mNetworkProviderSettings).connect(any(), anyBoolean(), anyBoolean());
+ }
+
+ @Test
+ public void onSelectedWifiPreferenceClick_isSaved_launchNetworkDetailsFragment() {
+ when(mWifiEntry.isSaved()).thenReturn(true);
+ final LongPressWifiEntryPreference preference =
+ mNetworkProviderSettings.createLongPressWifiEntryPreference(mWifiEntry);
+ doNothing().when(mNetworkProviderSettings).launchNetworkDetailsFragment(preference);
+
+ mNetworkProviderSettings.onSelectedWifiPreferenceClick(preference);
+
+ verify(mNetworkProviderSettings).launchNetworkDetailsFragment(preference);
+ }
+
+ @Test
@Config(shadows = ShadowPreferenceFragmentCompat.class)
public void onStop_shouldRemoveCallbacks() {
View fragmentView = mock(View.class);
diff --git a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
index e31d959..057b6cb 100644
--- a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
@@ -26,6 +26,7 @@
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
@@ -35,6 +36,7 @@
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
@@ -109,6 +111,8 @@
private Network mNetwork;
@Mock
private Preference mPreference;
+ @Mock
+ private UserManager mUserManager;
@Captor
private ArgumentCaptor<NetworkCallback> mCallbackCaptor;
private PrivateDnsPreferenceController mController;
@@ -127,6 +131,7 @@
mShadowContentResolver = Shadow.extract(mContentResolver);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(mConnectivityManager);
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
doNothing().when(mConnectivityManager).registerDefaultNetworkCallback(
mCallbackCaptor.capture(), nullable(Handler.class));
@@ -174,6 +179,12 @@
}
@Test
+ public void getAvailabilityStatus_disabledForGuestUser() {
+ doReturn(true).when(mUserManager).isGuestUser();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER);
+ }
+
+ @Test
public void goThroughLifecycle_shouldRegisterUnregisterSettingsObserver() {
mLifecycle.handleLifecycleEvent(ON_START);
verify(mContext, atLeastOnce()).getContentResolver();
diff --git a/tests/robotests/src/com/android/settings/wifi/LongPressWifiEntryPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/LongPressWifiEntryPreferenceTest.java
new file mode 100644
index 0000000..fd7cc89
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/LongPressWifiEntryPreferenceTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+
+import androidx.fragment.app.Fragment;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.wifitrackerlib.WifiEntry;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class LongPressWifiEntryPreferenceTest {
+
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Spy
+ Context mContext = ApplicationProvider.getApplicationContext();
+ @Mock
+ Fragment mFragment;
+ @Mock
+ WifiEntry mWifiEntry;
+
+ LongPressWifiEntryPreference mPreference;
+
+ @Before
+ public void setUp() {
+ // Fake mWifiEntry as an available Wi-Fi network, and it's not connected.
+ when(mWifiEntry.canConnect()).thenReturn(true);
+ when(mWifiEntry.canDisconnect()).thenReturn(false);
+ when(mWifiEntry.isSaved()).thenReturn(false);
+
+ mPreference = new LongPressWifiEntryPreference(mContext, mWifiEntry, mFragment);
+ }
+
+ @Test
+ public void shouldEnabled_canConnect_returnTrue() {
+ // Fake mWifiEntry as an available Wi-Fi network, and it's not connected.
+ when(mWifiEntry.canConnect()).thenReturn(true);
+
+ assertThat(mPreference.shouldEnabled()).isTrue();
+ }
+
+ @Test
+ public void shouldEnabled_canNotConnect_returnFalse() {
+ // Fake mWifiEntry as a restricted Wi-Fi network, and cannot connect.
+ when(mWifiEntry.canConnect()).thenReturn(false);
+
+ assertThat(mPreference.shouldEnabled()).isFalse();
+ }
+
+ @Test
+ public void shouldEnabled_canNotConnectButCanDisconnect_returnTrue() {
+ // Fake mWifiEntry as a connected Wi-Fi network without saved configuration.
+ when(mWifiEntry.canConnect()).thenReturn(false);
+ when(mWifiEntry.canDisconnect()).thenReturn(true);
+
+ assertThat(mPreference.shouldEnabled()).isTrue();
+ }
+
+ @Test
+ public void shouldEnabled_canNotConnectButIsSaved_returnTrue() {
+ // Fake mWifiEntry as a saved Wi-Fi network
+ when(mWifiEntry.canConnect()).thenReturn(false);
+ when(mWifiEntry.isSaved()).thenReturn(true);
+
+ assertThat(mPreference.shouldEnabled()).isTrue();
+ }
+
+ @Test
+ public void shouldEnabled_canNotConnectButCanDisconnectAndIsSaved_returnTrue() {
+ // Fake mWifiEntry as a connected Wi-Fi network
+ when(mWifiEntry.canConnect()).thenReturn(false);
+ when(mWifiEntry.canDisconnect()).thenReturn(true);
+ when(mWifiEntry.isSaved()).thenReturn(true);
+
+ assertThat(mPreference.shouldEnabled()).isTrue();
+ }
+}
diff --git a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
index 064f813..249b713 100644
--- a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
@@ -18,12 +18,15 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
@@ -31,12 +34,12 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.RestrictedSwitchPreference;
import org.junit.Before;
import org.junit.Test;
@@ -55,6 +58,8 @@
@Mock
NotificationManager mNm;
@Mock
+ AppOpsManager mAppOpsManager;
+ @Mock
PackageManager mPm;
PackageInfo mPkgInfo;
ComponentName mCn = new ComponentName("a", "b");
@@ -75,15 +80,47 @@
mController.setNm(mNm);
mController.setParent(mFragment);
mController.setPkgInfo(mPkgInfo);
+
}
@Test
public void updateState_checked() {
+ when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
+ AppOpsManager.MODE_ALLOWED);
when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true);
- SwitchPreference pref = new SwitchPreference(mContext);
+ RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
+ mContext);
+ pref.setAppOps(mAppOpsManager);
mController.updateState(pref);
assertThat(pref.isChecked()).isTrue();
+ assertThat(pref.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void restrictedSettings_appOpsDisabled() {
+ when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
+ AppOpsManager.MODE_ERRORED);
+ when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(false);
+ RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
+ mContext);
+ pref.setAppOps(mAppOpsManager);
+
+ mController.updateState(pref);
+ assertThat(pref.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void restrictedSettings_serviceAlreadyEnabled() {
+ when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
+ AppOpsManager.MODE_ERRORED);
+ when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true);
+ RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
+ mContext);
+ pref.setAppOps(mAppOpsManager);
+
+ mController.updateState(pref);
+ assertThat(pref.isEnabled()).isTrue();
}
@Test
diff --git a/tests/unit/src/com/android/settings/biometrics/BiometricNavigationUtilsTest.java b/tests/unit/src/com/android/settings/biometrics/BiometricNavigationUtilsTest.java
index c767c32..395f88f 100644
--- a/tests/unit/src/com/android/settings/biometrics/BiometricNavigationUtilsTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/BiometricNavigationUtilsTest.java
@@ -64,7 +64,7 @@
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
doNothing().when(mContext).startActivity(any());
- mBiometricNavigationUtils = new BiometricNavigationUtils();
+ mBiometricNavigationUtils = new BiometricNavigationUtils(UserHandle.myUserId());
}
@Test
diff --git a/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java b/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java
index 55b3fae..10f1110 100644
--- a/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java
@@ -56,8 +56,8 @@
private static final ComponentName COMPONENT_NAME =
new ComponentName("package", "class");
- private static final UserHandle USER_HANDLE = new UserHandle(UserHandle.myUserId());
-
+ private static final int USER_ID = UserHandle.myUserId();
+ private static final UserHandle USER_HANDLE = new UserHandle(USER_ID);
@Mock
private PackageManager mPackageManager;
@@ -85,7 +85,8 @@
when(mApplicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
.thenReturn(mDevicePolicyManager);
when(mApplicationContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
- mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(mApplicationContext);
+ mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(
+ mApplicationContext, USER_ID);
}
@Test
@@ -121,6 +122,54 @@
}
@Test
+ public void hasEnrolled_withoutFingerprintHardware_withoutFaceHardware_returnsFalse() {
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
+ when(mFaceManager.isHardwareDetected()).thenReturn(false);
+
+ assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isFalse();
+ }
+
+ @Test
+ public void hasEnrolled_withoutFingerprintEnroll_withoutFaceEnroll_returnsFalse() {
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
+
+ assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isFalse();
+ }
+
+ @Test
+ public void hasEnrolled_withoutFingerprintEnroll_withFaceEnroll_returnsTrue() {
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
+
+ assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isTrue();
+ }
+
+ @Test
+ public void hasEnrolled_withFingerprintEnroll_withoutFaceEnroll_returnsTrue() {
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
+
+ assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isTrue();
+ }
+
+ @Test
+ public void hasEnrolled_withFingerprintEnroll_withFaceEnroll_returnsTrue() {
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
+
+ assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isTrue();
+ }
+
+ @Test
public void getDisabledAdmin_whenFingerprintDisabled_whenFaceDisabled_returnsEnforcedAdmin() {
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME))
.thenReturn(KEYGUARD_DISABLE_FACE | KEYGUARD_DISABLE_FINGERPRINT);
diff --git a/tests/unit/src/com/android/settings/biometrics/face/FaceStatusUtilsTest.java b/tests/unit/src/com/android/settings/biometrics/face/FaceStatusUtilsTest.java
index f670fad..9f9dd93 100644
--- a/tests/unit/src/com/android/settings/biometrics/face/FaceStatusUtilsTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/face/FaceStatusUtilsTest.java
@@ -49,7 +49,8 @@
private static final ComponentName COMPONENT_NAME =
new ComponentName("package", "class");
- private static final UserHandle USER_HANDLE = new UserHandle(UserHandle.myUserId());
+ private static final int USER_ID = UserHandle.myUserId();
+ private static final UserHandle USER_HANDLE = new UserHandle(USER_ID);
@Mock
@@ -78,7 +79,7 @@
when(mApplicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
.thenReturn(mDevicePolicyManager);
when(mApplicationContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
- mFaceStatusUtils = new FaceStatusUtils(mApplicationContext, mFaceManager);
+ mFaceStatusUtils = new FaceStatusUtils(mApplicationContext, mFaceManager, USER_ID);
}
@Test
@@ -114,6 +115,20 @@
}
@Test
+ public void hasEnrolled_withEnrolledTemplates_returnsTrue() {
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
+
+ assertThat(mFaceStatusUtils.hasEnrolled()).isTrue();
+ }
+
+ @Test
+ public void hasEnrolled_withoutEnrolledTemplates_returnsFalse() {
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
+
+ assertThat(mFaceStatusUtils.hasEnrolled()).isFalse();
+ }
+
+ @Test
public void getDisabledAdmin_whenFaceDisabled_returnsEnforcedAdmin() {
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME))
.thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FACE);
diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java
index b4abb5d..4ecf82e 100644
--- a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java
@@ -52,7 +52,8 @@
private static final ComponentName COMPONENT_NAME =
new ComponentName("package", "class");
- private static final UserHandle USER_HANDLE = new UserHandle(UserHandle.myUserId());
+ private static final int USER_ID = UserHandle.myUserId();
+ private static final UserHandle USER_HANDLE = new UserHandle(USER_ID);
@Mock
@@ -82,7 +83,7 @@
.thenReturn(mDevicePolicyManager);
when(mApplicationContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
mFingerprintStatusUtils =
- new FingerprintStatusUtils(mApplicationContext, mFingerprintManager);
+ new FingerprintStatusUtils(mApplicationContext, mFingerprintManager, USER_ID);
}
@Test
@@ -118,6 +119,20 @@
}
@Test
+ public void hasEnrolled_withEnrolledFingerprints_returnsTrue() {
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
+
+ assertThat(mFingerprintStatusUtils.hasEnrolled()).isTrue();
+ }
+
+ @Test
+ public void hasEnrolled_withoutEnrolledFingerprints_returnsFalse() {
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
+
+ assertThat(mFingerprintStatusUtils.hasEnrolled()).isFalse();
+ }
+
+ @Test
public void getDisabledAdmin_whenFingerprintDisabled_returnsEnforcedAdmin() {
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME))
.thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
diff --git a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java
index 13778f7..3030f0c 100644
--- a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java
+++ b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -112,8 +113,8 @@
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
- verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
- any(), any(), any(), any());
+ verify(mSafetyCenterManagerWrapper, never())
+ .setSafetySourceData(any(), any(), any(), any());
}
@Test
@@ -124,8 +125,8 @@
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
- verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
- any(), any(), any(), any());
+ verify(mSafetyCenterManagerWrapper, never())
+ .setSafetySourceData(any(), any(), any(), any());
}
@Test
@@ -137,11 +138,9 @@
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
- ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
- verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), captor.capture(), any(), any());
- assertThat(captor.getValue()).isEqualTo(BiometricsSafetySource.SAFETY_SOURCE_ID);
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), any(), any());
}
@Test
@@ -153,11 +152,9 @@
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
- ArgumentCaptor<SafetyEvent> captor = ArgumentCaptor.forClass(SafetyEvent.class);
- verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), any(), captor.capture());
- assertThat(captor.getValue()).isEqualTo(EVENT_SOURCE_STATE_CHANGED);
+ verify(mSafetyCenterManagerWrapper)
+ .setSafetySourceData(any(), any(), any(), eq(EVENT_SOURCE_STATE_CHANGED));
}
@Test
@@ -429,6 +426,128 @@
Settings.CombinedBiometricSettingsActivity.class.getName());
}
+ @Test
+ public void setSafetySourceData_faceAndFingerprint_whenFaceEnrolled_setsOkStatus() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
+
+ BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
+
+ ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
+ SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
+ assertThat(safetySourceStatus.getStatusLevel())
+ .isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK);
+ }
+
+ @Test
+ public void setSafetySourceData_faceAndFingerprint_whenFingerprintEnrolled_setsOkStatus() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
+
+ BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
+
+ ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
+ SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
+ assertThat(safetySourceStatus.getStatusLevel())
+ .isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK);
+ }
+
+ @Test
+ public void setSafetySourceData_faceAndFingerprint_whenNotEnrolled_setsNoneStatus() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
+
+ BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
+
+ ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
+ SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
+ assertThat(safetySourceStatus.getStatusLevel())
+ .isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE);
+ }
+
+ @Test
+ public void setSafetySourceData_fingerprint_whenEnrolled_setsOKStatus() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.isHardwareDetected()).thenReturn(false);
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
+
+ BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
+
+ ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
+ SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
+ assertThat(safetySourceStatus.getStatusLevel())
+ .isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK);
+ }
+
+ @Test
+ public void setSafetySourceData_fingerprint_whenNotEnrolled_setsNoneStatus() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.isHardwareDetected()).thenReturn(false);
+ when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
+
+ BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
+
+ ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
+ SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
+ assertThat(safetySourceStatus.getStatusLevel())
+ .isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE);
+ }
+
+ @Test
+ public void setSafetySourceData_face_whenEnrolled_setsOKStatus() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
+
+ BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
+
+ ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
+ SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
+ assertThat(safetySourceStatus.getStatusLevel())
+ .isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK);
+ }
+
+ @Test
+ public void setSafetySourceData_face_whenNotEnrolled_setsNoneStatus() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
+
+ BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
+
+ ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
+ SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
+ assertThat(safetySourceStatus.getStatusLevel())
+ .isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE);
+ }
+
private void assertSafetySourceDisabledDataSetWithSingularSummary(String expectedTitleResName,
String expectedSummaryResName) {
assertSafetySourceDisabledDataSet(
@@ -478,13 +597,16 @@
private void assertSafetySourceDisabledDataSet(String expectedTitle, String expectedSummary) {
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), captor.capture(), any());
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceData safetySourceData = captor.getValue();
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
assertThat(safetySourceStatus.getTitle().toString()).isEqualTo(expectedTitle);
assertThat(safetySourceStatus.getSummary().toString()).isEqualTo(expectedSummary);
assertThat(safetySourceStatus.isEnabled()).isFalse();
+ assertThat(safetySourceStatus.getStatusLevel())
+ .isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE);
+
final Intent clickIntent = safetySourceStatus.getPendingIntent().getIntent();
assertThat(clickIntent).isNotNull();
assertThat(clickIntent.getAction()).isEqualTo(ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
@@ -494,7 +616,7 @@
String expectedSettingsClassName) {
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), captor.capture(), any());
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceData safetySourceData = captor.getValue();
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
@@ -509,7 +631,6 @@
.isEqualTo(expectedSettingsClassName);
}
-
private List<Fingerprint> createFingerprintList(int size) {
final List<Fingerprint> fingerprintList = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
diff --git a/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java
index db2702d..ea36b6b 100644
--- a/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java
+++ b/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java
@@ -22,6 +22,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -117,12 +118,9 @@
LockScreenSafetySource.setSafetySourceData(mApplicationContext,
mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED);
- ArgumentCaptor<String> idCaptor = ArgumentCaptor.forClass(String.class);
- verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), idCaptor.capture(), any(), any());
- String safetySourceId = idCaptor.getValue();
- assertThat(safetySourceId).isEqualTo(LockScreenSafetySource.SAFETY_SOURCE_ID);
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(LockScreenSafetySource.SAFETY_SOURCE_ID), any(), any());
}
@Test
@@ -132,12 +130,9 @@
LockScreenSafetySource.setSafetySourceData(mApplicationContext,
mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED);
- ArgumentCaptor<SafetyEvent> eventCaptor = ArgumentCaptor.forClass(SafetyEvent.class);
- verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), any(), eventCaptor.capture());
- SafetyEvent safetyEvent = eventCaptor.getValue();
- assertThat(safetyEvent).isEqualTo(EVENT_SOURCE_STATE_CHANGED);
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), any(), any(), eq(EVENT_SOURCE_STATE_CHANGED));
}
@Test
@@ -176,7 +171,7 @@
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), captor.capture(), any());
+ any(), eq(LockScreenSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceData safetySourceData = captor.getValue();
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
@@ -195,7 +190,7 @@
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), captor.capture(), any());
+ any(), eq(LockScreenSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceData safetySourceData = captor.getValue();
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
@@ -221,7 +216,7 @@
}
@Test
- public void setSafetySourceData_whenLockPatternIsNotSecure_setIssue() {
+ public void setSafetySourceData_whenLockPatternIsNotSecure_setsIssue() {
whenScreenLockIsEnabled();
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mScreenLockPreferenceDetailsUtils.isLockPatternSecure()).thenReturn(false);
@@ -231,7 +226,7 @@
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), captor.capture(), any());
+ any(), eq(LockScreenSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceData safetySourceData = captor.getValue();
assertThat(safetySourceData.getIssues()).hasSize(1);
@@ -244,7 +239,7 @@
ResourcesUtils.getResourcesString(mApplicationContext,
"no_screen_lock_issue_summary"));
assertThat(issue.getSeverityLevel()).isEqualTo(
- SafetySourceStatus.STATUS_LEVEL_RECOMMENDATION);
+ SafetySourceIssue.SEVERITY_LEVEL_RECOMMENDATION);
assertThat(issue.getIssueTypeId()).isEqualTo(
LockScreenSafetySource.NO_SCREEN_LOCK_ISSUE_TYPE_ID);
assertThat(issue.getIssueCategory()).isEqualTo(SafetySourceIssue.ISSUE_CATEGORY_DEVICE);
@@ -270,7 +265,7 @@
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), captor.capture(), any());
+ any(), eq(LockScreenSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceData safetySourceData = captor.getValue();
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
@@ -289,7 +284,7 @@
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), captor.capture(), any());
+ any(), eq(LockScreenSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceData safetySourceData = captor.getValue();
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
@@ -311,7 +306,7 @@
final ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(
SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), captor.capture(), any());
+ any(), eq(LockScreenSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
final IconAction iconAction = captor.getValue().getStatus().getIconAction();
assertThat(iconAction.getIconType()).isEqualTo(IconAction.ICON_TYPE_GEAR);
@@ -330,7 +325,7 @@
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
- any(), any(), captor.capture(), any());
+ any(), eq(LockScreenSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceData safetySourceData = captor.getValue();
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
@@ -338,13 +333,16 @@
}
@Test
- public void onLockScreenChange_whenSafetyCenterEnabled_setData() {
+ public void onLockScreenChange_whenSafetyCenterEnabled_setsLockscreenAndBiometricData() {
whenScreenLockIsEnabled();
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
LockScreenSafetySource.onLockScreenChange(mApplicationContext);
- verify(mSafetyCenterManagerWrapper).setSafetySourceData(any(), any(), any(), any());
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(LockScreenSafetySource.SAFETY_SOURCE_ID), any(), any());
+ verify(mSafetyCenterManagerWrapper).setSafetySourceData(
+ any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), any(), any());
}
@Test