Snap for 12404440 from 9cdd1108c3 to 24Q4-release

Change-Id: Iaf43ac3fd61ffff035ebf51289ef758f4ca42b47
This commit is contained in:
Android Build Coastguard Worker
2024-09-23 23:22:59 +00:00
41 changed files with 935 additions and 951 deletions

View File

@@ -1,658 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="4">
<issue
id="LintError"
severity="Error"
message="No `.class` files were found in project &quot;.&quot;, so none of the classfile based checks could be run. Does the project need to be built first?"
category="Lint"
priority="10"
summary="Lint Failure"
explanation="This issue type represents a problem running lint itself. Examples include failure to find bytecode for source files (which means certain detectors could not be run), parsing errors in lint configuration files, etc.&#xA;These errors are not errors in your own code, but they are shown to make it clear that some checks were not completed.">
<location
file="."/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview.xml"
line="38"
column="34"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview.xml"
line="38"
column="34"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.695&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview.xml"
line="39"
column="38"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.695&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview.xml"
line="39"
column="38"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview.xml"
line="52"
column="34"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview.xml"
line="52"
column="34"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.695&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview.xml"
line="53"
column="38"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.695&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview.xml"
line="53"
column="38"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview.xml"
line="66"
column="34"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview.xml"
line="66"
column="34"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.695&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview.xml"
line="67"
column="38"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.695&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview.xml"
line="67"
column="38"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="46"
column="36"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#001A73E8&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="46"
column="36"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.69&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="47"
column="39"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.69&quot; android:color=&quot;#FF1A73E8&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="47"
column="39"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="60"
column="36"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#001A73E8&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="60"
column="36"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.69&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="61"
column="39"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.69&quot; android:color=&quot;#FF1A73E8&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="61"
column="39"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="74"
column="36"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#001A73E8&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="74"
column="36"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.69&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="75"
column="39"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.69&quot; android:color=&quot;#FF1A73E8&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_three_finger_preview_tablet.xml"
line="75"
column="39"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_two_finger_preview.xml"
line="38"
column="34"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_two_finger_preview.xml"
line="38"
column="34"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.695&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_two_finger_preview.xml"
line="39"
column="38"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.695&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_two_finger_preview.xml"
line="39"
column="38"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_two_finger_preview.xml"
line="52"
column="34"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_two_finger_preview.xml"
line="52"
column="34"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.695&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_two_finger_preview.xml"
line="53"
column="38"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.695&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_two_finger_preview.xml"
line="53"
column="38"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_two_finger_preview_tablet.xml"
line="46"
column="36"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#001A73E8&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_two_finger_preview_tablet.xml"
line="46"
column="36"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.69&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_two_finger_preview_tablet.xml"
line="47"
column="39"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.69&quot; android:color=&quot;#FF1A73E8&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_two_finger_preview_tablet.xml"
line="47"
column="39"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#00669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_two_finger_preview_tablet.xml"
line="60"
column="36"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#001A73E8&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_two_finger_preview_tablet.xml"
line="60"
column="36"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.69&quot; android:color=&quot;#FF669DF6&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable-night/accessibility_gesture_navigation_two_finger_preview_tablet.xml"
line="61"
column="39"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0.69&quot; android:color=&quot;#FF1A73E8&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/accessibility_gesture_navigation_two_finger_preview_tablet.xml"
line="61"
column="39"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -1949,6 +1297,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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;pointer_fill_outline_color&quot;>#FFFFFF&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-night/colors.xml"
line="81"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -3277,6 +2641,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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;pointer_fill_outline_color&quot;>#000000&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="223"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -4685,6 +4065,22 @@
column="11"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/accessibility_feature_background&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/ic_pointer_and_touchpad.xml"
line="22"
column="13"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -5101,6 +4497,102 @@
column="15"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/pointer_fill_outline_color&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/pointer_icon_fill_color_foreground.xml"
line="25"
column="25"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/pointer_fill_outline_color&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/pointer_icon_fill_color_foreground.xml"
line="25"
column="25"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/pointer_fill_outline_color&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/pointer_icon_fill_color_foreground.xml"
line="47"
column="29"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/pointer_fill_outline_color&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/pointer_icon_fill_color_foreground.xml"
line="47"
column="29"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/pointer_fill_outline_color&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/pointer_icon_fill_color_foreground.xml"
line="64"
column="17"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/pointer_fill_outline_color&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/pointer_icon_fill_color_foreground.xml"
line="64"
column="17"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -6973,103 +6465,4 @@
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/accessibility_feature_background&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/ic_pointer_and_touchpad.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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;pointer_fill_outline_color&quot;>#FFFFFF&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-night/colors.xml"
line="81"
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;pointer_fill_outline_color&quot;>#000000&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="223"
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/pointer_fill_outline_color&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/pointer_icon_fill_color_foreground.xml"
line="25"
column="25"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/pointer_fill_outline_color&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/pointer_icon_fill_color_foreground.xml"
line="47"
column="25"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/pointer_fill_outline_color&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/pointer_icon_fill_color_foreground.xml"
line="64"
column="25"/>
</issue>
</issues>

View File

@@ -12141,8 +12141,8 @@
<string name="title_have_satellite_plan">Satellite messaging is included with your account</string>
<!-- Title for category "Your mobile plan when satellite is not included in plan" [CHAR_LIMIT=NONE] -->
<string name="title_no_satellite_plan">Satellite messaging isn\u2019t included with your account</string>
<!-- text view add satellite messaging" [CHAR_LIMIT=NONE] -->
<string name="summary_add_satellite_setting">Add satellite messaging</string>
<!-- text view "Learn more" [CHAR_LIMIT=NONE] -->
<string name="summary_add_satellite_setting">Learn More</string>
<!-- Category name "How it works" [CHAR_LIMIT=NONE] -->
<string name="category_name_how_it_works">How it works</string>
<!-- Title for satellite connection guide [CHAR_LIMIT=NONE] -->

View File

@@ -72,7 +72,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
@Nullable
private AlertDialog mLoadingDialog = null;
private AlertDialog mProgressDialog = null;
@VisibleForTesting
boolean mShouldTriggerAudioSharingShareThenPairFlow = false;
private CopyOnWriteArrayList<BluetoothDevice> mDevicesWithMetadataChangedListener =
@@ -89,7 +89,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
// In share then pair flow, we have to wait on this page till the device is connected.
// The BluetoothDevicePreference summary will be blank for seconds between "Pairing..." and
// "Connecting..." To help users better understand the process, we listen to metadata change
// as well and show a loading dialog with "Connecting to ...." once BluetoothDevice.getState()
// as well and show a progress dialog with "Connecting to ...." once BluetoothDevice.getState()
// gets to BOND_BONDED.
final BluetoothAdapter.OnMetadataChangedListener mMetadataListener =
new BluetoothAdapter.OnMetadataChangedListener() {
@@ -97,7 +97,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
public void onMetadataChanged(@NonNull BluetoothDevice device, int key,
@Nullable byte[] value) {
Log.d(getLogTag(), "onMetadataChanged device = " + device + ", key = " + key);
if (mShouldTriggerAudioSharingShareThenPairFlow && mLoadingDialog == null
if (mShouldTriggerAudioSharingShareThenPairFlow && mProgressDialog == null
&& device.getBondState() == BluetoothDevice.BOND_BONDED
&& mSelectedList.contains(device)) {
triggerAudioSharingShareThenPairFlow(device);
@@ -355,7 +355,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
return;
}
mJustBonded = device;
// Show connecting device loading state
// Show connecting device progress
String aliasName = device.getAlias();
String deviceName = TextUtils.isEmpty(aliasName) ? device.getAddress()
: aliasName;
@@ -387,9 +387,9 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
// TODO: use DialogFragment
private void showConnectingDialog(@NonNull String message) {
postOnMainThread(() -> {
if (mLoadingDialog != null) {
if (mProgressDialog != null) {
Log.d(getLogTag(), "showConnectingDialog, is already showing");
TextView textView = mLoadingDialog.findViewById(R.id.message);
TextView textView = mProgressDialog.findViewById(R.id.message);
if (textView != null && !message.equals(textView.getText().toString())) {
Log.d(getLogTag(), "showConnectingDialog, update message");
// TODO: use string res once finalized
@@ -401,7 +401,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = LayoutInflater.from(builder.getContext());
View customView = inflater.inflate(
R.layout.dialog_audio_sharing_loading_state, /* root= */
R.layout.dialog_audio_sharing_progress, /* root= */
null);
TextView textView = customView.findViewById(R.id.message);
if (textView != null) {
@@ -410,15 +410,15 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
}
AlertDialog dialog = builder.setView(customView).setCancelable(false).create();
dialog.setCanceledOnTouchOutside(false);
mLoadingDialog = dialog;
mProgressDialog = dialog;
dialog.show();
});
}
private void dismissConnectingDialog() {
postOnMainThread(() -> {
if (mLoadingDialog != null) {
mLoadingDialog.dismiss();
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
});
}

View File

@@ -26,6 +26,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
import android.util.Log;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
@@ -36,10 +37,16 @@ import androidx.slice.builders.SliceAction;
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.connecteddevice.BluetoothDashboardFragment;
import com.android.settings.network.SatelliteRepository;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Utility class to build a Bluetooth Slice, and handle all associated actions.
*/
@@ -80,18 +87,34 @@ public class BluetoothSliceBuilder {
final PendingIntent primaryAction = getPrimaryAction(context);
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
ListBuilder.ICON_IMAGE, title);
final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
null /* actionTitle */, isBluetoothEnabled);
RowBuilder rowBuilder = new RowBuilder();
rowBuilder.setTitle(title);
rowBuilder.setPrimaryAction(primarySliceAction);
if (!isSatelliteOn(context)) {
final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
null /* actionTitle */, isBluetoothEnabled);
rowBuilder.addEndItem(toggleSliceAction);
}
return new ListBuilder(context, CustomSliceRegistry.BLUETOOTH_URI, ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)
.addEndItem(toggleSliceAction)
.setPrimaryAction(primarySliceAction))
.addRow(rowBuilder)
.build();
}
private static boolean isSatelliteOn(Context context) {
boolean result = false;
SatelliteRepository satelliteRepository = new SatelliteRepository(context);
try {
result = satelliteRepository.requestIsSessionStarted(
Executors.newSingleThreadExecutor()).get(3000, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Log.e(TAG, "Error to get satellite status : " + e);
}
return result;
}
public static Intent getIntent(Context context) {
final String screenTitle = context.getText(R.string.bluetooth_settings_title).toString();
final Uri contentUri = new Uri.Builder().appendPath(

View File

@@ -29,8 +29,8 @@ import androidx.fragment.app.FragmentManager;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.bluetooth.BluetoothUtils;
public class AudioSharingRetryDialogFragment extends InstrumentedDialogFragment {
private static final String TAG = "AudioSharingRetryDialog";
public class AudioSharingErrorDialogFragment extends InstrumentedDialogFragment {
private static final String TAG = "AudioSharingErrorDialog";
@Override
public int getMetricsCategory() {
@@ -39,7 +39,7 @@ public class AudioSharingRetryDialogFragment extends InstrumentedDialogFragment
}
/**
* Display the {@link AudioSharingRetryDialogFragment} dialog.
* Display the {@link AudioSharingErrorDialogFragment} dialog.
*
* @param host The Fragment this dialog will be hosted.
*/
@@ -57,8 +57,8 @@ public class AudioSharingRetryDialogFragment extends InstrumentedDialogFragment
Log.d(TAG, "Dialog is showing, return.");
return;
}
Log.d(TAG, "Show up the retry dialog.");
AudioSharingRetryDialogFragment dialogFrag = new AudioSharingRetryDialogFragment();
Log.d(TAG, "Show up the error dialog.");
AudioSharingErrorDialogFragment dialogFrag = new AudioSharingErrorDialogFragment();
dialogFrag.show(manager, TAG);
}

View File

@@ -40,8 +40,8 @@ import com.google.common.base.Strings;
import java.util.concurrent.TimeUnit;
public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFragment {
private static final String TAG = "AudioSharingLoadingDlg";
public class AudioSharingProgressDialogFragment extends InstrumentedDialogFragment {
private static final String TAG = "AudioSharingProgressDlg";
private static final String BUNDLE_KEY_MESSAGE = "bundle_key_message";
private static final long AUTO_DISMISS_TIME_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(15);
@@ -58,7 +58,7 @@ public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFr
}
/**
* Display the {@link AudioSharingLoadingStateDialogFragment} dialog.
* Display the {@link AudioSharingProgressDialogFragment} dialog.
*
* @param host The Fragment this dialog will be hosted by.
* @param message The content to be shown on the dialog.
@@ -85,16 +85,15 @@ public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFr
return;
}
sMessage = message;
Log.d(TAG, "Show up the loading dialog.");
Log.d(TAG, "Show up the progress dialog.");
Bundle args = new Bundle();
args.putString(BUNDLE_KEY_MESSAGE, message);
AudioSharingLoadingStateDialogFragment dialogFrag =
new AudioSharingLoadingStateDialogFragment();
AudioSharingProgressDialogFragment dialogFrag = new AudioSharingProgressDialogFragment();
dialogFrag.setArguments(args);
dialogFrag.show(manager, TAG);
}
/** Dismiss the {@link AudioSharingLoadingStateDialogFragment} dialog. */
/** Dismiss the {@link AudioSharingProgressDialogFragment} dialog. */
public static void dismiss(@Nullable Fragment host) {
if (host == null || !BluetoothUtils.isAudioSharingEnabled()) return;
final FragmentManager manager;
@@ -119,7 +118,7 @@ public class AudioSharingLoadingStateDialogFragment extends InstrumentedDialogFr
String message = args.getString(BUNDLE_KEY_MESSAGE, "");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = LayoutInflater.from(builder.getContext());
View customView = inflater.inflate(R.layout.dialog_audio_sharing_loading_state, /* root= */
View customView = inflater.inflate(R.layout.dialog_audio_sharing_progress, /* root= */
null);
TextView textView = customView.findViewById(R.id.message);
if (!Strings.isNullOrEmpty(message)) textView.setText(message);

View File

@@ -41,7 +41,9 @@ import android.widget.CompoundButton.OnCheckedChangeListener;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
@@ -69,7 +71,6 @@ import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
@@ -113,14 +114,21 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
private final Executor mExecutor;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final OnAudioSharingStateChangedListener mListener;
@VisibleForTesting IntentFilter mIntentFilter;
private Map<Integer, List<BluetoothDevice>> mGroupedConnectedDevices = new HashMap<>();
@Nullable private AudioSharingDeviceItem mTargetActiveItem;
private List<AudioSharingDeviceItem> mDeviceItemsForSharing = new ArrayList<>();
@VisibleForTesting IntentFilter mIntentFilter;
private final AtomicBoolean mCallbacksRegistered = new AtomicBoolean(false);
private AtomicInteger mIntentHandleStage =
new AtomicInteger(StartIntentHandleStage.TO_HANDLE.ordinal());
// The sinks in adding source process. We show the progress dialog based on this list.
private CopyOnWriteArrayList<BluetoothDevice> mSinksInAdding = new CopyOnWriteArrayList<>();
// The primary/active sinks in adding source process.
// To avoid users advance to share then pair flow before the primary/active sinks successfully
// join the audio sharing, we will wait for the process complete for this list of sinks and then
// popup audio sharing dialog with options to pair new device.
private CopyOnWriteArrayList<BluetoothDevice> mSinksToWaitFor = new CopyOnWriteArrayList<>();
private AtomicBoolean mStoppingSharing = new AtomicBoolean(false);
@VisibleForTesting
BroadcastReceiver mReceiver =
@@ -153,6 +161,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
public void onBroadcastStartFailed(int reason) {
Log.d(TAG, "onBroadcastStartFailed(), reason = " + reason);
updateSwitch();
showErrorDialog();
mMetricsFeatureProvider.action(
mContext,
SettingsEnums.ACTION_AUDIO_SHARING_START_FAILED,
@@ -178,7 +187,10 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
+ reason
+ ", broadcastId = "
+ broadcastId);
mStoppingSharing.compareAndSet(true, false);
updateSwitch();
AudioSharingUtils.postOnMainThread(mContext,
() -> dismissStaleDialogsOtherThanErrorDialog());
AudioSharingUtils.toastMessage(
mContext,
mContext.getString(R.string.audio_sharing_sharing_stopped_label));
@@ -219,7 +231,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
TAG,
"Skip handleOnBroadcastReady: null assistant or "
+ "sink has active local source.");
cleanUp();
cleanUpStatesForStartSharing();
return;
}
handleOnBroadcastReady();
@@ -264,17 +276,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
+ source
+ ", reason = "
+ reason);
mMetricsFeatureProvider.action(
mContext,
SettingsEnums.ACTION_AUDIO_SHARING_JOIN_FAILED,
SettingsEnums.AUDIO_SHARING_SETTINGS);
AudioSharingUtils.toastMessage(
mContext,
String.format(
Locale.US,
"Fail to add source to %s reason %d",
sink.getAddress(),
reason));
if (mSinksInAdding.contains(sink)) {
stopAudioSharing();
showErrorDialog();
mMetricsFeatureProvider.action(
mContext,
SettingsEnums.ACTION_AUDIO_SHARING_JOIN_FAILED,
SettingsEnums.AUDIO_SHARING_SETTINGS);
}
}
@Override
@@ -298,13 +307,33 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
@NonNull BluetoothDevice sink,
int sourceId,
@NonNull BluetoothLeBroadcastReceiveState state) {
if (mStoppingSharing.get()) {
Log.d(TAG, "Skip onReceiveStateChanged, stopping broadcast");
return;
}
if (BluetoothUtils.isConnected(state)) {
if (mSinksInAdding.contains(sink)) {
mSinksInAdding.remove(sink);
}
dismissLoadingStateDialogIfNeeded();
dismissProgressDialogIfNeeded();
Log.d(TAG, "onReceiveStateChanged() connected, sink = " + sink
+ ", remaining sinks = " + mSinksInAdding);
if (mSinksToWaitFor.contains(sink)) {
mSinksToWaitFor.remove(sink);
if (mSinksToWaitFor.isEmpty()) {
// To avoid users advance to share then pair flow before the
// primary/active sinks successfully join the audio sharing,
// popup dialog till adding source complete for mSinksToWaitFor.
Pair<Integer, Object>[] eventData =
AudioSharingUtils.buildAudioSharingDialogEventData(
SettingsEnums.AUDIO_SHARING_SETTINGS,
SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE,
/* userTriggered= */ false,
/* deviceCountInSharing= */ 1,
/* candidateDeviceCount= */ 0);
showAudioSharingDialog(eventData);
}
}
}
}
};
@@ -411,6 +440,8 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
return;
}
stopAudioSharing();
mMetricsFeatureProvider.action(
mContext, SettingsEnums.ACTION_AUDIO_SHARING_MAIN_SWITCH_OFF);
}
}
@@ -542,7 +573,7 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
mSinksInAdding.clear();
// TODO: use string res once finalized.
AudioSharingUtils.postOnMainThread(mContext,
() -> AudioSharingLoadingStateDialogFragment.show(mFragment,
() -> AudioSharingProgressDialogFragment.show(mFragment,
"Starting audio stream..."));
mMetricsFeatureProvider.action(
mContext,
@@ -553,9 +584,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
private void stopAudioSharing() {
if (mBroadcast != null) {
mBroadcast.stopBroadcast(mBroadcast.getLatestBroadcastId());
mMetricsFeatureProvider.action(
mContext, SettingsEnums.ACTION_AUDIO_SHARING_MAIN_SWITCH_OFF);
int broadcastId = mBroadcast.getLatestBroadcastId();
if (broadcastId != -1) {
mBroadcast.stopBroadcast(broadcastId);
mStoppingSharing.compareAndSet(false, true);
mSinksInAdding.clear();
mSinksToWaitFor.clear();
}
cleanUpStatesForStartSharing();
}
}
@@ -617,11 +653,22 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
/* userTriggered= */ false,
/* deviceCountInSharing= */ targetActiveSinks.isEmpty() ? 0 : 1,
/* candidateDeviceCount= */ mDeviceItemsForSharing.size());
// Auto add primary/active sinks w/o user interactions.
if (!targetActiveSinks.isEmpty() && mTargetActiveItem != null) {
Log.d(TAG, "handleOnBroadcastReady: automatically add source to active sinks.");
addSourceToTargetSinks(targetActiveSinks, mTargetActiveItem.getName());
// To avoid users advance to share then pair flow before the primary/active sinks
// successfully join the audio sharing, save the primary/active sinks in mSinksToWaitFor
// and popup dialog till adding source complete for these sinks.
if (mDeviceItemsForSharing.isEmpty()) {
mSinksToWaitFor.clear();
mSinksToWaitFor.addAll(targetActiveSinks);
}
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING);
mTargetActiveItem = null;
// When audio sharing page is brought up by intent with EXTRA_START_LE_AUDIO_SHARING
// == true, plus there is one active lea headset and one connected lea headset, we
// should auto add these sinks without user interactions.
if (mIntentHandleStage.compareAndSet(
StartIntentHandleStage.HANDLE_AUTO_ADD.ordinal(),
StartIntentHandleStage.HANDLED.ordinal())
@@ -631,31 +678,42 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
List<BluetoothDevice> targetSinks = mGroupedConnectedDevices.getOrDefault(
target.getGroupId(), ImmutableList.of());
addSourceToTargetSinks(targetSinks, target.getName());
cleanUp();
cleanUpStatesForStartSharing();
// TODO: Add metric for auto add by intent
return;
}
}
// Still mark intent as handled if early returned due to preconditions not met
mIntentHandleStage.compareAndSet(
StartIntentHandleStage.HANDLE_AUTO_ADD.ordinal(),
StartIntentHandleStage.HANDLED.ordinal());
if (mFragment == null) {
Log.d(TAG, "handleOnBroadcastReady: dialog fail to show due to null fragment.");
dismissLoadingStateDialogIfNeeded();
cleanUp();
// Clean up states before early return.
dismissProgressDialogIfNeeded();
cleanUpStatesForStartSharing();
return;
}
showDialog(eventData);
// To avoid users advance to share then pair flow before the primary/active sinks
// successfully join the audio sharing, popup dialog till adding source complete for
// mSinksToWaitFor.
if (mSinksToWaitFor.isEmpty() && !mStoppingSharing.get()) {
showAudioSharingDialog(eventData);
}
}
private void showDialog(Pair<Integer, Object>[] eventData) {
private void showAudioSharingDialog(Pair<Integer, Object>[] eventData) {
if (!BluetoothUtils.isBroadcasting(mBtManager)) {
Log.d(TAG, "Skip showAudioSharingDialog, broadcast is stopped");
return;
}
AudioSharingDialogFragment.DialogEventListener listener =
new AudioSharingDialogFragment.DialogEventListener() {
@Override
public void onPositiveClick() {
// Could go to other pages, dismiss the loading dialog.
dismissLoadingStateDialogIfNeeded();
cleanUp();
// Could go to other pages, dismiss the progress dialog.
dismissProgressDialogIfNeeded();
cleanUpStatesForStartSharing();
}
@Override
@@ -663,14 +721,14 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
List<BluetoothDevice> targetSinks = mGroupedConnectedDevices.getOrDefault(
item.getGroupId(), ImmutableList.of());
addSourceToTargetSinks(targetSinks, item.getName());
cleanUp();
cleanUpStatesForStartSharing();
}
@Override
public void onCancelClick() {
// Could go to other pages, dismiss the loading dialog.
dismissLoadingStateDialogIfNeeded();
cleanUp();
// Could go to other pages, dismiss the progress dialog.
dismissProgressDialogIfNeeded();
cleanUpStatesForStartSharing();
}
};
AudioSharingUtils.postOnMainThread(
@@ -684,6 +742,36 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
});
}
private void showErrorDialog() {
AudioSharingUtils.postOnMainThread(mContext,
() -> {
// Remove all stale dialogs before showing error dialog
dismissStaleDialogsOtherThanErrorDialog();
AudioSharingErrorDialogFragment.show(mFragment);
});
}
@UiThread
private void dismissStaleDialogsOtherThanErrorDialog() {
List<Fragment> fragments = new ArrayList<Fragment>();
try {
if (mFragment != null) {
fragments =
mFragment.getChildFragmentManager().getFragments();
}
} catch (Exception e) {
Log.e(TAG, "Fail to dismiss stale dialogs: " + e.getMessage());
}
for (Fragment fragment : fragments) {
if (fragment != null && fragment instanceof DialogFragment
&& !(fragment instanceof AudioSharingErrorDialogFragment)
&& ((DialogFragment) fragment).getDialog() != null) {
Log.d(TAG, "Remove stale dialog = " + fragment.getTag());
((DialogFragment) fragment).dismiss();
}
}
}
private static final class MainSwitchAccessibilityDelegate extends View.AccessibilityDelegate {
@Override
public boolean onRequestSendAccessibilityEvent(
@@ -742,25 +830,25 @@ public class AudioSharingSwitchBarController extends BasePreferenceController
private void addSourceToTargetSinks(List<BluetoothDevice> targetActiveSinks,
@NonNull String sinkName) {
mSinksInAdding.addAll(targetActiveSinks);
AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager);
// TODO: move to res once finalized
String loadingMessage = "Sharing with " + sinkName + "...";
showLoadingStateDialog(loadingMessage);
String progressMessage = "Sharing with " + sinkName + "...";
showProgressDialog(progressMessage);
AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager);
}
private void showLoadingStateDialog(@NonNull String loadingMessage) {
private void showProgressDialog(@NonNull String progressMessage) {
AudioSharingUtils.postOnMainThread(mContext,
() -> AudioSharingLoadingStateDialogFragment.show(mFragment, loadingMessage));
() -> AudioSharingProgressDialogFragment.show(mFragment, progressMessage));
}
private void dismissLoadingStateDialogIfNeeded() {
private void dismissProgressDialogIfNeeded() {
if (mSinksInAdding.isEmpty()) {
AudioSharingUtils.postOnMainThread(mContext,
() -> AudioSharingLoadingStateDialogFragment.dismiss(mFragment));
() -> AudioSharingProgressDialogFragment.dismiss(mFragment));
}
}
private void cleanUp() {
private void cleanUpStatesForStartSharing() {
mGroupedConnectedDevices.clear();
mDeviceItemsForSharing.clear();
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2024 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.deviceinfo.firmwareversion
import android.content.Context
import android.os.SystemProperties
import androidx.preference.Preference
import com.android.settings.R
import com.android.settings.Utils
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceSummaryProvider
import com.android.settingslib.preference.PreferenceBinding
// LINT.IfChange
class BasebandVersionPreference :
PreferenceMetadata,
PreferenceSummaryProvider,
PreferenceAvailabilityProvider,
PreferenceBinding {
override val key: String
get() = "base_band"
override val title: Int
get() = R.string.baseband_version
override fun getSummary(context: Context): CharSequence? =
SystemProperties.get(BASEBAND_PROPERTY, context.getString(R.string.device_info_default))
override fun isAvailable(context: Context) = !Utils.isWifiOnly(context)
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
preference.isSelectable = false
preference.isCopyingEnabled = true
}
companion object {
const val BASEBAND_PROPERTY: String = "gsm.version.baseband"
}
}
// LINT.ThenChange(BasebandVersionPreferenceController.java)

View File

@@ -25,6 +25,7 @@ import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
// LINT.IfChange
public class BasebandVersionPreferenceController extends BasePreferenceController {
@VisibleForTesting
@@ -45,3 +46,4 @@ public class BasebandVersionPreferenceController extends BasePreferenceControlle
mContext.getString(R.string.device_info_default));
}
}
// LINT.ThenChange(BasebandVersionPreference.kt)

View File

@@ -50,9 +50,9 @@ class FirmwareVersionScreen : PreferenceScreenCreator, PreferenceSummaryProvider
+PreferenceWidget("os_firmware_version", R.string.firmware_version)
+PreferenceWidget("security_key", R.string.security_patch)
+PreferenceWidget("module_version", R.string.module_version)
+PreferenceWidget("base_band", R.string.baseband_version)
+PreferenceWidget("kernel_version", R.string.kernel_version)
+PreferenceWidget("os_build_number", R.string.build_number)
+BasebandVersionPreference()
+KernelVersionPreference()
+SimpleBuildNumberPreference()
}
private class PreferenceWidget(override val key: String, override val title: Int) :

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2024 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.deviceinfo.firmwareversion
import android.content.Context
import androidx.preference.Preference
import com.android.settings.R
import com.android.settingslib.DeviceInfoUtils
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceSummaryProvider
import com.android.settingslib.preference.PreferenceBinding
// LINT.IfChange
class KernelVersionPreference : PreferenceMetadata, PreferenceSummaryProvider, PreferenceBinding {
override val key: String
get() = "kernel_version"
override val title: Int
get() = R.string.kernel_version
override fun getSummary(context: Context): CharSequence? =
DeviceInfoUtils.getFormattedKernelVersion(context)
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
preference.isSelectable = false
preference.isCopyingEnabled = true
}
}
// LINT.ThenChange(KernelVersionPreferenceController.java)

View File

@@ -21,6 +21,7 @@ import android.content.Context;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.DeviceInfoUtils;
// LINT.IfChange
public class KernelVersionPreferenceController extends BasePreferenceController {
public KernelVersionPreferenceController(Context context, String preferenceKey) {
@@ -37,3 +38,4 @@ public class KernelVersionPreferenceController extends BasePreferenceController
return DeviceInfoUtils.getFormattedKernelVersion(mContext);
}
}
// LINT.ThenChange(KernelVersionPreference.kt)

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2024 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.deviceinfo.firmwareversion
import android.content.Context
import android.os.Build
import android.text.BidiFormatter
import android.view.View.LAYOUT_DIRECTION_RTL
import androidx.preference.Preference
import com.android.settings.R
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceSummaryProvider
import com.android.settingslib.preference.PreferenceBinding
// LINT.IfChange
class SimpleBuildNumberPreference :
PreferenceMetadata, PreferenceSummaryProvider, PreferenceBinding {
override val key: String
get() = "os_build_number"
override val title: Int
get() = R.string.build_number
override fun isIndexable(context: Context) = false
override fun getSummary(context: Context): CharSequence? {
val isRtl = context.resources.configuration.layoutDirection == LAYOUT_DIRECTION_RTL
return BidiFormatter.getInstance(isRtl).unicodeWrap(Build.DISPLAY)
}
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
preference.isSelectable = false
preference.isCopyingEnabled = true
}
}
// LINT.ThenChange(SimpleBuildNumberPreferenceController.java)

View File

@@ -22,6 +22,7 @@ import android.text.BidiFormatter;
import com.android.settings.core.BasePreferenceController;
// LINT.IfChange
public class SimpleBuildNumberPreferenceController extends BasePreferenceController {
public SimpleBuildNumberPreferenceController(Context context,
@@ -39,3 +40,4 @@ public class SimpleBuildNumberPreferenceController extends BasePreferenceControl
return BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY);
}
}
// LINT.ThenChange(SimpleBuildNumberPreference.kt)

View File

@@ -20,7 +20,6 @@ import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
@@ -80,10 +79,7 @@ public class OnDeviceRecognitionPreferenceController extends BasePreferenceContr
}
private void show(Preference preference) {
final List<UserHandle> userHandles = new ArrayList<>();
for (UserInfo userInfo : UserManager.get(mContext).getUsers()) {
userHandles.add(userInfo.getUserHandle());
}
final List<UserHandle> userHandles = UserManager.get(mContext).getEnabledProfiles();
// Only a single profile is installed. Proceed with its settings.
if (userHandles.size() == 1) {

View File

@@ -89,7 +89,7 @@ class MobileNetworkListFragment : DashboardFragment() {
private val simRepositoryFactory: (Context) -> SimRepository = ::SimRepository
) : BaseSearchIndexProvider(R.xml.network_provider_sims_list) {
public override fun isPageSearchEnabled(context: Context): Boolean =
simRepositoryFactory(context).showMobileNetworkPage()
simRepositoryFactory(context).canEnterMobileNetworkPage()
}
}
}

View File

@@ -57,7 +57,7 @@ constructor(
private var isAirplaneModeOn = false
override fun getAvailabilityStatus() =
if (SimRepository(mContext).showMobileNetworkPage()) AVAILABLE
if (SimRepository(mContext).showMobileNetworkPageEntrance()) AVAILABLE
else CONDITIONALLY_UNAVAILABLE
override fun displayPreference(screen: PreferenceScreen) {

View File

@@ -53,8 +53,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.lifecycle.LifecycleRegistry
import com.android.settings.R
import com.android.settings.SidecarFragment
import com.android.settings.network.telephony.SimRepository
import com.android.settings.network.telephony.SubscriptionActionDialogActivity
import com.android.settings.network.telephony.SubscriptionRepository
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity
import com.android.settings.network.telephony.requireSubscriptionManager
import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
@@ -578,6 +578,10 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
subId: Int,
isNewTask: Boolean = false,
) {
if (!SimRepository(context).canEnterMobileNetworkPage()) {
Log.i(TAG, "Unable to start SimOnboardingActivity due to missing permissions")
return
}
val intent = Intent(context, SimOnboardingActivity::class.java).apply {
putExtra(SUB_ID, subId)
if(isNewTask) {

View File

@@ -48,7 +48,7 @@ constructor(
override fun getSummary(): CharSequence {
val summaryResId =
if (simRepository.showMobileNetworkPage()) {
if (simRepository.showMobileNetworkPageEntrance()) {
R.string.network_dashboard_summary_mobile
} else {
R.string.network_dashboard_summary_no_mobile

View File

@@ -21,7 +21,6 @@ import android.provider.Settings
import android.telephony.SubscriptionInfo
import com.android.settings.R
import com.android.settings.datausage.BillingCyclePreferenceController.Companion.BillingCycleSearchItem
import com.android.settings.network.SubscriptionUtil
import com.android.settings.network.telephony.CarrierSettingsVersionPreferenceController.Companion.CarrierSettingsVersionSearchItem
import com.android.settings.network.telephony.DataUsagePreferenceController.Companion.DataUsageSearchItem
import com.android.settings.network.telephony.MmsMessagePreferenceController.Companion.MmsMessageSearchItem
@@ -36,7 +35,6 @@ import com.android.settings.spa.search.SpaSearchRepository.Companion.createSearc
import com.android.settings.spa.search.SpaSearchRepository.Companion.searchIndexProviderOf
import com.android.settingslib.search.SearchIndexableData
import com.android.settingslib.search.SearchIndexableRaw
import com.android.settingslib.spaprivileged.framework.common.userManager
import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBoolean
class MobileNetworkSettingsSearchIndex(
@@ -109,12 +107,8 @@ class MobileNetworkSettingsSearchIndex(
companion object {
/** suppress full page if user is not admin */
@JvmStatic
fun isMobileNetworkSettingsSearchable(context: Context): Boolean {
val isAirplaneMode by context.settingsGlobalBoolean(Settings.Global.AIRPLANE_MODE_ON)
return SubscriptionUtil.isSimHardwareVisible(context) &&
!isAirplaneMode &&
context.userManager.isAdminUser
}
fun isMobileNetworkSettingsSearchable(context: Context): Boolean =
SimRepository(context).canEnterMobileNetworkPage()
fun createSearchItems(context: Context): List<MobileNetworkSettingsSearchItem> =
listOf(

View File

@@ -18,13 +18,24 @@ package com.android.settings.network.telephony
import android.content.Context
import android.content.pm.PackageManager
import android.os.UserManager
import android.provider.Settings
import com.android.settingslib.spaprivileged.framework.common.userManager
import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBoolean
class SimRepository(context: Context) {
class SimRepository(private val context: Context) {
private val packageManager = context.packageManager
private val userManager = context.userManager
/** Gets whether we show mobile network settings page to the current user. */
fun showMobileNetworkPage(): Boolean =
/** Gets whether show mobile network settings page entrance to the current user. */
fun showMobileNetworkPageEntrance(): Boolean =
packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) && userManager.isAdminUser
/** Gets whether current user can enter mobile network settings page. */
fun canEnterMobileNetworkPage(): Boolean {
val isAirplaneMode by context.settingsGlobalBoolean(Settings.Global.AIRPLANE_MODE_ON)
return showMobileNetworkPageEntrance() &&
!isAirplaneMode &&
!userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)
}
}

View File

@@ -24,9 +24,8 @@ import android.media.RingtoneManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import com.android.settings.R;
import com.android.settings.RingtonePreference;
public class NotificationSoundPreference extends RingtonePreference {
@@ -49,6 +48,20 @@ public class NotificationSoundPreference extends RingtonePreference {
updateRingtoneName(mRingtone);
}
protected String generateRingtoneTitle(Uri uri) {
if (uri == null) {
return getContext().getString(com.android.internal.R.string.ringtone_silent);
} else if (RingtoneManager.isDefault(uri)) {
return getContext().getString(com.android.settings.R.string.notification_sound_default);
} else if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) {
return getContext().getString(
com.android.settings.R.string.notification_unknown_sound_title);
} else {
return Ringtone.getTitle(getContext(), uri, false /* followSettingsUri */,
true /* allowRemote */);
}
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
@@ -69,16 +82,7 @@ public class NotificationSoundPreference extends RingtonePreference {
AsyncTask ringtoneNameTask = new AsyncTask<Object, Void, CharSequence>() {
@Override
protected CharSequence doInBackground(Object... params) {
if (uri == null) {
return getContext().getString(com.android.internal.R.string.ringtone_silent);
} else if (RingtoneManager.isDefault(uri)) {
return getContext().getString(R.string.notification_sound_default);
} else if(ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) {
return getContext().getString(R.string.notification_unknown_sound_title);
} else {
return Ringtone.getTitle(getContext(), uri, false /* followSettingsUri */,
true /* allowRemote */);
}
return generateRingtoneTitle(uri);
}
@Override

View File

@@ -458,7 +458,7 @@ public class ZenModeBackend {
}
private static List<String> getDefaultRuleIds() {
return ZenModeConfig.DEFAULT_RULE_IDS;
return ZenModeConfig.getDefaultRuleIds();
}
NotificationManager.Policy toNotificationPolicy(ZenPolicy policy) {

View File

@@ -206,7 +206,12 @@ public class SimSlotChangeHandler {
if (hasActiveEsimSubscription()) {
if (mTelMgr.isMultiSimSupported() == TelephonyManager.MULTISIM_ALLOWED) {
Log.i(TAG, "Enabled profile exists. DSDS condition satisfied.");
startDsdsDialogActivity();
if (Flags.isDualSimOnboardingEnabled()) {
// enable dsds by sim onboarding flow
handleRemovableSimInsertWhenDsds(removableSlotInfo);
} else {
startDsdsDialogActivity();
}
} else {
Log.i(TAG, "Enabled profile exists. DSDS condition not satisfied.");
startChooseSimActivity(true);

View File

@@ -212,7 +212,7 @@ open class NetworkCellularGroupProvider : SettingsPageProvider, SearchablePage {
const val fileName = "NetworkCellularGroupProvider"
private fun isPageSearchable(context: Context) =
Flags.isDualSimOnboardingEnabled() && SimRepository(context).showMobileNetworkPage()
Flags.isDualSimOnboardingEnabled() && SimRepository(context).canEnterMobileNetworkPage()
}
}

View File

@@ -21,6 +21,8 @@ import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
@@ -35,6 +37,10 @@ public class TickButtonPreference extends TwoTargetPreference {
super(context);
}
public TickButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);

View File

@@ -69,6 +69,9 @@ android_robolectric_test {
"com_android_server_accessibility_flags_lib",
"flag-junit",
"flag-junit-base",
"kotlin-test",
"mockito-robolectric-prebuilt", // mockito deps order matters!
"mockito-kotlin2",
"notification_flags_lib",
"platform-test-annotations",
"testables",

View File

@@ -51,14 +51,14 @@ import org.robolectric.shadows.androidx.fragment.FragmentController;
ShadowAlertDialogCompat.class,
ShadowBluetoothAdapter.class,
})
public class AudioSharingRetryDialogFragmentTest {
public class AudioSharingErrorDialogFragmentTest {
@Rule
public final MockitoRule mocks = MockitoJUnit.rule();
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private Fragment mParent;
private AudioSharingRetryDialogFragment mFragment;
private AudioSharingErrorDialogFragment mFragment;
@Before
public void setUp() {
@@ -70,7 +70,7 @@ public class AudioSharingRetryDialogFragmentTest {
BluetoothStatusCodes.FEATURE_SUPPORTED);
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
mFragment = new AudioSharingRetryDialogFragment();
mFragment = new AudioSharingErrorDialogFragment();
mParent = new Fragment();
FragmentController.setupFragment(
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
@@ -91,7 +91,7 @@ public class AudioSharingRetryDialogFragmentTest {
@Test
public void onCreateDialog_flagOff_dialogNotExist() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingRetryDialogFragment.show(mParent);
AudioSharingErrorDialogFragment.show(mParent);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNull();
@@ -100,7 +100,7 @@ public class AudioSharingRetryDialogFragmentTest {
@Test
public void onCreateDialog_unattachedFragment_dialogNotExist() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingRetryDialogFragment.show(new Fragment());
AudioSharingErrorDialogFragment.show(new Fragment());
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNull();
@@ -109,7 +109,7 @@ public class AudioSharingRetryDialogFragmentTest {
@Test
public void onCreateDialog_flagOn_showDialog() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingRetryDialogFragment.show(mParent);
AudioSharingErrorDialogFragment.show(mParent);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();
@@ -119,7 +119,7 @@ public class AudioSharingRetryDialogFragmentTest {
@Test
public void onCreateDialog_clickOk_dialogDismiss() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingRetryDialogFragment.show(mParent);
AudioSharingErrorDialogFragment.show(mParent);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();

View File

@@ -52,7 +52,7 @@ import org.robolectric.shadows.androidx.fragment.FragmentController;
ShadowAlertDialogCompat.class,
ShadowBluetoothAdapter.class,
})
public class AudioSharingLoadingStateDialogFragmentTest {
public class AudioSharingProgressDialogFragmentTest {
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -60,7 +60,7 @@ public class AudioSharingLoadingStateDialogFragmentTest {
private static final String TEST_MESSAGE2 = "message2";
private Fragment mParent;
private AudioSharingLoadingStateDialogFragment mFragment;
private AudioSharingProgressDialogFragment mFragment;
@Before
public void setUp() {
@@ -72,7 +72,7 @@ public class AudioSharingLoadingStateDialogFragmentTest {
BluetoothStatusCodes.FEATURE_SUPPORTED);
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
mFragment = new AudioSharingLoadingStateDialogFragment();
mFragment = new AudioSharingProgressDialogFragment();
mParent = new Fragment();
FragmentController.setupFragment(
mParent, FragmentActivity.class, /* containerViewId= */ 0, /* bundle= */ null);
@@ -93,7 +93,7 @@ public class AudioSharingLoadingStateDialogFragmentTest {
@Test
public void onCreateDialog_flagOff_dialogNotExist() {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1);
AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNull();
@@ -102,7 +102,7 @@ public class AudioSharingLoadingStateDialogFragmentTest {
@Test
public void onCreateDialog_unattachedFragment_dialogNotExist() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingLoadingStateDialogFragment.show(new Fragment(), TEST_MESSAGE1);
AudioSharingProgressDialogFragment.show(new Fragment(), TEST_MESSAGE1);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNull();
@@ -111,7 +111,7 @@ public class AudioSharingLoadingStateDialogFragmentTest {
@Test
public void onCreateDialog_flagOn_showDialog() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1);
AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();
@@ -124,13 +124,13 @@ public class AudioSharingLoadingStateDialogFragmentTest {
@Test
public void dismissDialog_succeed() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1);
AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();
assertThat(dialog.isShowing()).isTrue();
AudioSharingLoadingStateDialogFragment.dismiss(mParent);
AudioSharingProgressDialogFragment.dismiss(mParent);
shadowMainLooper().idle();
assertThat(dialog.isShowing()).isFalse();
}
@@ -138,13 +138,13 @@ public class AudioSharingLoadingStateDialogFragmentTest {
@Test
public void showDialog_sameMessage_keepExistingDialog() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1);
AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();
assertThat(dialog.isShowing()).isTrue();
AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1);
AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1);
shadowMainLooper().idle();
assertThat(dialog.isShowing()).isTrue();
}
@@ -152,7 +152,7 @@ public class AudioSharingLoadingStateDialogFragmentTest {
@Test
public void showDialog_newMessage_keepAndUpdateDialog() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE1);
AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE1);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();
@@ -161,7 +161,7 @@ public class AudioSharingLoadingStateDialogFragmentTest {
assertThat(view).isNotNull();
assertThat(view.getText().toString()).isEqualTo(TEST_MESSAGE1);
AudioSharingLoadingStateDialogFragment.show(mParent, TEST_MESSAGE2);
AudioSharingProgressDialogFragment.show(mParent, TEST_MESSAGE2);
shadowMainLooper().idle();
assertThat(dialog.isShowing()).isTrue();
assertThat(view.getText().toString()).isEqualTo(TEST_MESSAGE2);

View File

@@ -146,6 +146,7 @@ public class AudioSharingSwitchBarControllerTest {
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
@Mock private VolumeControlProfile mVolumeControl;
@Mock private BluetoothLeBroadcastMetadata mMetadata;
@Mock private BluetoothLeBroadcastReceiveState mState;
@Mock private CompoundButton mBtnView;
@Mock private CachedBluetoothDevice mCachedDevice1;
@Mock private CachedBluetoothDevice mCachedDevice2;
@@ -499,7 +500,7 @@ public class AudioSharingSwitchBarControllerTest {
verify(mBroadcast).startPrivateBroadcast();
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
// No loading state dialog.
// No progress dialog.
assertThat(childFragments).isEmpty();
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
@@ -519,10 +520,9 @@ public class AudioSharingSwitchBarControllerTest {
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class);
when(state.getBroadcastId()).thenReturn(1);
when(mState.getBroadcastId()).thenReturn(1);
when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
when(mAssistant.getAllSources(mDevice2)).thenReturn(ImmutableList.of(state));
when(mAssistant.getAllSources(mDevice2)).thenReturn(ImmutableList.of(mState));
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
@@ -531,7 +531,7 @@ public class AudioSharingSwitchBarControllerTest {
verify(mBroadcast).startPrivateBroadcast();
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingLoadingStateDialogFragment.class.getName());
AudioSharingProgressDialogFragment.class.getName());
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
@@ -549,27 +549,92 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void onPlaybackStarted_showJoinAudioSharingDialog() {
public void onPlaybackStarted_singleActiveDevice_showJoinAudioSharingDialog() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2));
when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of());
doNothing().when(mBroadcast).startPrivateBroadcast();
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
shadowOf(Looper.getMainLooper()).idle();
verify(mBroadcast).startPrivateBroadcast();
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingLoadingStateDialogFragment.class.getName());
AudioSharingLoadingStateDialogFragment loadingFragment =
(AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments);
AudioSharingProgressDialogFragment.class.getName());
when(mBroadcast.isEnabled(null)).thenReturn(true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
verify(mFeatureFactory.metricsFeatureProvider)
.action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING));
when(mState.getBisSyncState()).thenReturn(ImmutableList.of(1L));
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice2, /* sourceId= */ 1,
mState);
shadowOf(Looper.getMainLooper()).idle();
childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments)
.comparingElementsUsing(CLAZZNAME_EQUALS)
.containsExactly(AudioSharingDialogFragment.class.getName());
Pair<Integer, Object>[] eventData = new Pair[0];
for (Fragment fragment : childFragments) {
if (fragment instanceof AudioSharingDialogFragment) {
eventData = ((AudioSharingDialogFragment) fragment).getEventData();
break;
}
}
assertThat(eventData)
.asList()
.containsExactly(
Pair.create(
AudioSharingUtils.MetricKey.METRIC_KEY_SOURCE_PAGE_ID.ordinal(),
SettingsEnums.AUDIO_SHARING_SETTINGS),
Pair.create(
AudioSharingUtils.MetricKey.METRIC_KEY_PAGE_ID.ordinal(),
SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE),
Pair.create(
AudioSharingUtils.MetricKey.METRIC_KEY_USER_TRIGGERED.ordinal(), 0),
Pair.create(
AudioSharingUtils.MetricKey.METRIC_KEY_DEVICE_COUNT_IN_SHARING
.ordinal(),
1),
Pair.create(
AudioSharingUtils.MetricKey.METRIC_KEY_CANDIDATE_DEVICE_COUNT
.ordinal(),
0));
childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@Test
public void onPlaybackStarted_oneActiveOnConnected_showJoinAudioSharingDialog() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of());
doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
shadowOf(Looper.getMainLooper()).idle();
verify(mBroadcast).startPrivateBroadcast();
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingProgressDialogFragment.class.getName());
AudioSharingProgressDialogFragment progressFragment =
(AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments);
// TODO: use string res once finalized
String expectedMessage = "Starting audio stream...";
checkLoadingStateDialogMessage(loadingFragment, expectedMessage);
checkProgressDialogMessage(progressFragment, expectedMessage);
when(mBroadcast.isEnabled(null)).thenReturn(true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
@@ -577,13 +642,13 @@ public class AudioSharingSwitchBarControllerTest {
.action(any(Context.class), eq(SettingsEnums.ACTION_AUTO_JOIN_AUDIO_SHARING));
// TODO: use string res once finalized
expectedMessage = "Sharing with " + TEST_DEVICE_NAME2 + "...";
checkLoadingStateDialogMessage(loadingFragment, expectedMessage);
checkProgressDialogMessage(progressFragment, expectedMessage);
childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments)
.comparingElementsUsing(CLAZZNAME_EQUALS)
.containsExactly(AudioSharingDialogFragment.class.getName(),
AudioSharingLoadingStateDialogFragment.class.getName());
AudioSharingProgressDialogFragment.class.getName());
Pair<Integer, Object>[] eventData = new Pair[0];
for (Fragment fragment : childFragments) {
@@ -616,18 +681,19 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void onPlaybackStarted_clickShareBtnOnDialog_addSource() {
public void onPlaybackStarted_oneActiveOnConnected_clickShareBtnOnDialog_addSource() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of());
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
shadowOf(Looper.getMainLooper()).idle();
verify(mBroadcast).startPrivateBroadcast();
when(mBroadcast.isEnabled(null)).thenReturn(true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
@@ -642,32 +708,33 @@ public class AudioSharingSwitchBarControllerTest {
verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
assertThat(dialog.isShowing()).isFalse();
// Loading state dialog shows sharing state for the user chosen sink.
// Progress dialog shows sharing progress for the user chosen sink.
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingLoadingStateDialogFragment.class.getName());
AudioSharingLoadingStateDialogFragment loadingFragment =
(AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments);
AudioSharingProgressDialogFragment.class.getName());
AudioSharingProgressDialogFragment progressFragment =
(AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments);
// TODO: use string res once finalized
String expectedMessage = "Sharing with " + TEST_DEVICE_NAME1 + "...";
checkLoadingStateDialogMessage(loadingFragment, expectedMessage);
checkProgressDialogMessage(progressFragment, expectedMessage);
childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@Test
public void onPlaybackStarted_clickCancelBtnOnDialog_doNothing() {
public void onPlaybackStarted_oneActiveOnConnected_clickCancelBtnOnDialog_doNothing() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of());
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
shadowOf(Looper.getMainLooper()).idle();
verify(mBroadcast).startPrivateBroadcast();
when(mBroadcast.isEnabled(null)).thenReturn(true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
@@ -682,15 +749,15 @@ public class AudioSharingSwitchBarControllerTest {
verify(mAssistant, never()).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
assertThat(dialog.isShowing()).isFalse();
// Loading state dialog shows sharing state for the auto add active sink.
// Progress dialog shows sharing progress for the auto add active sink.
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingLoadingStateDialogFragment.class.getName());
AudioSharingLoadingStateDialogFragment loadingFragment =
(AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments);
AudioSharingProgressDialogFragment.class.getName());
AudioSharingProgressDialogFragment progressFragment =
(AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments);
// TODO: use string res once finalized
String expectedMessage = "Sharing with " + TEST_DEVICE_NAME2 + "...";
checkLoadingStateDialogMessage(loadingFragment, expectedMessage);
checkProgressDialogMessage(progressFragment, expectedMessage);
childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@@ -754,28 +821,63 @@ public class AudioSharingSwitchBarControllerTest {
}
@Test
public void testAssistantCallbacks_onSourceAddFailed_logAction() {
public void testAssistantCallbacks_onSourceAddFailed_twoDevices_showErrorAndLogAction() {
FeatureFlagUtils.setEnabled(
mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
when(mBtnView.isEnabled()).thenReturn(true);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice2, mDevice1));
when(mAssistant.getAllSources(any(BluetoothDevice.class))).thenReturn(ImmutableList.of());
doNothing().when(mBroadcast).startPrivateBroadcast();
mController.onCheckedChanged(mBtnView, /* isChecked= */ true);
shadowOf(Looper.getMainLooper()).idle();
verify(mBroadcast).startPrivateBroadcast();
when(mBroadcast.isEnabled(null)).thenReturn(true);
when(mBroadcast.getLatestBluetoothLeBroadcastMetadata()).thenReturn(mMetadata);
mController.mBroadcastCallback.onPlaybackStarted(0, 0);
shadowOf(Looper.getMainLooper()).idle();
verify(mAssistant).addSource(mDevice2, mMetadata, /* isGroupOp= */ false);
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();
View btnView = dialog.findViewById(R.id.positive_btn);
assertThat(btnView).isNotNull();
btnView.performClick();
shadowMainLooper().idle();
verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
assertThat(dialog.isShowing()).isFalse();
mController.mBroadcastAssistantCallback.onSourceAddFailed(
mDevice1, mMetadata, /* reason= */ 1);
shadowMainLooper().idle();
// Progress dialog shows sharing progress for the user chosen sink.
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingErrorDialogFragment.class.getName());
verify(mFeatureFactory.metricsFeatureProvider)
.action(
mContext,
SettingsEnums.ACTION_AUDIO_SHARING_JOIN_FAILED,
SettingsEnums.AUDIO_SHARING_SETTINGS);
childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@Test
public void testAssistantCallbacks_onReceiveStateChanged_dismissLoadingDialog() {
AudioSharingLoadingStateDialogFragment.show(mParentFragment, TEST_DEVICE_NAME1);
public void testAssistantCallbacks_onReceiveStateChanged_dismissProgressDialog() {
AudioSharingProgressDialogFragment.show(mParentFragment, TEST_DEVICE_NAME1);
shadowOf(Looper.getMainLooper()).idle();
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingLoadingStateDialogFragment.class.getName());
AudioSharingProgressDialogFragment.class.getName());
BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class);
when(state.getBisSyncState()).thenReturn(ImmutableList.of(1L));
when(mState.getBisSyncState()).thenReturn(ImmutableList.of(1L));
mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1,
state);
mState);
shadowOf(Looper.getMainLooper()).idle();
childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).isEmpty();
@@ -783,11 +885,9 @@ public class AudioSharingSwitchBarControllerTest {
@Test
public void testAssistantCallbacks_doNothing() {
BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class);
// Do nothing
mController.mBroadcastAssistantCallback.onReceiveStateChanged(
mDevice1, /* sourceId= */ 1, state);
mDevice1, /* sourceId= */ 1, mState);
mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1);
mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1);
@@ -923,13 +1023,13 @@ public class AudioSharingSwitchBarControllerTest {
List<Fragment> childFragments = parentFragment.getChildFragmentManager().getFragments();
// Skip audio sharing dialog.
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingLoadingStateDialogFragment.class.getName());
// The loading state dialog shows sharing state for the auto add second sink.
AudioSharingLoadingStateDialogFragment loadingFragment =
(AudioSharingLoadingStateDialogFragment) Iterables.getOnlyElement(childFragments);
AudioSharingProgressDialogFragment.class.getName());
// Progress dialog shows sharing progress for the auto add second sink.
AudioSharingProgressDialogFragment progressFragment =
(AudioSharingProgressDialogFragment) Iterables.getOnlyElement(childFragments);
// TODO: use string res once finalized
String expectedMessage = "Sharing with " + TEST_DEVICE_NAME1 + "...";
checkLoadingStateDialogMessage(loadingFragment, expectedMessage);
checkProgressDialogMessage(progressFragment, expectedMessage);
childFragments.forEach(fragment -> ((DialogFragment) fragment).dismiss());
}
@@ -944,7 +1044,7 @@ public class AudioSharingSwitchBarControllerTest {
verify(mAssistant).addSource(mDevice1, mMetadata, /* isGroupOp= */ false);
List<Fragment> childFragments = mParentFragment.getChildFragmentManager().getFragments();
assertThat(childFragments).comparingElementsUsing(CLAZZNAME_EQUALS).containsExactly(
AudioSharingLoadingStateDialogFragment.class.getName());
AudioSharingProgressDialogFragment.class.getName());
}
private Fragment setUpFragmentWithStartSharingIntent() {
@@ -964,12 +1064,12 @@ public class AudioSharingSwitchBarControllerTest {
return fragment;
}
private void checkLoadingStateDialogMessage(
@NonNull AudioSharingLoadingStateDialogFragment fragment,
private void checkProgressDialogMessage(
@NonNull AudioSharingProgressDialogFragment fragment,
@NonNull String expectedMessage) {
TextView loadingMessage = fragment.getDialog() == null ? null
TextView progressMessage = fragment.getDialog() == null ? null
: fragment.getDialog().findViewById(R.id.message);
assertThat(loadingMessage).isNotNull();
assertThat(loadingMessage.getText().toString()).isEqualTo(expectedMessage);
assertThat(progressMessage).isNotNull();
assertThat(progressMessage.getText().toString()).isEqualTo(expectedMessage);
}
}

View File

@@ -38,6 +38,7 @@ import org.robolectric.RuntimeEnvironment;
import java.util.Arrays;
// LINT.IfChange
@RunWith(RobolectricTestRunner.class)
public class BasebandVersionPreferenceControllerTest {
@Mock
@@ -68,3 +69,4 @@ public class BasebandVersionPreferenceControllerTest {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
}
// LINT.ThenChange(BasebandVersionPreferenceTest.kt)

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2024 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.deviceinfo.firmwareversion
import android.content.Context
import android.content.ContextWrapper
import android.sysprop.TelephonyProperties
import android.telephony.TelephonyManager
import androidx.test.core.app.ApplicationProvider
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.robolectric.RobolectricTestRunner
// LINT.IfChange
@RunWith(RobolectricTestRunner::class)
class BasebandVersionPreferenceTest {
private lateinit var telephonyManager: TelephonyManager
private val context: Context =
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
override fun getSystemService(name: String): Any? =
when {
name == getSystemServiceName(TelephonyManager::class.java) -> telephonyManager
else -> super.getSystemService(name)
}
}
private val basebandVersionPreference = BasebandVersionPreference()
@Test
fun isAvailable_wifiOnly_unavailable() {
telephonyManager = mock { on { isDataCapable } doReturn false }
assertThat(basebandVersionPreference.isAvailable(context)).isFalse()
}
@Test
fun isAvailable_hasMobile_available() {
TelephonyProperties.baseband_version(listOf("test"))
telephonyManager = mock { on { isDataCapable } doReturn true }
assertThat(basebandVersionPreference.isAvailable(context)).isTrue()
}
}
// LINT.ThenChange(BasebandVersionPreferenceControllerTest.java)

View File

@@ -29,6 +29,7 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
// LINT.IfChange
@RunWith(RobolectricTestRunner.class)
public class KernelVersionPreferenceControllerTest {
@@ -49,3 +50,4 @@ public class KernelVersionPreferenceControllerTest {
DeviceInfoUtils.getFormattedKernelVersion(mContext));
}
}
// LINT.ThenChange(KernelVersionPreferenceTest.kt)

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2024 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.deviceinfo.firmwareversion
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.android.settingslib.DeviceInfoUtils
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
// LINT.IfChange
@RunWith(RobolectricTestRunner::class)
class KernelVersionPreferenceTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val kernelVersionPreference = KernelVersionPreference()
@Test
fun getSummary() {
assertThat(kernelVersionPreference.getSummary(context))
.isEqualTo(DeviceInfoUtils.getFormattedKernelVersion(context))
}
}
// LINT.ThenChange(KernelVersionPreferenceControllerTest.java)

View File

@@ -29,6 +29,7 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
// LINT.IfChange
@RunWith(RobolectricTestRunner.class)
public class SimpleBuildNumberPreferenceControllerTest {
@@ -48,3 +49,4 @@ public class SimpleBuildNumberPreferenceControllerTest {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
}
// LINT.ThenChange(SimpleBuildNumberPreferenceTest.kt)

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2024 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.deviceinfo.firmwareversion
import android.content.Context
import android.os.Build
import android.text.BidiFormatter
import androidx.test.core.app.ApplicationProvider
import com.google.common.truth.Truth.assertThat
import java.util.Locale
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
// LINT.IfChange
@RunWith(RobolectricTestRunner::class)
class SimpleBuildNumberPreferenceTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val simpleBuildNumberPreference = SimpleBuildNumberPreference()
@Test
fun isIndexable() {
assertThat(simpleBuildNumberPreference.isIndexable(context)).isFalse()
}
@Test
fun getSummary_ltr() {
context.resources.configuration.setLayoutDirection(Locale.ENGLISH)
assertThat(simpleBuildNumberPreference.getSummary(context))
.isEqualTo(BidiFormatter.getInstance(false).unicodeWrap(Build.DISPLAY))
}
@Test
fun getSummary_rtl() {
context.resources.configuration.setLayoutDirection(Locale("ar"))
assertThat(simpleBuildNumberPreference.getSummary(context))
.isEqualTo(BidiFormatter.getInstance(true).unicodeWrap(Build.DISPLAY))
}
}
// LINT.ThenChange(SimpleBuildNumberPreferenceControllerTest.java)

View File

@@ -23,14 +23,18 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.AutomaticZenRule;
import android.app.Flags;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.database.Cursor;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -53,12 +57,15 @@ public class ZenModeBackendTest {
private NotificationManager mNotificationManager;
private static final String GENERIC_RULE_NAME = "test";
private static final String DEFAULT_ID_1 = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
private static final String DEFAULT_ID_1 = ZenModeConfig.EVENTS_OBSOLETE_RULE_ID;
private static final String DEFAULT_ID_2 = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
private Context mContext;
private ZenModeBackend mBackend;
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -161,6 +168,10 @@ public class ZenModeBackendTest {
}
@Test
// With MODES_UI the Events rule is not default and is sorted differently. Most likely this
// whole test class should be disabled since ZenModeBackend should never be used with
// MODES_UI. However the other tests pass, so...
@DisableFlags(Flags.FLAG_MODES_UI)
public void updateState_checkRuleOrderingDescending_withDefaultRules() {
final int NUM_RULES = 4;
@@ -168,8 +179,8 @@ public class ZenModeBackendTest {
true);
Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR);
assertEquals(rules[0].getKey(), DEFAULT_ID_1);
assertEquals(rules[1].getKey(), DEFAULT_ID_2);
assertEquals(DEFAULT_ID_1, rules[0].getKey());
assertEquals(DEFAULT_ID_2, rules[1].getKey());
// NON-DEFAULT RULES check ordering, most recent at the bottom/end
for (int i = 0; i < NUM_RULES; i++) {
assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i + 2].getKey());

View File

@@ -36,7 +36,7 @@ class MobileNetworkListFragmentTest {
@Test
fun isPageSearchEnabled_showMobileNetworkPage_returnTrue() {
mockSimRepository.stub { on { showMobileNetworkPage() } doReturn true }
mockSimRepository.stub { on { canEnterMobileNetworkPage() } doReturn true }
val isEnabled = SearchIndexProvider { mockSimRepository }.isPageSearchEnabled(context)
@@ -45,7 +45,7 @@ class MobileNetworkListFragmentTest {
@Test
fun isPageSearchEnabled_hideMobileNetworkPage_returnFalse() {
mockSimRepository.stub { on { showMobileNetworkPage() } doReturn false }
mockSimRepository.stub { on { canEnterMobileNetworkPage() } doReturn false }
val isEnabled = SearchIndexProvider { mockSimRepository }.isPageSearchEnabled(context)

View File

@@ -71,7 +71,7 @@ class TopLevelNetworkEntryPreferenceControllerTest {
@Test
fun getSummary_hasMobile_shouldReturnMobileSummary() {
mockSimRepository.stub { on { showMobileNetworkPage() } doReturn true }
mockSimRepository.stub { on { showMobileNetworkPageEntrance() } doReturn true }
val summary = controller.summary
@@ -84,7 +84,7 @@ class TopLevelNetworkEntryPreferenceControllerTest {
@Test
fun getSummary_noMobile_shouldReturnNoMobileSummary() {
mockSimRepository.stub { on { showMobileNetworkPage() } doReturn false }
mockSimRepository.stub { on { showMobileNetworkPageEntrance() } doReturn false }
val summary = controller.summary

View File

@@ -37,50 +37,76 @@ class SimRepositoryTest {
private val mockPackageManager = mock<PackageManager>()
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { userManager } doReturn mockUserManager
on { packageManager } doReturn mockPackageManager
}
private val context: Context =
spy(ApplicationProvider.getApplicationContext()) {
on { userManager } doReturn mockUserManager
on { packageManager } doReturn mockPackageManager
}
private val repository = SimRepository(context)
@Test
fun showMobileNetworkPage_adminUserAndHasTelephony_returnTrue() {
mockUserManager.stub {
on { isAdminUser } doReturn true
}
fun showMobileNetworkPageEntrance_adminUserAndHasTelephony_returnTrue() {
mockUserManager.stub { on { isAdminUser } doReturn true }
mockPackageManager.stub {
on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn true
}
val showMobileNetworkPage = repository.showMobileNetworkPage()
val showMobileNetworkPage = repository.showMobileNetworkPageEntrance()
assertThat(showMobileNetworkPage).isTrue()
}
@Test
fun showMobileNetworkPage_notAdminUser_returnFalse() {
fun showMobileNetworkPageEntrance_notAdminUser_returnFalse() {
mockUserManager.stub { on { isAdminUser } doReturn false }
mockPackageManager.stub {
on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn true
}
val showMobileNetworkPage = repository.showMobileNetworkPageEntrance()
assertThat(showMobileNetworkPage).isFalse()
}
@Test
fun showMobileNetworkPageEntrance_noTelephony_returnFalse() {
mockUserManager.stub { on { isAdminUser } doReturn true }
mockPackageManager.stub {
on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn false
}
val showMobileNetworkPage = repository.showMobileNetworkPageEntrance()
assertThat(showMobileNetworkPage).isFalse()
}
@Test
fun canEnterMobileNetworkPage_allowConfigMobileNetwork_returnTrue() {
mockUserManager.stub {
on { isAdminUser } doReturn false
on { isAdminUser } doReturn true
on { hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS) } doReturn false
}
mockPackageManager.stub {
on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn true
}
val showMobileNetworkPage = repository.showMobileNetworkPage()
val showMobileNetworkPage = repository.canEnterMobileNetworkPage()
assertThat(showMobileNetworkPage).isFalse()
assertThat(showMobileNetworkPage).isTrue()
}
@Test fun showMobileNetworkPage_noTelephony_returnFalse() {
@Test
fun canEnterMobileNetworkPage_disallowConfigMobileNetwork_returnFalse() {
mockUserManager.stub {
on { isAdminUser } doReturn true
on { hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS) } doReturn true
}
mockPackageManager.stub {
on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn false
on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY) } doReturn true
}
val showMobileNetworkPage = repository.showMobileNetworkPage()
val showMobileNetworkPage = repository.canEnterMobileNetworkPage()
assertThat(showMobileNetworkPage).isFalse()
}