Merge "Allow deferred SUW to add multiple fingerprints" 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_icon_color_state_list.xml b/res/color/dream_card_icon_color_state_list.xml
new file mode 100644
index 0000000..c2e32cb
--- /dev/null
+++ b/res/color/dream_card_icon_color_state_list.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:state_selected="true" android:color="?androidprv:attr/textColorOnAccent"/>
+ <item android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
+</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/drawable/ic_accessibility_animation.xml b/res/drawable/ic_accessibility_animation.xml
new file mode 100644
index 0000000..13bc4a2
--- /dev/null
+++ b/res/drawable/ic_accessibility_animation.xml
@@ -0,0 +1,36 @@
+<!--
+ Copyright 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.
+ -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <com.android.settingslib.widget.AdaptiveIconShapeDrawable
+ android:width="@dimen/accessibility_icon_size"
+ android:height="@dimen/accessibility_icon_size"
+ android:color="@color/accessibility_feature_background"/>
+ </item>
+ <item android:gravity="center">
+ <vector
+ android:width="@dimen/accessibility_icon_foreground_size"
+ android:height="@dimen/accessibility_icon_foreground_size"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#ffffff"
+ android:fillType="evenOdd"
+ android:pathData="M9,22Q7.55,22 6.275,21.45Q5,20.9 4.05,19.95Q3.1,19 2.55,17.725Q2,16.45 2,15Q2,12.975 3.05,11.3Q4.1,9.625 5.8,8.75Q6.3,7.775 7.038,7.037Q7.775,6.3 8.75,5.8Q9.575,4.1 11.275,3.05Q12.975,2 15,2Q16.45,2 17.725,2.55Q19,3.1 19.95,4.05Q20.9,5 21.45,6.275Q22,7.55 22,9Q22,11.125 20.95,12.75Q19.9,14.375 18.2,15.25Q17.7,16.225 16.962,16.962Q16.225,17.7 15.25,18.2Q14.375,19.9 12.7,20.95Q11.025,22 9,22ZM9,20Q9.825,20 10.588,19.75Q11.35,19.5 12,19Q10.55,19 9.275,18.45Q8,17.9 7.05,16.95Q6.1,16 5.55,14.725Q5,13.45 5,12Q4.5,12.65 4.25,13.412Q4,14.175 4,15Q4,16.05 4.4,16.95Q4.8,17.85 5.475,18.525Q6.15,19.2 7.05,19.6Q7.95,20 9,20ZM12,17Q12.825,17 13.613,16.75Q14.4,16.5 15.05,16Q13.575,16 12.3,15.438Q11.025,14.875 10.075,13.925Q9.125,12.975 8.562,11.7Q8,10.425 8,8.95Q7.5,9.6 7.25,10.387Q7,11.175 7,12Q7,13.05 7.388,13.95Q7.775,14.85 8.475,15.525Q9.15,16.225 10.05,16.613Q10.95,17 12,17ZM15,14Q15.45,14 15.863,13.925Q16.275,13.85 16.7,13.7Q17.25,12.2 16.863,10.812Q16.475,9.425 15.525,8.475Q14.575,7.525 13.188,7.137Q11.8,6.75 10.3,7.3Q10.15,7.725 10.075,8.137Q10,8.55 10,9Q10,10.05 10.387,10.95Q10.775,11.85 11.475,12.525Q12.15,13.225 13.05,13.613Q13.95,14 15,14ZM19,12.05Q19.5,11.4 19.75,10.612Q20,9.825 20,9Q20,7.95 19.613,7.05Q19.225,6.15 18.525,5.475Q17.85,4.775 16.95,4.387Q16.05,4 15,4Q14.125,4 13.363,4.25Q12.6,4.5 11.95,5Q13.425,5 14.7,5.562Q15.975,6.125 16.925,7.075Q17.875,8.025 18.438,9.3Q19,10.575 19,12.05Z" />
+ </vector>
+ </item>
+</layer-list>
\ No newline at end of file
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/app_preferred_settings.xml b/res/layout/app_preferred_settings.xml
index b3343f5..126b9d8 100644
--- a/res/layout/app_preferred_settings.xml
+++ b/res/layout/app_preferred_settings.xml
@@ -18,7 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingStart="@dimen/preference_no_icon_padding_start"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingBottom="5dip"
android:orientation="vertical">
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 d845dfd..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 -->
@@ -5399,9 +5401,9 @@
<!-- Summary text for the accessibility button preference. [CHAR LIMIT=50] -->
<string name="accessibility_button_summary">Quickly access accessibility features</string>
<!-- Description for the accessibility button in gesture navigation. Explain how this page works. [CHAR LIMIT=NONE] -->
- <string name="accessibility_button_gesture_description"><b>How to use the button or gesture</b>\n\n1. Go to accessibility settings\n2. Select a feature and tap the shortcut\n3. To use the feature, tap the accessibility button or gesture</string>
+ <string name="accessibility_button_gesture_description"><b>To get started</b>\n1. Go to accessibility settings\n2. Select a feature and tap the shortcut\n3. Choose whether you want to use a button or gesture to access the feature</string>
<!-- Description for the accessibility button page. Explain how this page works. [CHAR LIMIT=NONE] -->
- <string name="accessibility_button_description"><b>How to use the button</b>\n\n1. Go to accessibility settings\n2. Select a feature and tap the shortcut\n3. To use the feature, tap the accessibility button</string>
+ <string name="accessibility_button_description"><b>To get started</b>\n1. Go to accessibility settings\n2. Select a feature and tap the shortcut\n3. Choose the button to use to access the feature</string>
<!-- Title for the button or gesture of the accessibility button. [CHAR LIMIT=35] -->
<string name="accessibility_button_or_gesture_title">Use button or gesture</string>
<!-- Title for the location of the accessibility button. [CHAR LIMIT=35] -->
@@ -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_color_and_motion.xml b/res/xml/accessibility_color_and_motion.xml
index 86b6564..a313526 100644
--- a/res/xml/accessibility_color_and_motion.xml
+++ b/res/xml/accessibility_color_and_motion.xml
@@ -39,7 +39,18 @@
settings:keywords="@string/keywords_color_inversion"
settings:controller="com.android.settings.accessibility.ColorInversionPreferenceController"/>
+ <com.android.settings.display.darkmode.DarkModePreference
+ android:key="dark_ui_mode_accessibility"
+ android:icon="@drawable/ic_dark_ui"
+ android:title="@string/dark_ui_mode"
+ android:fragment="com.android.settings.display.darkmode.DarkModeSettingsFragment"
+ android:widgetLayout="@null"
+ settings:widgetLayout="@null"
+ settings:controller="com.android.settings.display.DarkUIPreferenceController"
+ settings:searchable="false"/>
+
<SwitchPreference
+ android:icon="@drawable/ic_accessibility_animation"
android:key="toggle_disable_animations"
android:persistent="false"
android:summary="@string/accessibility_disable_animations_summary"
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 22226a1..509aed6 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -60,16 +60,6 @@
settings:keywords="@string/keywords_reduce_bright_colors"
settings:controller="com.android.settings.accessibility.ReduceBrightColorsPreferenceController"/>
- <com.android.settings.display.darkmode.DarkModePreference
- android:key="dark_ui_mode_accessibility"
- android:icon="@drawable/ic_dark_ui"
- android:title="@string/dark_ui_mode"
- android:fragment="com.android.settings.display.darkmode.DarkModeSettingsFragment"
- android:widgetLayout="@null"
- settings:widgetLayout="@null"
- settings:controller="com.android.settings.display.DarkUIPreferenceController"
- settings:searchable="false"/>
-
<Preference
android:fragment="com.android.settings.accessibility.MagnificationPreferenceFragment"
android:key="magnification_preference_screen"
@@ -79,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
@@ -160,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/accessibility_settings_for_setup_wizard.xml b/res/xml/accessibility_settings_for_setup_wizard.xml
index 78d8f72..a50e7dd 100644
--- a/res/xml/accessibility_settings_for_setup_wizard.xml
+++ b/res/xml/accessibility_settings_for_setup_wizard.xml
@@ -47,4 +47,12 @@
android:persistent="true"
android:summary="@string/talkback_summary"/>
+ <SwitchPreference
+ android:icon="@drawable/ic_accessibility_animation"
+ android:key="toggle_disable_animations"
+ android:persistent="false"
+ android:summary="@string/accessibility_disable_animations_summary"
+ android:title="@string/accessibility_disable_animations"
+ settings:controller="com.android.settings.accessibility.DisableAnimationsPreferenceController"/>
+
</PreferenceScreen>
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 c422df9..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"/>
@@ -648,7 +648,7 @@
android:title="@string/reset_shortcut_manager_throttling" />
</PreferenceCategory>
- <com.android.settings.development.autofill.AutofillPreferenceCategory
+ <PreferenceCategory
android:key="debug_autofill_category"
android:title="@string/debug_autofill_category"
settings:searchable="false"
@@ -672,7 +672,7 @@
android:key="autofill_reset_developer_options"
android:title="@string/autofill_reset_developer_options" />
- </com.android.settings.development.autofill.AutofillPreferenceCategory>
+ </PreferenceCategory>
<PreferenceCategory
android:key="storage_category"
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/TextReadingPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
index 0ff960f..930fbe4 100644
--- a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
@@ -16,6 +16,7 @@
package com.android.settings.accessibility;
+import android.app.settings.SettingsEnums;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -57,7 +58,7 @@
@Override
public int getMetricsCategory() {
- return super.getMetricsCategory();
+ return SettingsEnums.SUW_ACCESSIBILITY_TEXT_READING_OPTIONS;
}
@Override
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/dashboard/ControllerFutureTask.java b/src/com/android/settings/dashboard/ControllerFutureTask.java
deleted file mode 100644
index 84d11fd..0000000
--- a/src/com/android/settings/dashboard/ControllerFutureTask.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.dashboard;
-
-import com.android.settingslib.core.AbstractPreferenceController;
-
-import java.util.concurrent.FutureTask;
-
-/**
- * {@link FutureTask} of the Controller.
- */
-public class ControllerFutureTask extends FutureTask<Void> {
- private final AbstractPreferenceController mController;
-
- public ControllerFutureTask(ControllerTask task, Void result) {
- super(task, result);
- mController = task.getController();
- }
-
- AbstractPreferenceController getController() {
- return mController;
- }
-}
diff --git a/src/com/android/settings/dashboard/ControllerTask.java b/src/com/android/settings/dashboard/ControllerTask.java
deleted file mode 100644
index c62e738..0000000
--- a/src/com/android/settings/dashboard/ControllerTask.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.dashboard;
-
-import android.app.settings.SettingsEnums;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.utils.ThreadUtils;
-
-/**
- * A {@link Runnable} controller task. This task handle the visibility of the controller in the
- * background. Also handle the state updating in the main thread.
- */
-public class ControllerTask implements Runnable {
- private static final String TAG = "ControllerTask";
- private static final int CONTROLLER_UPDATESTATE_TIME_THRESHOLD = 50;
-
- private final AbstractPreferenceController mController;
- private final PreferenceScreen mScreen;
- private final int mMetricsCategory;
- private final MetricsFeatureProvider mMetricsFeature;
-
- public ControllerTask(AbstractPreferenceController controller, PreferenceScreen screen,
- MetricsFeatureProvider metricsFeature, int metricsCategory) {
- mController = controller;
- mScreen = screen;
- mMetricsFeature = metricsFeature;
- mMetricsCategory = metricsCategory;
- }
-
- @Override
- public void run() {
- if (!mController.isAvailable()) {
- return;
- }
-
- final String key = mController.getPreferenceKey();
- if (TextUtils.isEmpty(key)) {
- Log.d(TAG, String.format("Preference key is %s in Controller %s",
- key, mController.getClass().getSimpleName()));
- return;
- }
-
- final Preference preference = mScreen.findPreference(key);
- if (preference == null) {
- Log.d(TAG, String.format("Cannot find preference with key %s in Controller %s",
- key, mController.getClass().getSimpleName()));
- return;
- }
- ThreadUtils.postOnMainThread(() -> {
- final long t = SystemClock.elapsedRealtime();
- mController.updateState(preference);
- final int elapsedTime = (int) (SystemClock.elapsedRealtime() - t);
- if (elapsedTime > CONTROLLER_UPDATESTATE_TIME_THRESHOLD) {
- Log.w(TAG, "The updateState took " + elapsedTime + " ms in Controller "
- + mController.getClass().getSimpleName());
- if (mMetricsFeature != null) {
- mMetricsFeature.action(SettingsEnums.PAGE_UNKNOWN,
- SettingsEnums.ACTION_CONTROLLER_UPDATE_STATE, mMetricsCategory,
- mController.getClass().getSimpleName(), elapsedTime);
- }
- }
- });
- }
-
- AbstractPreferenceController getController() {
- return mController;
- }
-}
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 8b1d633..26fe1b1 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -48,7 +48,6 @@
import com.android.settingslib.drawer.ProviderTile;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.search.Indexable;
-import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.Arrays;
@@ -58,7 +57,6 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.ExecutionException;
/**
* Base fragment for dashboard style UI containing a list of static and dynamic setting items.
@@ -222,7 +220,7 @@
super.onResume();
updatePreferenceStates();
writeElapsedTimeMetric(SettingsEnums.ACTION_DASHBOARD_VISIBLE_TIME,
- "isParalleledControllers:" + isParalleledControllers());
+ "isParalleledControllers:false");
}
@Override
@@ -349,14 +347,6 @@
}
/**
- * @return {@code true} if the underlying controllers should be executed in parallel.
- * Override this function to enable/disable the behavior.
- */
- protected boolean isParalleledControllers() {
- return false;
- }
-
- /**
* Get current PreferenceController(s)
*/
protected Collection<List<AbstractPreferenceController>> getPreferenceControllers() {
@@ -395,36 +385,6 @@
}
/**
- * Use parallel method to update state of each preference managed by PreferenceController.
- */
- @VisibleForTesting
- // To use this parallel approach will cause the side effect of the UI flicker. Such as
- // the thumb sliding of the toggle button.
- void updatePreferenceStatesInParallel() {
- final PreferenceScreen screen = getPreferenceScreen();
- final Collection<List<AbstractPreferenceController>> controllerLists =
- mPreferenceControllers.values();
- final List<ControllerFutureTask> taskList = new ArrayList<>();
- for (List<AbstractPreferenceController> controllerList : controllerLists) {
- for (AbstractPreferenceController controller : controllerList) {
- final ControllerFutureTask task = new ControllerFutureTask(
- new ControllerTask(controller, screen, mMetricsFeatureProvider,
- getMetricsCategory()), null /* result */);
- taskList.add(task);
- ThreadUtils.postOnBackgroundThread(task);
- }
- }
-
- for (ControllerFutureTask task : taskList) {
- try {
- task.get();
- } catch (InterruptedException | ExecutionException e) {
- Log.w(TAG, task.getController().getPreferenceKey() + " " + e.getMessage());
- }
- }
- }
-
- /**
* Refresh all preference items, including both static prefs from xml, and dynamic items from
* DashboardCategory.
*/
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/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 434bcfd..57114e2 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -47,6 +47,7 @@
import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.development.autofill.AutofillCategoryController;
import com.android.settings.development.autofill.AutofillLoggingLevelPreferenceController;
import com.android.settings.development.autofill.AutofillResetOptionsPreferenceController;
import com.android.settings.development.bluetooth.AbstractBluetoothDialogPreferenceController;
@@ -566,6 +567,7 @@
controllers.add(new DefaultLaunchPreferenceController(context, "density"));
controllers.add(new DefaultLaunchPreferenceController(context, "background_check"));
controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps"));
+ controllers.add(new AutofillCategoryController(context, lifecycle));
controllers.add(new AutofillLoggingLevelPreferenceController(context, lifecycle));
controllers.add(new AutofillResetOptionsPreferenceController(context));
controllers.add(new BluetoothCodecDialogPreferenceController(context, lifecycle,
diff --git a/src/com/android/settings/development/autofill/AutofillCategoryController.java b/src/com/android/settings/development/autofill/AutofillCategoryController.java
new file mode 100644
index 0000000..91b3b9c
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillCategoryController.java
@@ -0,0 +1,103 @@
+/*
+ * 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.development.autofill;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.autofill.AutofillManager;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+/**
+ * Controller class for observing the state of AutofillManager.
+ */
+public class AutofillCategoryController extends DeveloperOptionsPreferenceController implements
+ LifecycleObserver, OnStart, OnStop {
+
+ private static final String TAG = "AutofillCategoryController";
+
+ private static final String CATEGORY_KEY = "debug_autofill_category";
+ private static final long DELAYED_MESSAGE_TIME_MS = 2000;
+
+ private ContentResolver mContentResolver;
+ private ContentObserver mSettingsObserver;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+ public AutofillCategoryController(Context context, Lifecycle lifecycle) {
+ super(context);
+
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+
+ mSettingsObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ // We cannot apply the change yet because AutofillManager.isEnabled() state is
+ // updated by a ContentObserver as well and there's no guarantee of which observer
+ // is called first - hence, it's possible that the state didn't change here yet.
+ mHandler.postDelayed(
+ () -> mPreference.notifyDependencyChange(shouldDisableDependents()),
+ DELAYED_MESSAGE_TIME_MS);
+ }
+ };
+ mContentResolver = context.getContentResolver();
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return CATEGORY_KEY;
+ }
+
+ @Override
+ public void onStart() {
+ mContentResolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.AUTOFILL_SERVICE), false,
+ mSettingsObserver);
+
+ }
+
+ @Override
+ public void onStop() {
+ mContentResolver.unregisterContentObserver(mSettingsObserver);
+ }
+
+ // PreferenceCategory.isEnabled() always return false, so we rather not change that logic
+ // decide whether the children should be shown using isAutofillEnabled() instead.
+ private boolean isAutofillEnabled() {
+ final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
+ final boolean enabled = afm != null && afm.isEnabled();
+ Log.v(TAG, "isAutofillEnabled(): " + enabled);
+ return enabled;
+ }
+
+ private boolean shouldDisableDependents() {
+ final boolean shouldIt = !isAutofillEnabled();
+ Log.v(TAG, "shouldDisableDependents(): " + shouldIt);
+ return shouldIt;
+ }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillPreferenceCategory.java b/src/com/android/settings/development/autofill/AutofillPreferenceCategory.java
deleted file mode 100644
index cbfbdd3..0000000
--- a/src/com/android/settings/development/autofill/AutofillPreferenceCategory.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.settings.development.autofill;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.Settings;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.autofill.AutofillManager;
-
-import androidx.preference.PreferenceCategory;
-
-public final class AutofillPreferenceCategory extends PreferenceCategory {
-
- private static final String TAG = "AutofillPreferenceCategory";
- private static final long DELAYED_MESSAGE_TIME_MS = 2000;
-
- private final ContentResolver mContentResolver;
- private final ContentObserver mSettingsObserver;
- private final Handler mHandler = new Handler(Looper.getMainLooper());
-
- public AutofillPreferenceCategory(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- mSettingsObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange, Uri uri, int userId) {
- // We cannot apply the change yet because AutofillManager.isEnabled() state is
- // updated by a ContentObserver as well and there's no guarantee of which observer
- // is called first - hence, it's possible that the state didn't change here yet.
- mHandler.postDelayed(() -> notifyDependencyChange(shouldDisableDependents()),
- DELAYED_MESSAGE_TIME_MS);
- }
- };
- mContentResolver = context.getContentResolver();
- }
-
- @Override
- public void onAttached() {
- super.onAttached();
-
- mContentResolver.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.AUTOFILL_SERVICE), false,
- mSettingsObserver);
- }
-
- @Override
- public void onDetached() {
- mContentResolver.unregisterContentObserver(mSettingsObserver);
-
- super.onDetached();
- }
-
- // PreferenceCategory.isEnabled() always return false, so we rather not change that logic
- // decide whether the children should be shown using isAutofillEnabled() instead.
- private boolean isAutofillEnabled() {
- final AutofillManager afm = getContext().getSystemService(AutofillManager.class);
- final boolean enabled = afm != null && afm.isEnabled();
- Log.v(TAG, "isAutofillEnabled(): " + enabled);
- return enabled;
- }
-
- @Override
- public boolean shouldDisableDependents() {
- final boolean shouldIt = !isAutofillEnabled();
- Log.v(TAG, "shouldDisableDependents(): " + shouldIt);
- return shouldIt;
- }
-}
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 2237712..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,17 +93,19 @@
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_text_color_state_list));
+ mContext.getColorStateList(R.color.dream_card_icon_color_state_list));
}
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/network/UiccSlotUtil.java b/src/com/android/settings/network/UiccSlotUtil.java
index c4f495c..9a157d6 100644
--- a/src/com/android/settings/network/UiccSlotUtil.java
+++ b/src/com/android/settings/network/UiccSlotUtil.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccSlotInfo;
import android.telephony.UiccSlotMapping;
@@ -47,6 +48,7 @@
private static final long DEFAULT_WAIT_AFTER_SWITCH_TIMEOUT_MILLIS = 25 * 1000L;
+ public static final int INVALID_LOGICAL_SLOT_ID = -1;
public static final int INVALID_PHYSICAL_SLOT_ID = -1;
public static final int INVALID_PORT_ID = -1;
@@ -115,24 +117,27 @@
}
TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
int inactiveRemovableSlot = getInactiveRemovableSlot(telMgr.getUiccSlotsInfo(), slotId);
- Log.i(TAG, "The InactiveRemovableSlot: " + inactiveRemovableSlot);
-
- Collection<UiccSlotMapping> uiccSlotMappings = telMgr.getSimSlotMapping();
- Log.i(TAG, "The SimSlotMapping: " + uiccSlotMappings);
-
+ Log.d(TAG, "The InactiveRemovableSlot: " + inactiveRemovableSlot);
if (inactiveRemovableSlot == INVALID_PHYSICAL_SLOT_ID) {
// The slot is invalid slot id, then to skip this.
// The slot is active, then the sim can enable directly.
return;
}
+ Collection<UiccSlotMapping> uiccSlotMappings = telMgr.getSimSlotMapping();
+ Log.d(TAG, "The SimSlotMapping: " + uiccSlotMappings);
+
+ SubscriptionManager subscriptionManager = context.getSystemService(
+ SubscriptionManager.class);
+ int excludedLogicalSlotIndex = getExcludedLogicalSlotIndex(uiccSlotMappings,
+ SubscriptionUtil.getActiveSubscriptions(subscriptionManager), removedSubInfo,
+ telMgr.isMultiSimEnabled());
performSwitchToSlot(telMgr,
prepareUiccSlotMappings(uiccSlotMappings,
/*slot is psim*/ true,
inactiveRemovableSlot,
/*removable sim's port Id*/ TelephonyManager.DEFAULT_PORT_INDEX,
- removedSubInfo,
- telMgr.isMultiSimEnabled()),
+ excludedLogicalSlotIndex),
context);
}
@@ -156,16 +161,21 @@
}
TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
Collection<UiccSlotMapping> uiccSlotMappings = telMgr.getSimSlotMapping();
- Log.i(TAG, "The SimSlotMapping: " + uiccSlotMappings);
+ Log.d(TAG, "The SimSlotMapping: " + uiccSlotMappings);
if (isTargetSlotActive(uiccSlotMappings, physicalSlotId, port)) {
- Log.i(TAG, "The slot is active, then the sim can enable directly.");
+ Log.d(TAG, "The slot is active, then the sim can enable directly.");
return;
}
+ SubscriptionManager subscriptionManager = context.getSystemService(
+ SubscriptionManager.class);
+ int excludedLogicalSlotIndex = getExcludedLogicalSlotIndex(uiccSlotMappings,
+ SubscriptionUtil.getActiveSubscriptions(subscriptionManager), removedSubInfo,
+ telMgr.isMultiSimEnabled());
performSwitchToSlot(telMgr,
prepareUiccSlotMappings(uiccSlotMappings, /*slot is not psim*/ false,
- physicalSlotId, port, removedSubInfo, telMgr.isMultiSimEnabled()),
+ physicalSlotId, port, excludedLogicalSlotIndex),
context);
}
@@ -276,74 +286,91 @@
@VisibleForTesting
static Collection<UiccSlotMapping> prepareUiccSlotMappings(
Collection<UiccSlotMapping> uiccSlotMappings, boolean isPsim, int physicalSlotId,
- int port, SubscriptionInfo removedSubInfo, boolean isMultiSimEnabled) {
+ int port, int removedLogicalSlotId) {
+ if (removedLogicalSlotId == INVALID_LOGICAL_SLOT_ID) {
+ Log.d(TAG, "There is no removedLogicalSlotId. Do nothing.");
+ return uiccSlotMappings;
+ }
+ Log.d(TAG,
+ String.format(
+ "Create new SimSlotMapping. Remove the UiccSlotMapping of logicalSlot%d"
+ + ", and insert PhysicalSlotId%d-Port%d",
+ removedLogicalSlotId, physicalSlotId, port));
Collection<UiccSlotMapping> newUiccSlotMappings = new ArrayList<>();
- if (!isMultiSimEnabled) {
- // In the 'SS mode', the port is 0.
- newUiccSlotMappings.add(new UiccSlotMapping(port, physicalSlotId, 0));
- } else if (removedSubInfo != null) {
- // DSDS+MEP
- // The target slot+port is not active, but the all of logical slots are full. It
- // needs to replace one of logical slots.
- Log.i(TAG,
- String.format(
- "Start to set SimSlotMapping from subId%d(LogicalSlot%d-Port%d) to "
- + "PhysicalSlotId%d-Port%d",
- removedSubInfo.getSubscriptionId(), removedSubInfo.getSimSlotIndex(),
- removedSubInfo.getPortIndex(), physicalSlotId, port));
-
- int logicalSlotIndex = 0;
- if (isPsim) {
- // The target slot is psim
- newUiccSlotMappings.add(
- new UiccSlotMapping(port, physicalSlotId, logicalSlotIndex++));
- }
- Collection<UiccSlotMapping> tempUiccSlotMappings =
- uiccSlotMappings.stream()
- .sorted(Comparator.comparingInt(UiccSlotMapping::getLogicalSlotIndex))
- .collect(Collectors.toList());
- for (UiccSlotMapping uiccSlotMapping : tempUiccSlotMappings) {
- if (isSubInfoMappingIntoUiccSlotMapping(uiccSlotMapping, removedSubInfo)) {
- if (!isPsim) {
- // Replace this uiccSlotMapping
- newUiccSlotMappings.add(new UiccSlotMapping(port, physicalSlotId,
- uiccSlotMapping.getLogicalSlotIndex()));
- }
- continue;
+ int logicalSlotIndex = 0;
+ if (isPsim) {
+ // The target slot is psim. The psim is always the first index at LogicalSlot.
+ newUiccSlotMappings.add(
+ new UiccSlotMapping(port, physicalSlotId, logicalSlotIndex++));
+ }
+ Collection<UiccSlotMapping> tempUiccSlotMappings =
+ uiccSlotMappings.stream()
+ .sorted(Comparator.comparingInt(UiccSlotMapping::getLogicalSlotIndex))
+ .collect(Collectors.toList());
+ for (UiccSlotMapping uiccSlotMapping : tempUiccSlotMappings) {
+ if (uiccSlotMapping.getLogicalSlotIndex() == removedLogicalSlotId) {
+ if (!isPsim) {
+ // Replace this uiccSlotMapping
+ newUiccSlotMappings.add(new UiccSlotMapping(port, physicalSlotId,
+ uiccSlotMapping.getLogicalSlotIndex()));
}
-
- // If the psim is inserted, then change the
- // logicalSlotIndex for another uiccSlotMappings.
- newUiccSlotMappings.add(isPsim
- ? new UiccSlotMapping(
- uiccSlotMapping.getPortIndex(),
- uiccSlotMapping.getPhysicalSlotIndex(),
- logicalSlotIndex++
- ) : uiccSlotMapping);
+ continue;
}
- } else {
- // For no inserted psim case in DSDS+MEP, there is only one esim in device and
- // then user inserts another esim in DSDS+MEP.
- // If the target is esim, then replace the psim.
- Log.i(TAG, "The removedSubInfo is null");
- newUiccSlotMappings =
- uiccSlotMappings.stream().map(uiccSlotMapping -> {
- if (!isPsim && uiccSlotMapping.getPhysicalSlotIndex() != physicalSlotId) {
- return new UiccSlotMapping(port, physicalSlotId,
- uiccSlotMapping.getLogicalSlotIndex());
- }
- return uiccSlotMapping;
- }).collect(Collectors.toList());
+
+ // If the psim is inserted, then change the logicalSlotIndex for another
+ // uiccSlotMappings.
+ newUiccSlotMappings.add(isPsim
+ ? new UiccSlotMapping(uiccSlotMapping.getPortIndex(),
+ uiccSlotMapping.getPhysicalSlotIndex(), logicalSlotIndex++)
+ : uiccSlotMapping);
}
- Log.i(TAG, "The SimSlotMapping: " + newUiccSlotMappings);
+ Log.d(TAG, "The new SimSlotMapping: " + newUiccSlotMappings);
return newUiccSlotMappings;
}
- private static boolean isSubInfoMappingIntoUiccSlotMapping(UiccSlotMapping uiccSlotMapping,
- SubscriptionInfo subscriptionInfo) {
- return uiccSlotMapping != null
- && uiccSlotMapping.getLogicalSlotIndex() == subscriptionInfo.getSimSlotIndex()
- && uiccSlotMapping.getPortIndex() == subscriptionInfo.getPortIndex();
+ /**
+ * To get the excluded logical slot index from uiccSlotMapping list. If the sim which is
+ * enabled by user does not have the corresponding slot, then it needs to do the
+ * SimSlotMapping changed. This method can find the logical slot index of the corresponding slot
+ * before the Frameworks do the SimSlotMapping changed.
+ *
+ * @param uiccSlotMappings The uiccSlotMapping list from the Telephony Frameworks.
+ * @param activeSubInfos The active subscriptionInfo list.
+ * @param removedSubInfo The removed sim card which is selected by the user. If the user
+ * don't select removed sim , then the value is null.
+ * @param isMultiSimEnabled whether the device is in the DSDS mode or not.
+ * @return The logical slot index of removed slot. If it can't find the removed slot, it
+ * returns {@link #INVALID_LOGICAL_SLOT_ID}.
+ */
+ @VisibleForTesting
+ static int getExcludedLogicalSlotIndex(Collection<UiccSlotMapping> uiccSlotMappings,
+ Collection<SubscriptionInfo> activeSubInfos, SubscriptionInfo removedSubInfo,
+ boolean isMultiSimEnabled) {
+ if (!isMultiSimEnabled) {
+ Log.i(TAG, "In the ss mode.");
+ return 0;
+ }
+ if (removedSubInfo != null) {
+ // Use removedSubInfo's logicalSlotIndex
+ Log.i(TAG, "The removedSubInfo is not null");
+ return removedSubInfo.getSimSlotIndex();
+ }
+ // If it needs to do simSlotMapping when user enables sim and there is an empty slot which
+ // there is no enabled sim in this slot, then the empty slot can be removed.
+ Log.i(TAG, "The removedSubInfo is null");
+ return uiccSlotMappings.stream()
+ .filter(uiccSlotMapping -> {
+ // find the empty slots.
+ for (SubscriptionInfo subInfo : activeSubInfos) {
+ if (subInfo.getSimSlotIndex() == uiccSlotMapping.getLogicalSlotIndex()) {
+ return false;
+ }
+ }
+ return true;
+ })
+ .mapToInt(uiccSlotMapping -> uiccSlotMapping.getLogicalSlotIndex())
+ .findFirst()
+ .orElse(INVALID_LOGICAL_SLOT_ID);
}
}
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/src/com/android/settings/wifi/p2p/WifiP2pSettings.java b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
index a926360..404cdd3 100644
--- a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
+++ b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
@@ -375,13 +375,20 @@
super.onPause();
if (mWifiP2pManager != null && mChannel != null) {
mWifiP2pManager.stopPeerDiscovery(mChannel, null);
+ }
+ getActivity().unregisterReceiver(mReceiver);
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if (mWifiP2pManager != null && mChannel != null) {
if (!mLastGroupFormed) {
// Close the channel when p2p doesn't connected.
mChannel.close();
mChannel = null;
}
}
- getActivity().unregisterReceiver(mReceiver);
}
@Override
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/dashboard/ControllerFutureTaskTest.java b/tests/robotests/src/com/android/settings/dashboard/ControllerFutureTaskTest.java
deleted file mode 100644
index c66f2b5..0000000
--- a/tests/robotests/src/com/android/settings/dashboard/ControllerFutureTaskTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.dashboard;
-
-import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.core.BasePreferenceController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class ControllerFutureTaskTest {
- private static final String KEY = "my_key";
-
- private Context mContext;
- private TestPreferenceController mTestController;
- private PreferenceScreen mScreen;
-
- @Before
- public void setUp() {
- mContext = RuntimeEnvironment.application;
- mTestController = new TestPreferenceController(mContext, KEY);
- final PreferenceManager preferenceManager = new PreferenceManager(mContext);
- mScreen = preferenceManager.createPreferenceScreen(mContext);
- }
-
- @Test
- public void getController_addTask_checkControllerKey() {
- final ControllerFutureTask futureTask = new ControllerFutureTask(
- new ControllerTask(mTestController, mScreen, null /* metricsFeature */,
- METRICS_CATEGORY_UNKNOWN), null /* result */);
-
- assertThat(futureTask.getController().getPreferenceKey()).isEqualTo(KEY);
- }
-
-
- static class TestPreferenceController extends BasePreferenceController {
- TestPreferenceController(Context context, String preferenceKey) {
- super(context, preferenceKey);
- }
-
- @Override
- public int getAvailabilityStatus() {
- return AVAILABLE;
- }
- }
-}
diff --git a/tests/robotests/src/com/android/settings/dashboard/ControllerTaskTest.java b/tests/robotests/src/com/android/settings/dashboard/ControllerTaskTest.java
deleted file mode 100644
index 17ab79c..0000000
--- a/tests/robotests/src/com/android/settings/dashboard/ControllerTaskTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.dashboard;
-
-import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.AbstractPreferenceController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class ControllerTaskTest {
- private static final String KEY = "my_key";
-
- private Context mContext;
- private PreferenceScreen mScreen;
- private TestPreferenceController mTestController;
- private ControllerTask mControllerTask;
-
- @Before
- public void setUp() {
- mContext = RuntimeEnvironment.application;
- final PreferenceManager preferenceManager = new PreferenceManager(mContext);
- mScreen = preferenceManager.createPreferenceScreen(mContext);
- mTestController = spy(new TestPreferenceController(mContext));
- mControllerTask = new ControllerTask(mTestController, mScreen, null /* metricsFeature */,
- METRICS_CATEGORY_UNKNOWN);
- }
-
- @Test
- public void doRun_controlNotAvailable_noRunUpdateState() {
- mTestController.setAvailable(false);
-
- mControllerTask.run();
-
- verify(mTestController, never()).updateState(any(Preference.class));
- }
-
- @Test
- public void doRun_emptyKey_noRunUpdateState() {
- mTestController.setKey("");
-
- mControllerTask.run();
-
- verify(mTestController, never()).updateState(any(Preference.class));
- }
-
- @Test
- public void doRun_preferenceNotExist_noRunUpdateState() {
- mTestController.setKey(KEY);
-
- mControllerTask.run();
-
- verify(mTestController, never()).updateState(any(Preference.class));
- }
-
- @Test
- public void doRun_executeUpdateState() {
- mTestController.setKey(KEY);
- final Preference preference = new Preference(mContext);
- preference.setKey(KEY);
- mScreen.addPreference(preference);
-
- mControllerTask.run();
-
- verify(mTestController).updateState(any(Preference.class));
- }
-
- static class TestPreferenceController extends AbstractPreferenceController {
- private boolean mAvailable;
- private String mKey;
-
- TestPreferenceController(Context context) {
- super(context);
- mAvailable = true;
- }
-
- @Override
- public boolean isAvailable() {
- return mAvailable;
- }
-
- @Override
- public String getPreferenceKey() {
- return mKey;
- }
-
- void setAvailable(boolean available) {
- mAvailable = available;
- }
-
- void setKey(String key) {
- mKey = key;
- }
- }
-}
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
index aa5f980..894a6c5 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
@@ -390,7 +390,6 @@
private final ContentResolver mContentResolver;
public final PreferenceScreen mScreen;
- private boolean mIsParalleled;
public TestFragment(Context context) {
mContext = context;
@@ -398,7 +397,6 @@
mScreen = mock(PreferenceScreen.class);
mContentResolver = mock(ContentResolver.class);
mControllers = new ArrayList<>();
- mIsParalleled = true;
when(mPreferenceManager.getContext()).thenReturn(mContext);
ReflectionHelpers.setField(
@@ -445,13 +443,6 @@
return mContentResolver;
}
- protected boolean isParalleledControllers() {
- return mIsParalleled;
- }
-
- void setUsingControllerEnhancement(boolean isParalleled) {
- mIsParalleled = isParalleled;
- }
}
private static class TestDynamicDataObserver extends DynamicDataObserver {
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/robotests/src/com/android/settings/wifi/p2p/WifiP2pSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2pSettingsTest.java
index 332cf14..448c109 100644
--- a/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2pSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2pSettingsTest.java
@@ -320,11 +320,17 @@
}
@Test
+ public void onStop_notLastGroupFormed_shouldCloseChannel() {
+ mFragment.onStop();
+
+ assertThat(mFragment.mChannel).isNull();
+ }
+
+ @Test
public void peerDiscovery_whenOnPause_shouldStop() {
mFragment.onPause();
verify(mWifiP2pManager, times(1)).stopPeerDiscovery(any(), any());
- assertThat(mFragment.mChannel).isNull();
}
@Test
@@ -332,7 +338,6 @@
mFragment.onPause();
verify(mWifiP2pManager, times(1)).stopPeerDiscovery(any(), any());
- assertThat(mFragment.mChannel).isNull();
mFragment.onResume();
assertThat(mFragment.mChannel).isNotNull();
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/network/UiccSlotUtilTest.java b/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
index 8a0a4b0..cc9bdfc 100644
--- a/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
+++ b/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
@@ -116,9 +116,10 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingSsModePsimActive();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingSsModeEsimPort0Active();
+ int removedLogicalSlotIndex = 0;
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, null, false);
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -129,9 +130,10 @@
createUiccSlotMappingSsModeEsimPort0Active();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingSsModePsimActive();
+ int removedLogicalSlotIndex = 0;
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, null, false);
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -141,9 +143,10 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingPsimAndPort1();
- SubscriptionInfo subInfo = createSubscriptionInfo(1, 0);
+ int removedLogicalSlotIndex = 1;
+
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, subInfo, true);
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -153,10 +156,10 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingPsimAndPort0();
+ int removedLogicalSlotIndex = 1;
- SubscriptionInfo subInfo = createSubscriptionInfo(1, 1);
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, subInfo, true);
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -166,10 +169,10 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingDualPortsB();
+ int removedLogicalSlotIndex = 0;
- SubscriptionInfo subInfo = createSubscriptionInfo(0, 0);
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, subInfo, true);
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -179,10 +182,10 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingDualPortsA();
+ int removedLogicalSlotIndex = 0;
- SubscriptionInfo subInfo = createSubscriptionInfo(0, 0);
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, subInfo, true);
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -192,9 +195,10 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingDualPortsB();
+ int removedLogicalSlotIndex = 0;
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, null, true);
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -204,9 +208,66 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingDualPortsA();
+ int removedLogicalSlotIndex = 0;
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, null, true);
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_oneEsimAndFromDualPortsAToPsimAndPort1_psimAndPort1() {
+ // There is only one enabled esimPort1 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort1();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_oneEsimAndFromDualPortsAToPsimAndPort0_psimAndPort0() {
+ // There is only one enabled esimPort0 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort0();
+ int removedLogicalSlotIndex = 1;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_oneEsimAndFromDualPortsBToPsimAndPort1_psimAndPort1() {
+ // There is only one enabled esimPort1 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort1();
+ int removedLogicalSlotIndex = 1;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_oneEsimAndFromDualPortsBToPsimAndPort0_psimAndPort0() {
+ // There is only one enabled esimPort0 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort0();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -216,10 +277,10 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingPsimAndPort1();
+ int removedLogicalSlotIndex = 0;
- SubscriptionInfo subInfo = createSubscriptionInfo(0, 0);
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, subInfo, true);
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -229,10 +290,10 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingPsimAndPort0();
+ int removedLogicalSlotIndex = 1;
- SubscriptionInfo subInfo = createSubscriptionInfo(1, 1);
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, subInfo, true);
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -242,10 +303,10 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingPsimAndPort1();
+ int removedLogicalSlotIndex = 1;
- SubscriptionInfo subInfo = createSubscriptionInfo(1, 0);
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, subInfo, true);
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
@@ -255,20 +316,240 @@
Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
Collection<UiccSlotMapping> verifyUiccSlotMappings =
createUiccSlotMappingPsimAndPort0();
+ int removedLogicalSlotIndex = 0;
- SubscriptionInfo subInfo = createSubscriptionInfo(0, 1);
Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
- uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, subInfo, true);
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
}
- private SubscriptionInfo createSubscriptionInfo(int logicalSlotIndex, int portIndex) {
- return new SubscriptionInfo(
- 0, "", logicalSlotIndex, "", "", 0, 0, "", 0, null, "", "", "",
- true /* isEmbedded */,
- null, "", 25,
- false, null, false, 0, 0, 0, null, null, true, portIndex);
+ @Test
+ public void getExcludedLogicalSlotIndex_fromPsimActiveToEsimPort0Active_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingSsModePsimActive();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(0, 0);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, false);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromEsimPort0ActiveToPsimActive_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingSsModeEsimPort0Active();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(0, 0);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, false);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromPsimAndPort0ToPsimAndPort1_logicalSlot1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 0);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(1, 0);
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromPsimAndPort1ToPsimAndPort0_logicalSlot1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 1);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(1, 1);
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromPsimAndPort0ToDualPortsB_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 0);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(0, 0);
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromPsimAndPort1ToDualPortsA_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 1);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(0, 0);
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_noPsimAndFromPsimAndPort0ToDualPortsB_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(1, 0);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_noPsimAndFromPsimAndPort1ToDualPortsA_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(1, 1);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_oneEsimAndFromDualPortsAToPsimAndPort1_logicalSlot0() {
+ // There is only one enabled esimPort1 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(1, 1);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_oneEsimAndFromDualPortsAToPsimAndPort0_logicalSlot1() {
+ // There is only one enabled esimPort0 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(0, 0);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_oneEsimAndFromDualPortsBToPsimAndPort1_logicalSlot1() {
+ // There is only one enabled esimPort1 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(0, 1);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_oneEsimAndFromDualPortsBToPsimAndPort0_logicalSlot0() {
+ // There is only one enabled esimPort0 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(1, 0);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromDualPortsAToPsimAndPort1_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 1);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(0, 0);
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromDualPortsAToPsimAndPort0_logicalSlot1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 1);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(1, 1);
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromDualPortsBToPsimAndPort1_logicalSlot1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 1, 1, 0);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(1, 0);
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromDualPortsBToPsimAndPort0_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 1, 1, 0);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(0, 1);
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
}
private void compareTwoUiccSlotMappings(Collection<UiccSlotMapping> testUiccSlotMappings,
@@ -288,6 +569,30 @@
}
}
+ private SubscriptionInfo createSubscriptionInfo(int logicalSlotIndex, int portIndex) {
+ return new SubscriptionInfo(
+ 0, "", logicalSlotIndex, "", "", 0, 0, "", 0, null, "", "", "",
+ true /* isEmbedded */,
+ null, "", 25,
+ false, null, false, 0, 0, 0, null, null, true, portIndex);
+ }
+
+ private List<SubscriptionInfo> createActiveSubscriptionInfoListOneSim(int logicalSlotIndex,
+ int portIndex) {
+ List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
+ subscriptionInfoList.add(createSubscriptionInfo(logicalSlotIndex, portIndex));
+
+ return subscriptionInfoList;
+ }
+
+ private List<SubscriptionInfo> createActiveSubscriptionInfoListTwoSims(int logicalSlotIndex1,
+ int portIndex1, int logicalSlotIndex2, int portIndex2) {
+ List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
+ subscriptionInfoList.add(createSubscriptionInfo(logicalSlotIndex1, portIndex1));
+ subscriptionInfoList.add(createSubscriptionInfo(logicalSlotIndex2, portIndex2));
+ return subscriptionInfoList;
+ }
+
// Device | |Slot |
// Working| |Mapping|
// State |Type |Mode |Friendly name
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