Snap for 5158715 from 4c3251ebab to qt-release

Change-Id: I12aa2ebf2d53f8a9b010ef720fe881643730901d
This commit is contained in:
android-build-team Robot
2018-12-02 04:09:02 +00:00
106 changed files with 2623 additions and 1299 deletions

View File

@@ -114,13 +114,6 @@
<uses-library android:name="org.apache.http.legacy" />
<!-- Settings -->
<activity android:name="SettingsActivity"
android:label="@string/settings_label_launcher"
android:launchMode="singleTask">
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
<activity android:name=".homepage.SettingsHomepageActivity"
android:label="@string/settings_label_launcher"
android:theme="@style/Theme.Settings.Home"
@@ -3044,6 +3037,9 @@
<activity
android:name=".wifi.dpp.WifiDppConfiguratorActivity"/>
<activity android:name=".homepage.contextualcards.ContextualCardFeedbackDialog"
android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
<!-- This is the longest AndroidManifest.xml ever. -->
</application>
</manifest>

View File

@@ -1,6 +1,18 @@
<?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"
@@ -169,12 +181,12 @@
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;material_empty_color_light&quot;>#FFCED7DB&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
errorLine1=" &lt;color name=&quot;homepage_accessibility_background&quot;>#783BE5&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
file="res/values-night/colors.xml"
line="22"
column="5"/>
column="3"/>
</issue>
<issue
@@ -189,10 +201,26 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="24"
line="22"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#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;homepage_support_background&quot;>#3F5FBD&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-night/colors.xml"
line="23"
column="3"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -205,7 +233,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="26"
line="24"
column="5"/>
</issue>
@@ -221,7 +249,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="27"
line="25"
column="5"/>
</issue>
@@ -237,7 +265,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="28"
line="26"
column="5"/>
</issue>
@@ -253,7 +281,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="29"
line="27"
column="5"/>
</issue>
@@ -269,23 +297,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="31"
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;setup_lock_pattern_view_regular_color_dark&quot;>#ffbdbdbd&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="33"
line="29"
column="5"/>
</issue>
@@ -301,7 +313,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="35"
line="32"
column="5"/>
</issue>
@@ -317,7 +329,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="37"
line="34"
column="5"/>
</issue>
@@ -333,7 +345,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="38"
line="35"
column="5"/>
</issue>
@@ -349,7 +361,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="39"
line="36"
column="5"/>
</issue>
@@ -365,7 +377,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="41"
line="38"
column="5"/>
</issue>
@@ -381,7 +393,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="42"
line="39"
column="5"/>
</issue>
@@ -397,7 +409,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="44"
line="41"
column="5"/>
</issue>
@@ -413,7 +425,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="49"
line="46"
column="5"/>
</issue>
@@ -429,7 +441,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="50"
line="47"
column="5"/>
</issue>
@@ -445,7 +457,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="52"
line="49"
column="5"/>
</issue>
@@ -461,23 +473,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="53"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#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;wifi_divider&quot;>#ffe0e0e0&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="55"
line="50"
column="5"/>
</issue>
@@ -493,103 +489,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="58"
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;voice_interaction_highlight&quot;>#33b5e5&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="59"
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;memory_normal&quot;>#ff009587&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="61"
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;memory_moderate&quot;>#ffF3B300&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="62"
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;memory_low&quot;>#ffff9700&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="63"
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;memory_critical&quot;>#ffff5621&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="64"
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;memory_avg_use&quot;>#ff384248&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="66"
line="54"
column="5"/>
</issue>
@@ -605,39 +505,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="69"
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;importance_icon_tint&quot;>#8a000000&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="71"
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;importance_disabled_tint&quot;>#4d000000&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="72"
line="57"
column="5"/>
</issue>
@@ -653,7 +521,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="75"
line="60"
column="5"/>
</issue>
@@ -669,7 +537,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="76"
line="61"
column="5"/>
</issue>
@@ -685,7 +553,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="77"
line="62"
column="5"/>
</issue>
@@ -701,7 +569,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="78"
line="63"
column="5"/>
</issue>
@@ -717,7 +585,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="79"
line="64"
column="5"/>
</issue>
@@ -733,7 +601,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="82"
line="66"
column="5"/>
</issue>
@@ -749,7 +617,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="83"
line="67"
column="5"/>
</issue>
@@ -765,7 +633,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="84"
line="68"
column="5"/>
</issue>
@@ -781,7 +649,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="85"
line="69"
column="5"/>
</issue>
@@ -797,7 +665,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="86"
line="70"
column="5"/>
</issue>
@@ -813,7 +681,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="87"
line="71"
column="5"/>
</issue>
@@ -829,7 +697,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="88"
line="72"
column="5"/>
</issue>
@@ -845,7 +713,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="89"
line="73"
column="5"/>
</issue>
@@ -861,7 +729,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="90"
line="74"
column="5"/>
</issue>
@@ -877,7 +745,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="91"
line="75"
column="5"/>
</issue>
@@ -893,7 +761,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="92"
line="76"
column="5"/>
</issue>
@@ -909,7 +777,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="94"
line="78"
column="5"/>
</issue>
@@ -925,7 +793,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="97"
line="81"
column="5"/>
</issue>
@@ -941,7 +809,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="100"
line="84"
column="5"/>
</issue>
@@ -953,43 +821,11 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#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;wifi_details_icon_color&quot;>#8A000000&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
errorLine1=" &lt;color name=&quot;fallback_tintColor&quot;>#89000000&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="103"
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;suggestion_condition_background&quot;>#f2f2f2&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="106"
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;condition_card_background&quot;>#f8f8f8&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="107"
line="87"
column="5"/>
</issue>
@@ -1005,7 +841,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="110"
line="90"
column="5"/>
</issue>
@@ -1021,7 +857,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="111"
line="91"
column="5"/>
</issue>
@@ -1037,7 +873,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="112"
line="92"
column="5"/>
</issue>
@@ -1053,7 +889,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="113"
line="93"
column="5"/>
</issue>
@@ -1069,7 +905,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="114"
line="94"
column="5"/>
</issue>
@@ -1085,7 +921,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="115"
line="95"
column="5"/>
</issue>
@@ -1101,7 +937,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="116"
line="96"
column="5"/>
</issue>
@@ -1117,7 +953,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="117"
line="97"
column="5"/>
</issue>
@@ -1133,7 +969,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="118"
line="98"
column="5"/>
</issue>
@@ -1145,11 +981,11 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#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;homepage_accessibility_background&quot;>#783BE5&lt;/color>"
errorLine1=" &lt;color name=&quot;homepage_accessibility_background&quot;>#5011C1&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="119"
line="99"
column="5"/>
</issue>
@@ -1165,7 +1001,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="120"
line="100"
column="5"/>
</issue>
@@ -1177,11 +1013,11 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#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;homepage_support_background&quot;>#3F5FBD&lt;/color>"
errorLine1=" &lt;color name=&quot;homepage_support_background&quot;>#26459C&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="121"
line="101"
column="5"/>
</issue>
@@ -1197,7 +1033,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="122"
line="102"
column="5"/>
</issue>
@@ -1213,7 +1049,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="123"
line="103"
column="5"/>
</issue>
@@ -1229,7 +1065,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="124"
line="104"
column="5"/>
</issue>
@@ -1245,7 +1081,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="125"
line="105"
column="5"/>
</issue>
@@ -1261,7 +1097,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="126"
line="106"
column="5"/>
</issue>
@@ -1277,7 +1113,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="130"
line="110"
column="5"/>
</issue>
@@ -1293,7 +1129,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="135"
line="115"
column="5"/>
</issue>
@@ -1309,7 +1145,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="136"
line="116"
column="5"/>
</issue>
@@ -1325,7 +1161,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="137"
line="117"
column="5"/>
</issue>
@@ -1341,7 +1177,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="138"
line="118"
column="5"/>
</issue>
@@ -1357,7 +1193,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="139"
line="119"
column="5"/>
</issue>
@@ -1373,7 +1209,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="140"
line="120"
column="5"/>
</issue>
@@ -1389,7 +1225,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="143"
line="123"
column="5"/>
</issue>
@@ -1405,7 +1241,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="144"
line="124"
column="5"/>
</issue>
@@ -1421,7 +1257,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="145"
line="125"
column="5"/>
</issue>
@@ -1437,7 +1273,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="146"
line="126"
column="5"/>
</issue>
@@ -1453,7 +1289,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="147"
line="127"
column="5"/>
</issue>
@@ -1737,12 +1573,12 @@
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:tint=&quot;@color/wifi_details_icon_color&quot;>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
errorLine1=" android:color=&quot;@color/homepage_about_background&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/ic_frequency_antenna.xml"
line="22"
column="9"/>
file="res/drawable/ic_homepage_about.xml"
line="23"
column="17"/>
</issue>
<issue
@@ -1753,10 +1589,10 @@
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/homepage_about_background&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
errorLine1=" android:color=&quot;@color/homepage_accessibility_background&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/ic_homepage_about.xml"
file="res/drawable/ic_homepage_accessibility.xml"
line="23"
column="17"/>
</issue>
@@ -1985,6 +1821,22 @@
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/homepage_support_background&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/ic_homepage_support.xml"
line="23"
column="17"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -2033,22 +1885,6 @@
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:tint=&quot;@color/wifi_details_icon_color&quot;>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/ic_security_lock_24dp.xml"
line="22"
column="9"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -2605,7 +2441,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/strings.xml"
line="5806"
line="5805"
column="36"/>
</issue>
@@ -2637,7 +2473,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="419"
line="425"
column="44"/>
</issue>
@@ -2653,7 +2489,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="425"
line="431"
column="44"/>
</issue>
@@ -2669,7 +2505,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="426"
line="432"
column="44"/>
</issue>
@@ -2685,7 +2521,23 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="461"
line="467"
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 name=&quot;strokeColor&quot;>@color/homepage_card_stroke_color&lt;/item>"
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="474"
column="34"/>
</issue>

View File

@@ -19,7 +19,7 @@
android:viewportHeight="24"
android:width="24dp"
android:height="24dp"
android:tint="@color/wifi_details_icon_color">
android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M12,5c-3.9,0-7,3.1-7,7h2c0-2.8,2.2-5,5-5s5,2.2,5,5h2C19,8.1,15.9,5,12,5z M13,14.3c0.9-0.4,1.5-1.3,1.5-2.3
c0-1.4-1.1-2.5-2.5-2.5S9.5,10.6,9.5,12c0,1,0.6,1.9,1.5,2.3v3.3L7.6,21L9,22.4l3-3l3,3l1.4-1.4L13,17.6V14.3z M12,1

View File

@@ -19,7 +19,7 @@
android:viewportHeight="24"
android:width="24dp"
android:height="24dp"
android:tint="@color/wifi_details_icon_color">
android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"
android:fillColor="#FFFFFFFF" />

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="24dp"
android:paddingTop="18dp"
android:textColor="?android:attr/colorPrimary"
android:textSize="20sp"/>
<include layout="@layout/horizontal_divider"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/panel_parent_layout"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<include layout="@layout/panel_buttons"/>
</LinearLayout>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/wifi_dpp_fragment_header"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<SurfaceView
android:id="@+id/preview_view"
android:layout_width="426dp"
android:layout_height="320dp"
android:layout_gravity="center"/>
<com.android.settings.wifi.qrcode.QrDecorateView
android:id="@+id/decorate_view"
android:layout_width="426dp"
android:layout_height="320dp"
android:layout_gravity="center"/>
</FrameLayout>
<TextView android:id="@+id/error_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<include layout="@layout/wifi_dpp_fragment_footer"
android:gravity="center|bottom"/>
</LinearLayout>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="14dp"
android:paddingBottom="14dp"
android:orientation="horizontal">
<Button
android:id="@+id/see_more"
style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="@string/see_more"/>
<Space
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<Button
android:id="@+id/done"
style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:text="@string/done"/>
</LinearLayout>

View File

@@ -14,13 +14,30 @@
See the License for the specific language governing permissions and
limitations under the License
-->
<!-- Note: There is a landscape version of this layout. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/panel_parent_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:paddingBottom="8dp"
android:layout_margin="4dp"
android:orientation="vertical">
android:gravity="center"
android:paddingBottom="24dp"
android:paddingTop="18dp"
android:textColor="?android:attr/colorPrimary"
android:textSize="20sp"/>
<include layout="@layout/horizontal_divider"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/panel_parent_layout"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<include layout="@layout/panel_buttons"/>
</LinearLayout>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.slice.widget.SliceView
android:id="@+id/slice_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="20dp"
android:paddingEnd="20dp" />
<include layout="@layout/horizontal_divider"/>
</LinearLayout>

View File

@@ -15,42 +15,33 @@
limitations under the License.
-->
<FrameLayout
<com.google.android.material.card.MaterialCardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/search_bar_container"
android:id="@+id/search_bar"
style="@style/SearchBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/colorBackground"
android:theme="@style/ThemeOverlay.Settings.SearchBar"
app:layout_scrollFlags="scroll|enterAlways">
<androidx.cardview.widget.CardView
android:id="@+id/search_bar"
<Toolbar
android:id="@+id/search_action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/search_bar_margin"
app:cardCornerRadius="@dimen/search_bar_corner_radius"
app:cardElevation="@dimen/search_bar_card_elevation">
<Toolbar
android:id="@+id/search_action_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/search_bar_height"
android:background="?android:attr/selectableItemBackground"
android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset"
android:navigationIcon="@drawable/ic_search_24dp">
<TextView
android:id="@+id/search_action_bar_title"
style="@style/TextAppearance.SearchBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search_menu"/>
</Toolbar>
<ImageView
android:id="@+id/account_avatar"
android:layout_marginStart="@dimen/search_bar_avatar_start_margin"
android:layout_marginEnd="@dimen/search_bar_avatar_end_margin"
android:layout_width="@dimen/search_bar_avatar_size"
android:layout_height="@dimen/search_bar_avatar_size"
android:layout_gravity="end|center_vertical"/>
</androidx.cardview.widget.CardView>
</FrameLayout>
android:layout_height="@dimen/search_bar_height"
android:background="?android:attr/selectableItemBackground"
android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset"
android:navigationIcon="@drawable/ic_search_24dp">
<TextView
android:id="@+id/search_action_bar_title"
style="@style/TextAppearance.SearchBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search_menu"/>
</Toolbar>
<ImageView
android:id="@+id/account_avatar"
android:layout_marginStart="@dimen/search_bar_avatar_start_margin"
android:layout_marginEnd="@dimen/search_bar_avatar_end_margin"
android:layout_width="@dimen/search_bar_avatar_size"
android:layout_height="@dimen/search_bar_avatar_size"
android:layout_gravity="end|center_vertical"/>
</com.google.android.material.card.MaterialCardView>

View File

@@ -23,11 +23,12 @@
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:background="@android:color/transparent"
app:elevation="0dp">
<include layout="@layout/search_bar"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/main_content_scrollable_container"
android:layout_width="match_parent"

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2014, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/search_bar" />
<FrameLayout
android:id="@+id/main_content"
android:layout_height="match_parent"
android:layout_width="match_parent" />
</LinearLayout>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/wifi_dpp_fragment_header"/>
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"/>
<ImageView
android:id="@+id/wifi_ap_picture_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"/>
<TextView android:id="@+id/choose_different_network"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<include layout="@layout/wifi_dpp_fragment_footer"
android:gravity="center|bottom"/>
</LinearLayout>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/wifi_dpp_fragment_header"/>
<ListView android:id="@+id/saved_wifi_network_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<include layout="@layout/wifi_dpp_fragment_footer"
android:gravity="center|bottom"/>
</LinearLayout>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/wifi_dpp_fragment_header"/>
<ImageView
android:id="@+id/barcode_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"/>
</LinearLayout>

View File

@@ -17,7 +17,6 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -33,7 +32,7 @@
android:layout_width="320dp"
android:layout_height="426dp"
android:layout_gravity="center"/>
<ImageView
<com.android.settings.wifi.qrcode.QrDecorateView
android:id="@+id/decorate_view"
android:layout_width="320dp"
android:layout_height="426dp"

View File

@@ -47,7 +47,8 @@
android:id="@+id/zen_onboarding_new_setting_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="8dp" />
android:paddingHorizontal="8dp"
android:minHeight="48dp"/>
<LinearLayout
android:layout_width="match_parent"
@@ -83,7 +84,8 @@
android:id="@+id/zen_onboarding_current_setting_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="8dp" />
android:paddingHorizontal="8dp"
android:minHeight="48dp"/>
<LinearLayout
android:layout_width="match_parent"

View File

@@ -19,5 +19,7 @@
<color name="switch_bar_background">#dadce0</color>
<color name="switchbar_switch_track_tint">#82000000</color>
<color name="switchbar_switch_thumb_tint">@android:color/black</color>
<color name="homepage_accessibility_background">#783BE5</color>
<color name="homepage_support_background">#3F5FBD</color>
</resources>

View File

@@ -19,8 +19,6 @@
<color name="red">#F00</color>
<color name="blue">#00F</color>
<color name="material_empty_color_light">#FFCED7DB</color>
<color name="bluetooth_dialog_text_color">#8a000000</color>
<color name="crypt_keeper_clock_background">#ff9a9a9a</color>
@@ -30,7 +28,6 @@
<color name="divider_color">#20ffffff</color>
<color name="title_color">@android:color/holo_blue_light</color>
<color name="setup_lock_pattern_view_regular_color_dark">#ffbdbdbd</color>
<color name="setup_lock_pattern_view_regular_color_light">@color/lock_pattern_view_regular_color</color>
<color name="setup_lock_pattern_view_success_color_dark">#ff84ffff</color>
<color name="setup_lock_pattern_view_success_color_light">@color/suw_color_accent_light</color>
@@ -52,25 +49,13 @@
<color name="running_processes_system_ram">#ff384248</color>
<color name="running_processes_free_ram">#ffced7db</color>
<color name="wifi_divider">#ffe0e0e0</color>
<color name="sim_noitification">@*android:color/accent_device_default_light</color>
<color name="confirm_device_credential_transparent_black">#60000000</color>
<color name="voice_interaction_highlight">#33b5e5</color>
<color name="memory_normal">#ff009587</color>
<color name="memory_moderate">#ffF3B300</color>
<color name="memory_low">#ffff9700</color>
<color name="memory_critical">#ffff5621</color>
<color name="memory_avg_use">#ff384248</color>
<!-- Accent color that matches the settings launcher icon -->
<color name="icon_accent">#ffabffec</color>
<color name="importance_icon_tint">#8a000000</color>
<color name="importance_disabled_tint">#4d000000</color>
<!-- Accessibility SUW colors -->
<color name="material_blue_500">#4285F4</color>
<color name="material_blue_700">#3367D6</color>
@@ -78,7 +63,6 @@
<color name="material_grey_200">#ffffff</color>
<color name="switch_bar_background">#ff80868B</color>
<color name="message_text_incoming">#ffffffff</color>
<color name="message_text_outgoing">#ff323232</color>
<color name="timestamp_text_outgoing">#99323232</color>
@@ -99,12 +83,8 @@
<!-- Color for the background of the shortcut icons.-->
<color name="shortcut_background">#fff5f5f5</color>
<!-- Color for preference icons on the Wifi Network Details page -->
<color name="wifi_details_icon_color">#8A000000</color>
<!-- Suggestion/condition colors -->
<color name="suggestion_condition_background">#f2f2f2</color>
<color name="condition_card_background">#f8f8f8</color>
<!-- The fallback color for tinting icons. Only used when colorControlNormal is unavailable -->
<color name="fallback_tintColor">#89000000</color>
<!-- Dashboard/homepage icon background colors -->
<color name="homepage_network_background">#2196F3</color>
@@ -116,9 +96,9 @@
<color name="homepage_storage_background">#C14CE6</color>
<color name="homepage_security_background">#0F9D58</color>
<color name="homepage_accounts_background">#F15B8D</color>
<color name="homepage_accessibility_background">#783BE5</color>
<color name="homepage_accessibility_background">#5011C1</color>
<color name="homepage_system_background">#9E9E9E</color>
<color name="homepage_support_background">#3F5FBD</color>
<color name="homepage_support_background">#26459C</color>
<color name="homepage_generic_icon_background">#1A73E8</color>
<color name="homepage_location_background">#2EC7DC</color>
<color name="homepage_about_background">#9FA8DA</color>

View File

@@ -151,6 +151,9 @@
com.android.settings.intelligence
</string>
<!-- Settings intelligence interaction log intent action -->
<string name="config_settingsintelligence_log_action" translatable="false"></string>
<!-- Emergency app package name -->
<string name="config_emergency_package_name" translatable="false">
com.android.emergency
@@ -160,4 +163,6 @@
android.settings.EDIT_EMERGENCY_INFO
</string>
<!-- Email address for the homepage contextual cards feedback -->
<string name="config_contextual_card_feedback_email" translatable="false"></string>
</resources>

View File

@@ -95,11 +95,7 @@
<dimen name="switchbar_subsettings_margin_start">72dp</dimen>
<dimen name="switchbar_subsettings_margin_end">16dp</dimen>
<!-- The following two margins need to match, with the caveat that
the second should be negative. The second one ensures that the icons and text
align despite the additional padding caused by the search bar's card background. -->
<dimen name="search_bar_margin">16dp</dimen>
<dimen name="search_bar_negative_margin">-16dp</dimen>
<dimen name="search_bar_height">48dp</dimen>
<dimen name="search_bar_corner_radius">2dp</dimen>

View File

@@ -3456,9 +3456,9 @@
<!-- Button title to factory data reset the entire device. The "(factory reset)" part is optional for translation. [CHAR LIMIT=30 BACKUP_MESSAGE_ID=3531267871084279512]-->
<string name="master_clear_short_title">Erase all data (factory reset)</string>
<!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset [CHAR LIMIT=NONE] -->
<string name="master_clear_desc" product="tablet">"This will erase all data from your tablet\u2019s <b>internal storage</b>, including:\n\n<li>Your Google account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
<string name="master_clear_desc" product="tablet">"This will erase all data from your tablet\u2019s <b>internal storage</b>, including:\n\n<li>Your Google Account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
<!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset [CHAR LIMIT=NONE] -->
<string name="master_clear_desc" product="default">"This will erase all data from your phone\u2019s <b>internal storage</b>, including:\n\n<li>Your Google account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
<string name="master_clear_desc" product="default">"This will erase all data from your phone\u2019s <b>internal storage</b>, including:\n\n<li>Your Google Account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
<!-- SD card & phone storage settings screen, instructions and list of current accounts. The list of accounts follows this text[CHAR LIMIT=NONE] -->
<string name="master_clear_accounts" product="default">"\n\nYou are currently signed into the following accounts:\n"</string>
<!-- SD card & phone storage settings screen, notification if other users are present on the device [CHAR LIMIT=NONE] -->
@@ -3488,17 +3488,17 @@
<!-- SD card & phone storage settings screen, description for check box to erase eSIMs for tablets [CHAR LIMIT=NONE] -->
<string name="erase_esim_storage_description" product="tablet">Erase all eSIMs on the tablet. This will not cancel your mobile service plan.</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Factory data reset -->
<string name="master_clear_button_text" product="tablet">Reset tablet</string>
<string name="master_clear_button_text" product="tablet">Erase all data</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Factory data reset -->
<string name="master_clear_button_text" product="default">Reset phone</string>
<string name="master_clear_button_text" product="default">Erase all data</string>
<!-- SD card & phone storage settings screen, message on screen after user selects Reset phone button -->
<string name="master_clear_final_desc">Erase all your personal information and downloaded apps? You can\u2019t undo this action!</string>
<string name="master_clear_final_desc">All of your personal information and downloaded apps will be deleted. You can\u2019t undo this action!</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Reset phone button -->
<string name="master_clear_final_button_text">Erase everything</string>
<!-- Master clear failed message -->
<string name="master_clear_failed">No reset was performed because the System Clear service isn\u2019t available.</string>
<!-- Master clear confirmation screen title [CHAR LIMIT=30] -->
<string name="master_clear_confirm_title">Reset?</string>
<string name="master_clear_confirm_title">Erase all data?</string>
<!-- Error message for users that aren't allowed to factory reset [CHAR LIMIT=none] -->
<string name="master_clear_not_available">Factory reset is not available for this user</string>
<!-- Master clear progress screen title [CHAR LIMIT=30] -->
@@ -8931,25 +8931,28 @@
<string name="condition_expand_hide">Hide</string>
<!-- Title of condition that hotspot is on [CHAR LIMIT=30] -->
<string name="condition_hotspot_title">Hotspot is on</string>
<string name="condition_hotspot_title">Hotspot</string>
<!-- Summary of condition that hotspot is on [CHAR LIMIT=NONE] -->
<string name="condition_hotspot_summary">Portable Wi-Fi hotspot <xliff:g name="ap_name" example="AndroidAP">%1$s</xliff:g> is active, Wi-Fi for this device is turned off.</string>
<string name="condition_hotspot_summary"><xliff:g name="ap_name" example="AndroidAP">%1$s</xliff:g> on</string>
<!-- Title of condition that airplane mode is on [CHAR LIMIT=30] -->
<string name="condition_airplane_title">Airplane mode is on</string>
<!-- Summary of condition that airplane mode is on [CHAR LIMIT=NONE] -->
<string name="condition_airplane_summary">When airplane mode is turned on, Wi\u2011Fi, Bluetooth, and mobile network are turned off. Wi\u2011Fi and Bluetooth can be turned back on.</string>
<string name="condition_airplane_summary">Networks unavailable</string>
<!-- Title of condition that do not disturb is on [CHAR LIMIT=36] -->
<string name="condition_zen_title">Do Not Disturb is on</string>
<!-- Summary of condition that do not disturb is on [CHAR LIMIT=36] -->
<string name="condition_zen_summary">Impacts what you hear and see</string>
<!-- Title of condition that battery saver is on [CHAR LIMIT=30] -->
<string name="condition_battery_title">Battery Saver is on</string>
<!-- Summary of condition that battery saver is on [CHAR LIMIT=NONE] -->
<string name="condition_battery_summary">Battery Saver turns off some device features and restricts apps</string>
<string name="condition_battery_summary">Features restricted</string>
<!-- Title of condition that cellular data is off [CHAR LIMIT=50] -->
<string name="condition_cellular_title">Mobile data is off</string>
@@ -8958,10 +8961,10 @@
<string name="condition_cellular_summary">Internet is available only via Wi-Fi</string>
<!-- Title of condition that background data is off [CHAR LIMIT=30] -->
<string name="condition_bg_data_title">Data Saver is on</string>
<string name="condition_bg_data_title">Data Saver</string>
<!-- Summary of condition that background data is off [CHAR LIMIT=NONE] -->
<string name="condition_bg_data_summary">Background data is only available via Wi-Fi. This may affect some apps or services when Wi-Fi is not available.</string>
<string name="condition_bg_data_summary">Features restricted</string>
<!-- Title of condition that work mode is off [CHAR LIMIT=30] -->
<string name="condition_work_title">Work profile is off</string>
@@ -8976,22 +8979,22 @@
<string name="condition_device_muted_title" product="tablet">Device is muted</string>
<!-- Title of condition that indicates device is muted [CHAR LIMIT=50] -->
<string name="condition_device_muted_title" product="default">Phone is muted</string>
<string name="condition_device_muted_title" product="default">Phone muted</string>
<!-- Summary of condition that indicates device is muted -->
<string name="condition_device_muted_summary">Calls and notifications will be muted</string>
<string name="condition_device_muted_summary">For calls &amp; notifications</string>
<!-- Title of condition that indicates device is set to vibrate [CHAR LIMIT=50] -->
<string name="condition_device_vibrate_title" product="tablet">Device is set to vibrate</string>
<!-- Title of condition that indicates device is muted [CHAR LIMIT=50] -->
<string name="condition_device_vibrate_title" product="default">Phone is set to vibrate</string>
<string name="condition_device_vibrate_title" product="default">Vibration only</string>
<!-- Summary of condition that indicates device is set to vibrate -->
<string name="condition_device_vibrate_summary" product="tablet">Calls and notifications will vibrate device</string>
<!-- Summary of condition that indicates device is set to vibrate -->
<string name="condition_device_vibrate_summary" product="default">Calls and notifications will vibrate phone</string>
<string name="condition_device_vibrate_summary" product="default">For calls &amp; notifications</string>
<!-- Night display: Title for the night display option Suggestion (renamed "Night Light" with title caps). [CHAR LIMIT=46] -->
<string name="night_display_suggestion_title">Set Night Light schedule</string>
@@ -9003,7 +9006,7 @@
<string name="condition_night_display_title">Night Light is on</string>
<!-- Summary of condition that night display is on (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
<string name="condition_night_display_summary">Screen is tinted amber. This may help you fall asleep.</string>
<string name="condition_night_display_summary">Screen tinted amber</string>
<!-- Summary for the condition section on the dashboard, representing number of conditions. [CHAR LIMIT=10] -->
<string name="condition_summary" translatable="false"><xliff:g name="count" example="3">%1$d</xliff:g></string>
@@ -9889,6 +9892,11 @@
<!-- UI debug setting: preference summary - describes the behavior of forcing full raw GNSS satellite measurements [CHAR LIMIT=NONE] -->
<string name="enable_gnss_raw_meas_full_tracking_summary">Track all GNSS constellations and frequencies with no duty cycling</string>
<!-- UI debug setting: preference title - allow background activity starts [CHAR LIMIT=60] -->
<string name="allow_background_activity_starts">Allow background activity starts</string>
<!-- UI debug setting: preference summary - describes the behavior of allowing background activity starts [CHAR LIMIT=NONE] -->
<string name="allow_background_activity_starts_summary">Allows all background activity starts</string>
<!-- UI debug setting: preference title - show all crash dialogs [CHAR LIMIT=60] -->
<string name="show_first_crash_dialog">Always show crash dialog</string>
<!-- UI debug setting: preference summary - describes the behavior of showing a dialog every time an app crashes [CHAR LIMIT=NONE] -->
@@ -10230,9 +10238,9 @@
<!-- UI debug setting: force desktop mode summary [CHAR LIMIT=NONE] -->
<string name="force_desktop_mode_summary">Force experimental desktop mode on secondary displays</string>
<!-- UI debug setting: Force enable "smart dark" UI rendering feature [CHAR LIMIT=40] -->
<!-- UI debug setting: Force enable "smart dark" UI rendering feature [CHAR LIMIT=60] -->
<string name="hwui_force_dark_title">Override force-dark</string>
<!-- UI debug setting: Force enable "smart dark" UI rendering feature summary [CHAR LIMIT=100] -->
<!-- UI debug setting: Force enable "smart dark" UI rendering feature summary [CHAR LIMIT=NONE] -->
<string name="hwui_force_dark_summary">Overrides the force-dark feature to be always-on</string>
<!-- Title for the top level Privacy Settings [CHAR LIMIT=30]-->
@@ -10249,4 +10257,9 @@
<!-- Summary for low storage slice. [CHAR LIMIT=NONE] -->
<string name="low_storage_summary">Storage is low. <xliff:g id="percentage" example="54%">%1$s</xliff:g> used - <xliff:g id="free_space" example="32GB">%2$s</xliff:g> free</string>
</resources>
<!-- Label for button in contextual card feedback dialog for users to send feedback [CHAR LIMIT=30] -->
<string name="contextual_card_feedback_send">Send feedback</string>
<!-- String for contextual card feedback dialog [CHAR LIMIT=NONE] -->
<string name="contextual_card_feedback_confirm_message">Would you like to give us feedback on this suggestion?</string>
</resources>

View File

@@ -17,7 +17,7 @@
<resources>
<style name="Widget.ActionBar.Base"
parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid"/>
parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid"/>
<style name="Widget.ActionBar"
parent="Widget.ActionBar.Base">
@@ -259,7 +259,8 @@
<style name="TextAppearance.Medium" parent="@android:style/TextAppearance.Material.Medium"/>
<style name="TextAppearance.Small" parent="@android:style/TextAppearance.Material.Small"/>
<style name="TextAppearance.Switch" parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
<style name="TextAppearance.Switch"
parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
<item name="android:textSize">16sp</item>
</style>
@@ -400,9 +401,11 @@
<style name="ActionSecondaryButton" parent="android:Widget.DeviceDefault.Button"/>
<style name="SettingsActionButton" parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
<style name="SettingsActionButton"
parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
<item name="android:drawablePadding">4dp</item>
<item name="android:drawableTint">@*android:color/btn_colored_borderless_text_material</item>
<item name="android:drawableTint">@*android:color/btn_colored_borderless_text_material
</item>
<item name="android:layout_marginEnd">8dp</item>
<item name="android:paddingTop">20dp</item>
<item name="android:paddingBottom">20dp</item>
@@ -465,6 +468,13 @@
<item name="strokeWidth">1dp</item>
</style>
<style name="SearchBarStyle">
<item name="android:layout_margin">@dimen/search_bar_margin</item>
<item name="cardCornerRadius">8dp</item>
<item name="strokeColor">@color/homepage_card_stroke_color</item>
<item name="strokeWidth">1dp</item>
</style>
<style name="ConditionCardBorderlessButton"
parent="android:Widget.DeviceDefault.Button.Borderless">
<item name="android:textColor">?android:attr/colorAccent</item>

View File

@@ -195,13 +195,11 @@
<item name="android:windowLightNavigationBar">true</item>
</style>
<style name="ThemeOverlay.Settings.SearchBar" parent="Theme.Settings">
<item name="android:colorBackground">?android:attr/colorPrimary</item>
<item name="cardBackgroundColor">?android:attr/colorBackground</item>
</style>
<style name="Theme.BottomDialog" parent="@*android:style/Theme.DeviceDefault.Settings.Dialog">
<item name="android:windowBackground">@drawable/settings_panel_background</item>
<item name="android:dividerHorizontal">@*android:drawable/list_divider_material</item>
<item name="android:windowNoTitle">true</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
</style>
</resources>

View File

@@ -484,6 +484,11 @@
android:fragment="com.android.settings.applications.appops.BackgroundCheckSummary"
android:title="@string/background_check_pref" />
<SwitchPreference
android:key="allow_background_activity_starts"
android:title="@string/allow_background_activity_starts"
android:summary="@string/allow_background_activity_starts_summary" />
<SwitchPreference
android:key="show_first_crash_dialog"
android:title="@string/show_first_crash_dialog"

View File

@@ -44,7 +44,6 @@
android:title="@string/auto_brightness_title"
android:summary="@string/summary_placeholder"
android:fragment="com.android.settings.display.AutoBrightnessSettings"
settings:searchable="false"
settings:controller="com.android.settings.display.AutoBrightnessPreferenceController" />
<com.android.settingslib.RestrictedPreference

View File

@@ -34,18 +34,18 @@
<!-- General Details Category -->
<PreferenceCategory
android:key="general_details_category" >
<com.android.settings.wifi.WifiDetailPreference
<Preference
android:key="signal_strength"
android:title="@string/wifi_signal"
android:selectable="false"/>
<com.android.settings.wifi.WifiDetailPreference
<Preference
android:key="frequency"
android:icon="@drawable/ic_frequency_antenna"
android:title="@string/wifi_frequency"
android:selectable="false"/>
<com.android.settings.wifi.WifiDetailPreference
<Preference
android:key="security"
android:icon="@drawable/ic_security_lock_24dp"
android:title="@string/wifi_security"
@@ -69,30 +69,36 @@
<PreferenceCategory
android:key="ip_details_category"
android:title="@string/wifi_setup_detail">
<com.android.settings.wifi.WifiDetailPreference
android:key="mac_address"
android:title="@string/wifi_advanced_mac_address_title"
android:selectable="false"/>
<com.android.settings.wifi.WifiDetailPreference
<Preference
android:key="mac_address"
android:title="@string/wifi_advanced_mac_address_title"
android:selectable="false"
settings:enableCopying="true"/>
<Preference
android:key="ip_address"
android:title="@string/wifi_ip_address"
android:selectable="false"/>
<com.android.settings.wifi.WifiDetailPreference
android:selectable="false"
settings:enableCopying="true"/>
<Preference
android:key="gateway"
android:title="@string/wifi_gateway"
android:selectable="false"/>
<com.android.settings.wifi.WifiDetailPreference
android:selectable="false"
settings:enableCopying="true"/>
<Preference
android:key="subnet_mask"
android:title="@string/wifi_details_subnet_mask"
android:selectable="false"/>
<com.android.settings.wifi.WifiDetailPreference
android:selectable="false"
settings:enableCopying="true"/>
<Preference
android:key="dns"
android:title="@string/wifi_details_dns"
android:selectable="false"/>
<com.android.settings.wifi.WifiDetailPreference
android:selectable="false"
settings:enableCopying="true"/>
<Preference
android:key="link_speed"
android:title="@string/wifi_speed"
android:selectable="false"/>
android:selectable="false"
settings:enableCopying="true"/>
</PreferenceCategory>
<!-- IPv6 Details -->

View File

@@ -38,7 +38,6 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toolbar;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
@@ -169,8 +168,6 @@ public class SettingsActivity extends SettingsBaseActivity
private Button mNextButton;
private boolean mIsShowingDashboard;
private ViewGroup mContent;
// Categories
@@ -241,9 +238,6 @@ public class SettingsActivity extends SettingsBaseActivity
// Getting Intent properties can only be done after the super.onCreate(...)
final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
mIsShowingDashboard = TextUtils.equals(
SettingsActivity.class.getName(), intent.getComponent().getClassName());
// This is a "Sub Settings" when:
// - this is a real SubSettings
// - or :settings:show_fragment_as_subsetting is passed to the Intent
@@ -256,8 +250,7 @@ public class SettingsActivity extends SettingsBaseActivity
setTheme(R.style.Theme_SubSettings);
}
setContentView(mIsShowingDashboard ?
R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
setContentView(R.layout.settings_main_prefs);
mContent = findViewById(R.id.main_content);
@@ -276,25 +269,16 @@ public class SettingsActivity extends SettingsBaseActivity
setTitleFromBackStack();
}
} else {
launchSettingFragment(initialFragmentName, isSubSettings, intent);
launchSettingFragment(initialFragmentName, intent);
}
final boolean deviceProvisioned = Utils.isDeviceProvisioned(this);
if (mIsShowingDashboard) {
findViewById(R.id.search_bar).setVisibility(
deviceProvisioned ? View.VISIBLE : View.INVISIBLE);
findViewById(R.id.action_bar).setVisibility(View.GONE);
final Toolbar toolbar = findViewById(R.id.search_action_bar);
setActionBar(toolbar);
FeatureFactory.getFactory(this).getSearchFeatureProvider()
.initSearchToolbar(this, toolbar);
}
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(deviceProvisioned);
actionBar.setHomeButtonEnabled(deviceProvisioned);
actionBar.setDisplayShowTitleEnabled(!mIsShowingDashboard);
actionBar.setDisplayShowTitleEnabled(true);
}
mSwitchBar = findViewById(R.id.switch_bar);
if (mSwitchBar != null) {
@@ -372,8 +356,8 @@ public class SettingsActivity extends SettingsBaseActivity
}
@VisibleForTesting
void launchSettingFragment(String initialFragmentName, boolean isSubSettings, Intent intent) {
if (!mIsShowingDashboard && initialFragmentName != null) {
void launchSettingFragment(String initialFragmentName, Intent intent) {
if (initialFragmentName != null) {
setTitleFromIntent(intent);
Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);

View File

@@ -76,7 +76,7 @@ public class BluetoothDetailsButtonsController extends BluetoothDetailsControlle
if (!mConnectButtonInitialized || previouslyConnected) {
mActionButtons
.setButton2Text(R.string.bluetooth_device_context_connect)
// TODO (b/119646923) Icon is not ready.
.setButton2Icon(R.drawable.ic_add_24dp)
.setButton2OnClickListener(
view -> mCachedDevice.connect(true /* connectAllProfiles */));
mConnectButtonInitialized = true;

View File

@@ -20,7 +20,6 @@ import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -37,6 +36,7 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.connecteddevice.BluetoothDashboardFragment;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
@@ -47,16 +47,6 @@ public class BluetoothSliceBuilder {
private static final String TAG = "BluetoothSliceBuilder";
/**
* Backing Uri for the Bluetooth Slice.
*/
public static final Uri BLUETOOTH_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(SettingsSlicesContract.KEY_BLUETOOTH)
.build();
/**
* Action notifying a change on the BluetoothSlice.
*/
@@ -74,7 +64,7 @@ public class BluetoothSliceBuilder {
}
/**
* Return a Bluetooth Slice bound to {@link #BLUETOOTH_URI}.
* Return a Bluetooth Slice bound to {@link CustomSliceRegistry#BLUETOOTH_URI}.
* <p>
* Note that you should register a listener for {@link #INTENT_FILTER} to get changes for
* Bluetooth.
@@ -88,11 +78,12 @@ public class BluetoothSliceBuilder {
context).getDefaultColor();
final PendingIntent toggleAction = getBroadcastIntent(context);
final PendingIntent primaryAction = getPrimaryAction(context);
final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
isBluetoothEnabled);
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
ListBuilder.ICON_IMAGE, title);
final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
null /* actionTitle */, isBluetoothEnabled);
return new ListBuilder(context, BLUETOOTH_URI, ListBuilder.INFINITY)
return new ListBuilder(context, CustomSliceRegistry.BLUETOOTH_URI, ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)

View File

@@ -193,17 +193,13 @@ public class DataUsageList extends DataUsageBaseFragment {
public void onResume() {
super.onResume();
mDataStateListener.setListener(true, mSubId, getContext());
updateBody();
// kick off background task to update stats
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
// wait a few seconds before kicking off
Thread.sleep(2 * DateUtils.SECOND_IN_MILLIS);
services.mStatsService.forceUpdate();
} catch (InterruptedException e) {
} catch (RemoteException e) {
}
return null;
@@ -211,9 +207,7 @@ public class DataUsageList extends DataUsageBaseFragment {
@Override
protected void onPostExecute(Void result) {
if (isAdded()) {
updateBody();
}
updateBody();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}

View File

@@ -187,28 +187,6 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
super.onResume();
mDataStateListener.setListener(true, mSubId, getContext());
updateBody();
// kick off background task to update stats
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
// wait a few seconds before kicking off
Thread.sleep(2 * DateUtils.SECOND_IN_MILLIS);
services.mStatsService.forceUpdate();
} catch (InterruptedException e) {
} catch (RemoteException e) {
}
return null;
}
@Override
protected void onPostExecute(Void result) {
if (isAdded()) {
updateBody();
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@Override

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.development;
import android.content.Context;
import android.provider.Settings;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
public class AllowBackgroundActivityStartsPreferenceController
extends DeveloperOptionsPreferenceController
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
private static final String BACKGROUND_ACTIVITY_STARTS_ENABLED_KEY
= "allow_background_activity_starts";
public AllowBackgroundActivityStartsPreferenceController(Context context) {
super(context);
}
@Override
public String getPreferenceKey() {
return BACKGROUND_ACTIVITY_STARTS_ENABLED_KEY;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
writeSetting((boolean) newValue);
return true;
}
private void writeSetting(boolean isEnabled) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, isEnabled ? 1 : 0);
}
@Override
public void updateState(Preference preference) {
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1);
((SwitchPreference) mPreference).setChecked(mode != 0);
}
@Override
protected void onDeveloperOptionsSwitchDisabled() {
super.onDeveloperOptionsSwitchDisabled();
writeSetting(false);
((SwitchPreference) mPreference).setChecked(false);
}
}

View File

@@ -454,6 +454,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
controllers.add(new ProfileGpuRenderingPreferenceController(context));
controllers.add(new KeepActivitiesPreferenceController(context));
controllers.add(new BackgroundProcessLimitPreferenceController(context));
controllers.add(new AllowBackgroundActivityStartsPreferenceController(context));
controllers.add(new ShowFirstCrashDialogPreferenceController(context));
controllers.add(new AppsNotRespondingPreferenceController(context));
controllers.add(new NotificationChannelWarningsPreferenceController(context));

View File

@@ -52,7 +52,7 @@ public class AutoBrightnessPreferenceController extends TogglePreferenceControll
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(
com.android.internal.R.bool.config_automatic_brightness_available)
? AVAILABLE_UNSEARCHABLE
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
@@ -67,4 +67,4 @@ public class AutoBrightnessPreferenceController extends TogglePreferenceControll
? R.string.auto_brightness_summary_on
: R.string.auto_brightness_summary_off);
}
}
}

View File

@@ -22,17 +22,14 @@ import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.net.Uri;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.provider.SettingsSlicesContract;
import android.util.Log;
import androidx.core.graphics.drawable.IconCompat;
@@ -43,7 +40,7 @@ import androidx.slice.builders.SliceAction;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBroadcastReceiver;
@@ -54,37 +51,23 @@ public class FlashlightSliceBuilder {
private static final String TAG = "FlashlightSliceBuilder";
public static final String KEY_FLASHLIGHT = "flashlight";
/**
* Backing Uri for the Flashlight Slice.
*/
public static final Uri FLASHLIGHT_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(KEY_FLASHLIGHT)
.build();
/**
* Action notifying a change on the Flashlight Slice.
*/
public static final String ACTION_FLASHLIGHT_SLICE_CHANGED =
"com.android.settings.flashlight.action.FLASHLIGHT_SLICE_CHANGED";
"com.android.settings.flashlight.action.FLASHLIGHT_SLICE_CHANGED";
/**
* Action broadcasting a change on whether flashlight is on or off.
*/
public static final String ACTION_FLASHLIGHT_CHANGED =
"com.android.settings.flashlight.action.FLASHLIGHT_CHANGED";
"com.android.settings.flashlight.action.FLASHLIGHT_CHANGED";
public static final IntentFilter INTENT_FILTER = new IntentFilter(ACTION_FLASHLIGHT_CHANGED);
private FlashlightSliceBuilder() {}
private FlashlightSliceBuilder() {
}
/**
* Return a Flashlight Slice bound to {@link #FLASHLIGHT_URI}.
*/
public static Slice getSlice(Context context) {
if (!isFlashlightAvailable(context)) {
return null;
@@ -93,14 +76,15 @@ public class FlashlightSliceBuilder {
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final IconCompat icon =
IconCompat.createWithResource(context, R.drawable.ic_signal_flashlight);
return new ListBuilder(context, FLASHLIGHT_URI, ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(context.getText(R.string.power_flashlight))
.setTitleItem(icon, ICON_IMAGE)
.setPrimaryAction(
new SliceAction(toggleAction, null, isFlashlightEnabled(context))))
.build();
return new ListBuilder(context, CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(context.getText(R.string.power_flashlight))
.setTitleItem(icon, ICON_IMAGE)
.setPrimaryAction(
SliceAction.createToggle(toggleAction, null, isFlashlightEnabled(context))))
.build();
}
/**
@@ -119,7 +103,7 @@ public class FlashlightSliceBuilder {
} catch (CameraAccessException e) {
Log.e(TAG, "Camera couldn't set torch mode.", e);
}
context.getContentResolver().notifyChange(FLASHLIGHT_URI, null);
context.getContentResolver().notifyChange(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, null);
}
private static String getCameraId(Context context) throws CameraAccessException {
@@ -130,7 +114,7 @@ public class FlashlightSliceBuilder {
Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
if (flashAvailable != null && flashAvailable
&& lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
&& lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
return id;
}
}
@@ -141,16 +125,16 @@ public class FlashlightSliceBuilder {
final Intent intent = new Intent(ACTION_FLASHLIGHT_SLICE_CHANGED);
intent.setClass(context, SliceBroadcastReceiver.class);
return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
PendingIntent.FLAG_CANCEL_CURRENT);
}
private static boolean isFlashlightAvailable(Context context) {
return Settings.Secure.getInt(
context.getContentResolver(), Secure.FLASHLIGHT_AVAILABLE, 0) == 1;
context.getContentResolver(), Secure.FLASHLIGHT_AVAILABLE, 0) == 1;
}
private static boolean isFlashlightEnabled(Context context) {
return Settings.Secure.getInt(
context.getContentResolver(), Secure.FLASHLIGHT_ENABLED, 0) == 1;
context.getContentResolver(), Secure.FLASHLIGHT_ENABLED, 0) == 1;
}
}

View File

@@ -42,6 +42,9 @@ import java.util.Map;
* Controller in charge of the battery tip group
*/
public class BatteryTipPreferenceController extends BasePreferenceController {
public static final String PREF_NAME = "battery_tip";
private static final String TAG = "BatteryTipPreferenceController";
private static final int REQUEST_ANOMALY_ACTION = 0;
private static final String KEY_BATTERY_TIPS = "key_battery_tips";

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.homepage.contextualcards;
import android.content.Context;
import java.util.List;
/** Feature provider for the contextual card feature. */
public interface ContextualCardFeatureProvider {
/** Homepage displays. */
public void logHomepageDisplay(Context context, Long latency);
/** When user clicks dismiss in contextual card */
public void logContextualCardDismiss(Context context, ContextualCard card);
/** After ContextualCardManager decides which cards will be displayed/hidden */
public void logContextualCardDisplay(Context context, List<ContextualCard> showedCards,
List<ContextualCard> hiddenCards);
/** When user clicks toggle/title area of a contextual card. */
public void logContextualCardClick(Context context, ContextualCard card, int row,
int tapTarget);
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.homepage.contextualcards;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.slice.widget.EventInfo;
import com.android.settings.R;
import java.util.List;
public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureProvider {
private static final String TAG = "ContextualCardFeature";
// Contextual card interaction logs
// Settings Homepage shows
private static final int CONTEXTUAL_HOME_SHOW = 38;
// Contextual card shows, log card name and rank
private static final int CONTEXTUAL_CARD_SHOW = 39;
// Contextual card is eligible to be shown, but doesn't rank high
// enough, log card name and score
private static final int CONTEXTUAL_CARD_NOT_SHOW = 40;
// Contextual card is dismissed, log card name
private static final int CONTEXTUAL_CARD_DISMISS = 41;
// Contextual card is clicked , log card name, score, tap area
private static final int CONTEXTUAL_CARD_CLICK = 42;
// SettingsLogBroadcastReceiver contracts
// contextual card name
private static final String EXTRA_CONTEXTUALCARD_NAME = "name";
// contextual card score
private static final String EXTRA_CONTEXTUALCARD_SCORE = "score";
// contextual card clicked row
private static final String EXTRA_CONTEXTUALCARD_ROW = "row";
// contextual card tap target
private static final String EXTRA_CONTEXTUALCARD_TAP_TARGET = "target";
// contextual homepage display latency
private static final String EXTRA_LATENCY = "latency";
// log type
private static final String EXTRA_CONTEXTUALCARD_ACTION_TYPE = "type";
// Contextual card tap target
private static final int TARGET_DEFAULT = 0;
// Click title area
private static final int TARGET_TITLE = 1;
// Click toggle
private static final int TARGET_TOGGLE = 2;
// Click slider
private static final int TARGET_SLIDER = 3;
@Override
public void logHomepageDisplay(Context context, Long latency) {
}
@Override
public void logContextualCardDismiss(Context context, ContextualCard card) {
final Intent intent = new Intent();
intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_DISMISS);
intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
sendBroadcast(context, intent);
}
@Override
public void logContextualCardDisplay(Context context, List<ContextualCard> showCards,
List<ContextualCard> hiddenCards) {
}
@Override
public void logContextualCardClick(Context context, ContextualCard card, int row,
int actionType) {
final Intent intent = new Intent();
intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_CLICK);
intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
intent.putExtra(EXTRA_CONTEXTUALCARD_ROW, row);
intent.putExtra(EXTRA_CONTEXTUALCARD_TAP_TARGET, actionTypeToTapTarget(actionType));
sendBroadcast(context, intent);
}
@VisibleForTesting
void sendBroadcast(final Context context, final Intent intent) {
intent.setPackage(context.getString(R.string.config_settingsintelligence_package_name));
final String action = context.getString(R.string.config_settingsintelligence_log_action);
if (!TextUtils.isEmpty(action)) {
intent.setAction(action);
context.sendBroadcast(intent);
}
}
private int actionTypeToTapTarget(int actionType) {
switch (actionType) {
case EventInfo.ACTION_TYPE_CONTENT:
return TARGET_TITLE;
case EventInfo.ACTION_TYPE_TOGGLE:
return TARGET_TOGGLE;
case EventInfo.ACTION_TYPE_SLIDER:
return TARGET_SLIDER;
default:
Log.w(TAG, "unknown type " + actionType);
return TARGET_DEFAULT;
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.homepage.contextualcards;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
import com.android.settings.R;
public class ContextualCardFeedbackDialog extends AlertActivity implements
DialogInterface.OnClickListener {
public static final String EXTRA_CARD_NAME = "card_name";
public static final String EXTRA_FEEDBACK_EMAIL = "feedback_email";
private static final String TAG = "CardFeedbackDialog";
private static final String SUBJECT = "Settings Contextual Card Feedback - ";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final AlertController.AlertParams alertParams = mAlertParams;
alertParams.mMessage = getText(R.string.contextual_card_feedback_confirm_message);
alertParams.mPositiveButtonText = getText(R.string.contextual_card_feedback_send);
alertParams.mPositiveButtonListener = this;
alertParams.mNegativeButtonText = getText(R.string.skip_label);
setupAlert();
}
@Override
public void onClick(DialogInterface dialog, int which) {
final String cardName = getIntent().getStringExtra(EXTRA_CARD_NAME);
final String email = getIntent().getStringExtra(EXTRA_FEEDBACK_EMAIL);
final Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + email));
intent.putExtra(Intent.EXTRA_SUBJECT, SUBJECT + cardName);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (Exception e) {
Log.e(TAG, "Send feedback failed.", e);
}
finish();
}
}

View File

@@ -34,8 +34,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.slice.Slice;
import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
import com.android.settings.wifi.WifiSlice;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settingslib.utils.AsyncLoaderCompat;
import java.util.ArrayList;
@@ -170,8 +169,8 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
private int getNumberOfLargeCard(List<ContextualCard> cards) {
return (int) cards.stream()
.filter(card -> card.getSliceUri().equals(WifiSlice.WIFI_URI)
|| card.getSliceUri().equals(ConnectedDeviceSlice.CONNECTED_DEVICE_URI))
.filter(card -> card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI)
|| card.getSliceUri().equals(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI))
.count();
}

View File

@@ -40,6 +40,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
/**
@@ -132,8 +133,13 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
// except Conditional cards, all other cards are from the database. So when the map sent
// here is empty, we only keep Conditional cards.
if (cardTypes.isEmpty()) {
final Set<Integer> conditionalCardTypes = new TreeSet() {{
add(ContextualCard.CardType.CONDITIONAL);
add(ContextualCard.CardType.CONDITIONAL_HEADER);
add(ContextualCard.CardType.CONDITIONAL_FOOTER);
}};
cardsToKeep = mContextualCards.stream()
.filter(card -> card.getCardType() == ContextualCard.CardType.CONDITIONAL)
.filter(card -> conditionalCardTypes.contains(card.getCardType()))
.collect(Collectors.toList());
} else {
cardsToKeep = mContextualCards.stream()

View File

@@ -16,16 +16,11 @@
package com.android.settings.homepage.contextualcards;
import static android.provider.SettingsSlicesContract.KEY_WIFI;
import android.annotation.Nullable;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
import com.android.settings.intelligence.ContextualCardProto.ContextualCard;
import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
import com.android.settings.wifi.WifiSlice;
import com.android.settings.slices.CustomSliceRegistry;
import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
@@ -39,26 +34,26 @@ public class SettingsContextualCardProvider extends ContextualCardProvider {
public ContextualCardList getContextualCards() {
final ContextualCard wifiCard =
ContextualCard.newBuilder()
.setSliceUri(WifiSlice.WIFI_URI.toString())
.setCardName(KEY_WIFI)
.setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI.toString())
.setCardName(CustomSliceRegistry.WIFI_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard connectedDeviceCard =
ContextualCard.newBuilder()
.setSliceUri(ConnectedDeviceSlice.CONNECTED_DEVICE_URI.toString())
.setCardName(ConnectedDeviceSlice.PATH_CONNECTED_DEVICE)
.setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
.setCardName(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard lowStorageCard =
ContextualCard.newBuilder()
.setSliceUri(LowStorageSlice.LOW_STORAGE_URI.toString())
.setCardName(LowStorageSlice.PATH_LOW_STORAGE)
.setSliceUri(CustomSliceRegistry.LOW_STORAGE_SLICE_URI.toString())
.setCardName(CustomSliceRegistry.LOW_STORAGE_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard batteryFixCard =
ContextualCard.newBuilder()
.setSliceUri(BatteryFixSlice.BATTERY_FIX_URI.toString())
.setCardName(BatteryFixSlice.PATH_BATTERY_FIX)
.setSliceUri(CustomSliceRegistry.BATTERY_FIX_SLICE_URI.toString())
.setCardName(CustomSliceRegistry.BATTERY_FIX_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCardList cards = ContextualCardList.newBuilder()

View File

@@ -98,25 +98,12 @@ public class DndConditionCardController implements ConditionalCardController {
.setName(mAppContext.getPackageName() + "/"
+ mAppContext.getText(R.string.condition_zen_title))
.setTitleText(mAppContext.getText(R.string.condition_zen_title).toString())
.setSummaryText(getSummary().toString())
.setSummaryText(mAppContext.getText(R.string.condition_zen_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp))
.setIsHalfWidth(true)
.build();
}
public CharSequence getSummary() {
final int zen = mNotificationManager.getZenMode();
final ZenModeConfig config;
boolean zenModeEnabled = zen != Settings.Global.ZEN_MODE_OFF;
if (zenModeEnabled) {
config = mNotificationManager.getZenModeConfig();
} else {
config = null;
}
return ZenModeConfig.getDescription(mAppContext, zen != Settings.Global.ZEN_MODE_OFF,
config, true);
}
public class Receiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

View File

@@ -16,8 +16,9 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
import static com.android.settings.slices.CustomSliceRegistry.BATTERY_INFO_SLICE_URI;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -37,7 +38,6 @@ import com.android.settings.Utils;
import com.android.settings.fuelgauge.BatteryInfo;
import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
/**
@@ -46,20 +46,6 @@ import com.android.settings.slices.SliceBuilderUtils;
public class BatterySlice implements CustomSliceable {
private static final String TAG = "BatterySlice";
/**
* The path denotes the unique name of battery slice.
*/
public static final String PATH_BATTERY_INFO = "battery_card";
/**
* Backing Uri for the Battery Slice.
*/
public static final Uri BATTERY_CARD_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_BATTERY_INFO)
.build();
private final Context mContext;
private BatteryInfo mBatteryInfo;
@@ -69,9 +55,6 @@ public class BatterySlice implements CustomSliceable {
mContext = context;
}
/**
* Return a {@link BatterySlice} bound to {@link #BATTERY_CARD_URI}
*/
@Override
public Slice getSlice() {
if (mBatteryInfo == null) {
@@ -81,8 +64,9 @@ public class BatterySlice implements CustomSliceable {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_settings_battery);
final CharSequence title = mContext.getText(R.string.power_usage_summary_title);
final SliceAction primarySliceAction = new SliceAction(getPrimaryAction(), icon, title);
final Slice slice = new ListBuilder(mContext, BATTERY_CARD_URI, ListBuilder.INFINITY)
final SliceAction primarySliceAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
ListBuilder.ICON_IMAGE, title);
final Slice slice = new ListBuilder(mContext, BATTERY_INFO_SLICE_URI, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
.addRow(new ListBuilder.RowBuilder()
@@ -97,7 +81,7 @@ public class BatterySlice implements CustomSliceable {
@Override
public Uri getUri() {
return BATTERY_CARD_URI;
return BATTERY_INFO_SLICE_URI;
}
@Override
@@ -108,12 +92,10 @@ public class BatterySlice implements CustomSliceable {
@Override
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.power_usage_summary_title).toString();
final Uri contentUri = new Uri.Builder().appendPath(PATH_BATTERY_INFO).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
PowerUsageSummary.class.getName(), PATH_BATTERY_INFO, screenTitle,
PowerUsageSummary.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
.setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
@Override

View File

@@ -17,7 +17,6 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -39,8 +38,8 @@ import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.datausage.DataUsageSummary;
import com.android.settings.datausage.DataUsageUtils;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.net.DataUsageController;
@@ -50,19 +49,6 @@ public class DataUsageSlice implements CustomSliceable {
private static final String TAG = "DataUsageSlice";
private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);
/**
* The path denotes the unique name of data usage slice.
*/
public static final String PATH_DATA_USAGE = "data_usage_card";
/**
* Backing Uri for the Data usage Slice.
*/
public static final Uri DATA_USAGE_CARD_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_DATA_USAGE)
.build();
private final Context mContext;
@@ -72,22 +58,21 @@ public class DataUsageSlice implements CustomSliceable {
@Override
public Uri getUri() {
return DATA_USAGE_CARD_URI;
return CustomSliceRegistry.DATA_USAGE_SLICE_URI;
}
/**
* Return a Data usage Slice bound to {@link #DATA_USAGE_CARD_URI}
*/
@Override
public Slice getSlice() {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_settings_data_usage);
final String title = mContext.getString(R.string.data_usage_summary_title);
final SliceAction primaryAction = new SliceAction(getPrimaryAction(), icon, title);
final SliceAction primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
ListBuilder.ICON_IMAGE, title);
final DataUsageController dataUsageController = new DataUsageController(mContext);
final DataUsageController.DataUsageInfo info = dataUsageController.getDataUsageInfo();
final ListBuilder listBuilder =
new ListBuilder(mContext, DATA_USAGE_CARD_URI, ListBuilder.INFINITY)
new ListBuilder(mContext, CustomSliceRegistry.DATA_USAGE_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.setHeader(new ListBuilder.HeaderBuilder().setTitle(title));
if (DataUsageUtils.hasSim(mContext)) {
@@ -106,12 +91,10 @@ public class DataUsageSlice implements CustomSliceable {
@Override
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.data_usage_wifi_title).toString();
final Uri contentUri = new Uri.Builder().appendPath(PATH_DATA_USAGE).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
DataUsageSummary.class.getName(), PATH_DATA_USAGE, screenTitle,
DataUsageSummary.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
.setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
private PendingIntent getPrimaryAction() {

View File

@@ -17,7 +17,6 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -39,8 +38,8 @@ import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.deviceinfo.DeviceModelPreferenceController;
import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.DeviceInfoUtils;
@@ -49,20 +48,6 @@ import java.util.List;
public class DeviceInfoSlice implements CustomSliceable {
private static final String TAG = "DeviceInfoSlice";
/**
* The path denotes the unique name of device info slice
*/
public static final String PATH_DEVICE_INFO = "device_info_card";
/**
* Backing Uri for the Device info Slice.
*/
public static final Uri DEVICE_INFO_CARD_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_DEVICE_INFO)
.build();
private final Context mContext;
private final SubscriptionManager mSubscriptionManager;
@@ -71,16 +56,15 @@ public class DeviceInfoSlice implements CustomSliceable {
mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
}
/**
* Return a device info slice bound to {@Link #DEVICE_INFO_CARD_URI}
*/
@Override
public Slice getSlice() {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_info_outline_24dp);
final String title = mContext.getString(R.string.device_info_label);
final SliceAction primaryAction = new SliceAction(getPrimaryAction(), icon, title);
return new ListBuilder(mContext, DEVICE_INFO_CARD_URI, ListBuilder.INFINITY)
final SliceAction primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
ListBuilder.ICON_IMAGE, title);
return new ListBuilder(mContext, CustomSliceRegistry.DEVICE_INFO_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor((Utils.getColorAccentDefaultColor(mContext)))
.setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
.addRow(new ListBuilder.RowBuilder()
@@ -92,18 +76,16 @@ public class DeviceInfoSlice implements CustomSliceable {
@Override
public Uri getUri() {
return DEVICE_INFO_CARD_URI;
return CustomSliceRegistry.DEVICE_INFO_SLICE_URI;
}
@Override
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.device_info_label).toString();
final Uri contentUri = new Uri.Builder().appendPath(PATH_DEVICE_INFO).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
MyDeviceInfoFragment.class.getName(), PATH_DEVICE_INFO, screenTitle,
MyDeviceInfoFragment.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
.setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
private PendingIntent getPrimaryAction() {

View File

@@ -17,10 +17,8 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
@@ -28,39 +26,27 @@ import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
import com.android.settings.R;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.CustomSliceRegistry;
// This is a slice helper class for EmergencyInfo
public class EmergencyInfoSlice {
/**
* The path denotes the unique name of emergency info slice.
*/
public static final String PATH_EMERGENCY_INFO_CARD = "emergency_info_card";
/**
* Backing Uri for the Emergency Info Slice.
*/
public static final Uri EMERGENCY_INFO_CARD_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_EMERGENCY_INFO_CARD)
.build();
private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
public static Slice getSlice(Context context) {
final ListBuilder listBuilder = new ListBuilder(context, EMERGENCY_INFO_CARD_URI,
final ListBuilder listBuilder = new ListBuilder(context,
CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI,
ListBuilder.INFINITY);
listBuilder.addRow(
new ListBuilder.RowBuilder()
.setTitle(context.getText(R.string.emergency_info_title))
.setSubtitle(
context.getText(R.string.emergency_info_contextual_card_summary))
.setPrimaryAction(generatePrimaryAction(context)));
.setPrimaryAction(createPrimaryAction(context)));
return listBuilder.build();
}
private static SliceAction generatePrimaryAction(Context context) {
private static SliceAction createPrimaryAction(Context context) {
PendingIntent pendingIntent =
PendingIntent.getActivity(
context,
@@ -68,10 +54,10 @@ public class EmergencyInfoSlice {
new Intent(ACTION_EDIT_EMERGENCY_INFO),
PendingIntent.FLAG_UPDATE_CURRENT);
return SliceAction.create(
return SliceAction.createDeeplink(
pendingIntent,
IconCompat.createWithResource(context, R.drawable.empty_icon),
ListBuilder.SMALL_IMAGE,
ListBuilder.ICON_IMAGE,
context.getText(R.string.emergency_info_title));
}
}

View File

@@ -17,7 +17,6 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -36,8 +35,8 @@ import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.deviceinfo.StorageDashboardFragment;
import com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
@@ -45,20 +44,6 @@ import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
public class StorageSlice implements CustomSliceable {
private static final String TAG = "StorageSlice";
/**
* The path denotes the unique name of storage slicel
*/
public static final String PATH_STORAGE_INFO = "storage_card";
/**
* Backing Uri for the storage slice.
*/
public static final Uri STORAGE_CARD_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_STORAGE_INFO)
.build();
private final Context mContext;
public StorageSlice(Context context) {
@@ -67,20 +52,19 @@ public class StorageSlice implements CustomSliceable {
@Override
public Uri getUri() {
return STORAGE_CARD_URI;
return CustomSliceRegistry.STORAGE_SLICE_URI;
}
/**
* Return a storage slice bound to {@link #STORAGE_CARD_URI}
*/
@Override
public Slice getSlice() {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_homepage_storage);
final String title = mContext.getString(R.string.storage_label);
final SliceAction primaryAction = new SliceAction(getPrimaryAction(), icon, title);
final SliceAction primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
ListBuilder.ICON_IMAGE, title);
final PrivateStorageInfo info = getPrivateStorageInfo();
return new ListBuilder(mContext, STORAGE_CARD_URI, ListBuilder.INFINITY)
return new ListBuilder(mContext, CustomSliceRegistry.STORAGE_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
.addRow(new ListBuilder.RowBuilder()
@@ -93,12 +77,10 @@ public class StorageSlice implements CustomSliceable {
@Override
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.storage_label).toString();
final Uri contentUri = new Uri.Builder().appendPath(PATH_STORAGE_INFO).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
StorageDashboardFragment.class.getName(), PATH_STORAGE_INFO, screenTitle,
StorageDashboardFragment.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
.setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
private PendingIntent getPrimaryAction() {

View File

@@ -19,7 +19,6 @@ package com.android.settings.homepage.contextualcards.slices;
import static android.content.Context.MODE_PRIVATE;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -34,7 +33,6 @@ import androidx.slice.builders.ListBuilder.RowBuilder;
import androidx.slice.builders.SliceAction;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.SubSettings;
@@ -42,9 +40,10 @@ import com.android.settings.Utils;
import com.android.settings.fuelgauge.BatteryStatsHelperLoader;
import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.fuelgauge.batterytip.BatteryTipLoader;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.utils.ThreadUtils;
@@ -53,20 +52,6 @@ import java.util.List;
public class BatteryFixSlice implements CustomSliceable {
/**
* Unique name of Battery Fix Slice.
*/
public static final String PATH_BATTERY_FIX = "battery_fix";
/**
* Uri for Battery Fix Slice.
*/
public static final Uri BATTERY_FIX_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_BATTERY_FIX)
.build();
@VisibleForTesting
static final String PREFS = "battery_fix_prefs";
@VisibleForTesting
@@ -82,12 +67,9 @@ public class BatteryFixSlice implements CustomSliceable {
@Override
public Uri getUri() {
return BATTERY_FIX_URI;
return CustomSliceRegistry.BATTERY_FIX_SLICE_URI;
}
/**
* Return a Slice bound to {@link #BATTERY_FIX_URI}.
*/
@Override
public Slice getSlice() {
IconCompat icon;
@@ -106,10 +88,12 @@ public class BatteryFixSlice implements CustomSliceable {
for (BatteryTip batteryTip : batteryTips) {
if (batteryTip.getState() != BatteryTip.StateType.INVISIBLE) {
icon = IconCompat.createWithResource(mContext, batteryTip.getIconId());
primaryAction = new SliceAction(getPrimaryAction(),
primaryAction = SliceAction.createDeeplink(getPrimaryAction(),
icon,
ListBuilder.ICON_IMAGE,
batteryTip.getTitle(mContext));
slice = new ListBuilder(mContext, BATTERY_FIX_URI, ListBuilder.INFINITY)
slice = new ListBuilder(mContext, CustomSliceRegistry.BATTERY_FIX_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(new RowBuilder()
.setTitle(batteryTip.getTitle(mContext))
@@ -124,8 +108,10 @@ public class BatteryFixSlice implements CustomSliceable {
icon = IconCompat.createWithResource(mContext,
R.drawable.ic_battery_status_good_24dp);
final String title = mContext.getString(R.string.power_usage_summary_title);
primaryAction = new SliceAction(getPrimaryAction(), icon, title);
slice = new ListBuilder(mContext, BATTERY_FIX_URI, ListBuilder.INFINITY)
primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
ListBuilder.ICON_IMAGE, title);
slice = new ListBuilder(mContext, CustomSliceRegistry.BATTERY_FIX_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(new RowBuilder()
.setTitle(title)
@@ -140,10 +126,11 @@ public class BatteryFixSlice implements CustomSliceable {
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.power_usage_summary_title)
.toString();
final Uri contentUri = new Uri.Builder().appendPath(PATH_BATTERY_FIX).build();
final Uri contentUri = new Uri.Builder()
.appendPath(BatteryTipPreferenceController.PREF_NAME).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
PowerUsageSummary.class.getName(), PATH_BATTERY_FIX,
PowerUsageSummary.class.getName(), BatteryTipPreferenceController.PREF_NAME,
screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())

View File

@@ -18,7 +18,6 @@ package com.android.settings.homepage.contextualcards.slices;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -43,8 +42,8 @@ import com.android.settings.Utils;
import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -67,20 +66,6 @@ import java.util.stream.Collectors;
*/
public class ConnectedDeviceSlice implements CustomSliceable {
/**
* The path denotes the unique name of Connected device Slice.
*/
public static final String PATH_CONNECTED_DEVICE = "connected_device";
/**
* Backing Uri for Connected device Slice.
*/
public static final Uri CONNECTED_DEVICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_CONNECTED_DEVICE)
.build();
/**
* To sort the Bluetooth devices by {@link CachedBluetoothDevice}.
* Refer compareTo method from {@link com.android.settings.bluetooth.BluetoothDevicePreference}.
@@ -109,12 +94,9 @@ public class ConnectedDeviceSlice implements CustomSliceable {
@Override
public Uri getUri() {
return CONNECTED_DEVICE_URI;
return CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI;
}
/**
* Return a Connected Device Slice bound to {@link #CONNECTED_DEVICE_URI}.
*/
@Override
public Slice getSlice() {
final IconCompat icon = IconCompat.createWithResource(mContext,
@@ -124,10 +106,11 @@ public class ConnectedDeviceSlice implements CustomSliceable {
R.string.no_connected_devices);
final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext, 0,
getIntent(), 0);
final SliceAction primarySliceAction = new SliceAction(primaryActionIntent, icon,
title);
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryActionIntent, icon,
ListBuilder.ICON_IMAGE, title);
final ListBuilder listBuilder =
new ListBuilder(mContext, CONNECTED_DEVICE_URI, ListBuilder.INFINITY)
new ListBuilder(mContext, CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
// Get row builders by connected devices, e.g. Bluetooth.
@@ -159,14 +142,12 @@ public class ConnectedDeviceSlice implements CustomSliceable {
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.connected_devices_dashboard_title)
.toString();
final Uri contentUri = new Uri.Builder().appendPath(PATH_CONNECTED_DEVICE).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
ConnectedDeviceDashboardFragment.class.getName(), PATH_CONNECTED_DEVICE,
ConnectedDeviceDashboardFragment.class.getName(), "" /* key */,
screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
.setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
@Override
@@ -251,9 +232,10 @@ public class ConnectedDeviceSlice implements CustomSliceable {
}
private SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
return new SliceAction(
return SliceAction.createDeeplink(
getBluetoothDetailIntent(bluetoothDevice),
IconCompat.createWithResource(mContext, R.drawable.ic_settings),
ListBuilder.ICON_IMAGE,
bluetoothDevice.getName());
}

View File

@@ -17,7 +17,6 @@
package com.android.settings.homepage.contextualcards.slices;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -36,8 +35,8 @@ import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.deviceinfo.StorageSettings;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
@@ -46,20 +45,6 @@ import java.text.NumberFormat;
public class LowStorageSlice implements CustomSliceable {
/**
* The path denotes the unique name of Low storage Slice.
*/
public static final String PATH_LOW_STORAGE = "low_storage";
/**
* Backing Uri for Low storage Slice.
*/
public static final Uri LOW_STORAGE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_LOW_STORAGE)
.build();
private static final String TAG = "LowStorageSlice";
/**
@@ -73,9 +58,6 @@ public class LowStorageSlice implements CustomSliceable {
mContext = context;
}
/**
* Return a Low storage Slice bound to {@link #LOW_STORAGE_URI}
*/
@Override
public Slice getSlice() {
// Get current storage percentage from StorageManager.
@@ -97,8 +79,9 @@ public class LowStorageSlice implements CustomSliceable {
// Show Low storage Slice.
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
final CharSequence title = mContext.getText(R.string.storage_menu_free);
final SliceAction primarySliceAction = new SliceAction(
PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon, title);
final SliceAction primarySliceAction = SliceAction.createDeeplink(
PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon,
ListBuilder.ICON_IMAGE, title);
final String lowStorageSummary = mContext.getString(R.string.low_storage_summary,
NumberFormat.getPercentInstance().format(currentStoragePercentage),
Formatter.formatFileSize(mContext, info.freeBytes));
@@ -108,7 +91,8 @@ public class LowStorageSlice implements CustomSliceable {
* Slices doesn't support "Icon on the left" in header. Now we intend to start with Icon
* right aligned. Will update the icon to left until Slices support it.
*/
return new ListBuilder(mContext, LOW_STORAGE_URI, ListBuilder.INFINITY)
return new ListBuilder(mContext, CustomSliceRegistry.LOW_STORAGE_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(new RowBuilder()
.setTitle(title)
@@ -120,7 +104,7 @@ public class LowStorageSlice implements CustomSliceable {
@Override
public Uri getUri() {
return LOW_STORAGE_URI;
return CustomSliceRegistry.LOW_STORAGE_SLICE_URI;
}
@Override
@@ -132,13 +116,11 @@ public class LowStorageSlice implements CustomSliceable {
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.storage_label)
.toString();
final Uri contentUri = new Uri.Builder().appendPath(PATH_LOW_STORAGE).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
StorageSettings.class.getName(), PATH_LOW_STORAGE,
StorageSettings.class.getName(), "" /* key */,
screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
.setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
}

View File

@@ -17,12 +17,19 @@
package com.android.settings.homepage.contextualcards.slices;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import com.android.settings.homepage.contextualcards.CardContentProvider;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
import com.android.settings.homepage.contextualcards.ContextualCard;
import com.android.settings.homepage.contextualcards.ContextualCardController;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.homepage.contextualcards.ContextualCardFeedbackDialog;
import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.utils.ThreadUtils;
/**
@@ -32,7 +39,8 @@ public class SliceContextualCardController implements ContextualCardController {
private static final String TAG = "SliceCardController";
private Context mContext;
private final Context mContext;
private ContextualCardUpdateListener mCardUpdateListener;
public SliceContextualCardController(Context context) {
@@ -51,7 +59,7 @@ public class SliceContextualCardController implements ContextualCardController {
@Override
public void onActionClick(ContextualCard card) {
//TODO(b/113783548): Implement feedback mechanism
}
@Override
@@ -60,10 +68,33 @@ public class SliceContextualCardController implements ContextualCardController {
final CardDatabaseHelper dbHelper = CardDatabaseHelper.getInstance(mContext);
dbHelper.markContextualCardAsDismissed(mContext, card.getName());
});
showFeedbackDialog(card);
final ContextualCardFeatureProvider contexualCardFeatureProvider =
FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
contexualCardFeatureProvider.logContextualCardDismiss(mContext, card);
}
@Override
public void setCardUpdateListener(ContextualCardUpdateListener listener) {
mCardUpdateListener = listener;
}
@VisibleForTesting
void showFeedbackDialog(ContextualCard card) {
final String email = mContext.getString(R.string.config_contextual_card_feedback_email);
if (TextUtils.isEmpty(email)) {
return;
}
final Intent feedbackIntent = new Intent(mContext, ContextualCardFeedbackDialog.class);
feedbackIntent.putExtra(ContextualCardFeedbackDialog.EXTRA_CARD_NAME,
getSimpleCardName(card));
feedbackIntent.putExtra(ContextualCardFeedbackDialog.EXTRA_FEEDBACK_EMAIL, email);
feedbackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(feedbackIntent);
}
private String getSimpleCardName(ContextualCard card) {
final String[] split = card.getName().split("/");
return split[split.length - 1];
}
}

View File

@@ -20,6 +20,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -38,10 +39,13 @@ import androidx.slice.widget.SliceView;
import com.android.settings.R;
import com.android.settings.homepage.contextualcards.ContextualCard;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.homepage.contextualcards.ContextualCardRenderer;
import com.android.settings.homepage.contextualcards.ControllerRendererPool;
import com.android.settings.overlay.FeatureFactory;
import java.util.Map;
import java.util.Set;
/**
* Card renderer for {@link ContextualCard} built as slices.
@@ -58,6 +62,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
private final Context mContext;
private final LifecycleOwner mLifecycleOwner;
private final ControllerRendererPool mControllerRendererPool;
private final Set<ContextualCard> mCardSet;
public SliceContextualCardRenderer(Context context, LifecycleOwner lifecycleOwner,
ControllerRendererPool controllerRendererPool) {
@@ -65,6 +70,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
mLifecycleOwner = lifecycleOwner;
mSliceLiveDataMap = new ArrayMap<>();
mControllerRendererPool = controllerRendererPool;
mCardSet = new ArraySet<>();
}
@Override
@@ -99,6 +105,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
sliceLiveData = SliceLiveData.fromUri(mContext, uri);
mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
}
mCardSet.add(card);
sliceLiveData.removeObservers(mLifecycleOwner);
sliceLiveData.observe(mLifecycleOwner, slice -> {
@@ -128,14 +135,27 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
final Button btnRemove = cardHolder.itemView.findViewById(R.id.remove);
btnRemove.setOnClickListener(v -> {
mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(
card);
mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(card);
});
}
@Override
public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) {
//TODO(b/79698338): Log user interaction
// sliceItem.getSlice().getUri() is like
// content://android.settings.slices/action/wifi/_gen/0/_gen/0
// contextualCard.getSliceUri() is prefix of sliceItem.getSlice().getUri()
for (ContextualCard card : mCardSet) {
if (sliceItem.getSlice().getUri().toString().startsWith(
card.getSliceUri().toString())) {
ContextualCardFeatureProvider contexualCardFeatureProvider =
FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
contexualCardFeatureProvider.logContextualCardClick(mContext, card,
eventInfo.rowIndex, eventInfo.actionType);
break;
}
}
}
public static class SliceViewHolder extends RecyclerView.ViewHolder {

View File

@@ -23,11 +23,9 @@ import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
@@ -39,6 +37,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBuilderUtils;
/**
@@ -46,21 +45,11 @@ import com.android.settings.slices.SliceBuilderUtils;
*/
public class LocationSliceBuilder {
/**
* Backing Uri for the Location Slice.
*/
public static final Uri LOCATION_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(KEY_LOCATION)
.build();
private LocationSliceBuilder() {
}
/**
* Return a Location Slice bound to {@link #LOCATION_URI}.
* Return a Location Slice bound to {@link CustomSliceRegistry#LOCATION_SLICE_URI}.
*/
public static Slice getSlice(Context context) {
final IconCompat icon = IconCompat.createWithResource(context,
@@ -68,9 +57,11 @@ public class LocationSliceBuilder {
final String title = context.getString(R.string.location_settings_title);
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final PendingIntent primaryAction = getPrimaryAction(context);
final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
ListBuilder.ICON_IMAGE, title);
return new ListBuilder(context, LOCATION_URI, ListBuilder.INFINITY)
return new ListBuilder(context, CustomSliceRegistry.LOCATION_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)

View File

@@ -19,7 +19,6 @@ package com.android.settings.network.telephony;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -40,9 +39,8 @@ import androidx.slice.builders.SliceAction;
import com.android.ims.ImsManager;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
@@ -57,12 +55,7 @@ import java.util.concurrent.TimeoutException;
*/
public class Enhanced4gLteSliceHelper {
private static final String TAG = "Enhanced4gLteSliceHelper";
/**
* Settings slice path to enhanced 4g LTE setting.
*/
public static final String PATH_ENHANCED_4G_LTE = "enhanced_4g_lte";
private static final String TAG = "Enhanced4gLteSlice";
/**
* Action passed for changes to enhanced 4g LTE slice (toggle).
@@ -70,14 +63,6 @@ public class Enhanced4gLteSliceHelper {
public static final String ACTION_ENHANCED_4G_LTE_CHANGED =
"com.android.settings.mobilenetwork.action.ENHANCED_4G_LTE_CHANGED";
/**
* Slice Uri for Enhanced 4G slice
*/
public static final Uri SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_ENHANCED_4G_LTE)
.build();
/**
* Action for mobile network settings activity which
* allows setting configuration for Enhanced 4G LTE
@@ -107,7 +92,7 @@ public class Enhanced4gLteSliceHelper {
* Enhanced 4g lte mode title variant resource name
*/
private static final String RESOURCE_ENHANCED_4G_LTE_MODE_TITLE_VARIANT =
"enhanced_4g_lte_mode_title_variant";
"enhanced_4g_lte_mode_title_variant";
@VisibleForTesting
public Enhanced4gLteSliceHelper(Context context) {
@@ -187,13 +172,15 @@ public class Enhanced4gLteSliceHelper {
.addRow(new RowBuilder()
.setTitle(getEnhanced4glteModeTitle(subId))
.addEndItem(
new SliceAction(
SliceAction.createToggle(
getBroadcastIntent(ACTION_ENHANCED_4G_LTE_CHANGED),
null /* actionTitle */, isEnhanced4gLteEnabled))
.setPrimaryAction(new SliceAction(
getActivityIntent(ACTION_MOBILE_NETWORK_SETTINGS_ACTIVITY),
icon,
getEnhanced4glteModeTitle(subId))))
.setPrimaryAction(
SliceAction.createDeeplink(
getActivityIntent(ACTION_MOBILE_NETWORK_SETTINGS_ACTIVITY),
icon,
ListBuilder.ICON_IMAGE,
getEnhanced4glteModeTitle(subId))))
.build();
}
@@ -225,8 +212,7 @@ public class Enhanced4gLteSliceHelper {
}
// notify change in slice in any case to get re-queried. This would result in displaying
// appropriate message with the updated setting.
final Uri uri = SliceBuilderUtils.getUri(PATH_ENHANCED_4G_LTE, false /*isPlatformSlice*/);
mContext.getContentResolver().notifyChange(uri, null);
mContext.getContentResolver().notifyChange(CustomSliceRegistry.ENHANCED_4G_SLICE_URI, null);
}
private CharSequence getEnhanced4glteModeTitle(int subId) {

View File

@@ -35,6 +35,9 @@ import com.android.settingslib.core.lifecycle.events.OnResume;
public class ZenModePreferenceController extends BasePreferenceController
implements LifecycleObserver, OnResume, OnPause {
public static final String ZEN_MODE_KEY = "zen_mode";
private SettingObserver mSettingObserver;
private ZenModeSettings.SummaryBuilder mSummaryBuilder;

View File

@@ -18,16 +18,16 @@ package com.android.settings.notification;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static com.android.settings.notification.ZenModePreferenceController.ZEN_MODE_KEY;
import android.annotation.ColorInt;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.provider.Settings;
import android.provider.SettingsSlicesContract;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
@@ -39,7 +39,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
@@ -47,18 +47,6 @@ public class ZenModeSliceBuilder {
private static final String TAG = "ZenModeSliceBuilder";
private static final String ZEN_MODE_KEY = "zen_mode";
/**
* Backing Uri for the Zen Mode Slice.
*/
public static final Uri ZEN_MODE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(ZEN_MODE_KEY)
.build();
/**
* Action notifying a change on the Zen Mode Slice.
*/
@@ -77,7 +65,7 @@ public class ZenModeSliceBuilder {
}
/**
* Return a ZenMode Slice bound to {@link #ZEN_MODE_URI}.
* Return a ZenMode Slice bound to {@link CustomSliceRegistry#ZEN_MODE_URI}.
* <p>
* Note that you should register a listener for {@link #INTENT_FILTER} to get changes for
* ZenMode.
@@ -88,12 +76,13 @@ public class ZenModeSliceBuilder {
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final PendingIntent toggleAction = getBroadcastIntent(context);
final PendingIntent primaryAction = getPrimaryAction(context);
final SliceAction primarySliceAction = new SliceAction(primaryAction,
(IconCompat) null /* icon */, title);
final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction,
(IconCompat) null /* icon */, ListBuilder.ICON_IMAGE, title);
final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction, null /* actionTitle */,
isZenModeEnabled);
return new ListBuilder(context, ZEN_MODE_URI, ListBuilder.INFINITY)
return new ListBuilder(context, CustomSliceRegistry.ZEN_MODE_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)

View File

@@ -28,6 +28,7 @@ import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.gestures.AssistGestureFeatureProvider;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.localepicker.LocaleFeatureProvider;
import com.android.settings.panel.PanelFeatureProvider;
import com.android.settings.search.SearchFeatureProvider;
@@ -108,6 +109,8 @@ public abstract class FeatureFactory {
public abstract PanelFeatureProvider getPanelFeatureProvider();
public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider();
public static final class FactoryNotFoundException extends RuntimeException {
public FactoryNotFoundException(Throwable throwable) {
super("Unable to create factory. Did you misconfigure Proguard?", throwable);

View File

@@ -40,6 +40,8 @@ import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.fuelgauge.PowerUsageFeatureProviderImpl;
import com.android.settings.gestures.AssistGestureFeatureProvider;
import com.android.settings.gestures.AssistGestureFeatureProviderImpl;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProviderImpl;
import com.android.settings.localepicker.LocaleFeatureProvider;
import com.android.settings.localepicker.LocaleFeatureProviderImpl;
import com.android.settings.panel.PanelFeatureProvider;
@@ -75,6 +77,7 @@ public class FeatureFactoryImpl extends FeatureFactory {
private SlicesFeatureProvider mSlicesFeatureProvider;
private AccountFeatureProvider mAccountFeatureProvider;
private PanelFeatureProvider mPanelFeatureProvider;
private ContextualCardFeatureProvider mContextualCardFeatureProvider;
@Override
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -220,4 +223,11 @@ public class FeatureFactoryImpl extends FeatureFactory {
}
return mPanelFeatureProvider;
}
public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
if (mContextualCardFeatureProvider == null) {
mContextualCardFeatureProvider = new ContextualCardFeatureProviderImpl();
}
return mContextualCardFeatureProvider;
}
}

View File

@@ -16,16 +16,13 @@
package com.android.settings.panel;
import androidx.annotation.VisibleForTesting;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.wifi.WifiSlice;
import com.android.settings.slices.CustomSliceRegistry;
import java.util.ArrayList;
import java.util.List;
@@ -34,19 +31,11 @@ import java.util.List;
* Represents the Internet Connectivity Panel.
*
* <p>
* Displays Wifi (full Slice) and Airplane mode.
* Displays Wifi (full Slice) and Airplane mode.
* </p>
*/
public class InternetConnectivityPanel implements PanelContent {
@VisibleForTesting
static final Uri AIRPLANE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
.build();
private final Context mContext;
public static InternetConnectivityPanel create(Context context) {
@@ -65,13 +54,13 @@ public class InternetConnectivityPanel implements PanelContent {
@Override
public List<Uri> getSlices() {
final List<Uri> uris = new ArrayList<>();
uris.add(WifiSlice.WIFI_URI);
uris.add(AIRPLANE_URI);
uris.add(CustomSliceRegistry.WIFI_SLICE_URI);
uris.add(CustomSliceRegistry.AIRPLANE_URI);
return uris;
}
@Override
public Intent getSeeMoreIntent() {
return null;
return new Intent(Settings.ACTION_WIRELESS_SETTINGS);
}
}

View File

@@ -16,19 +16,20 @@
package com.android.settings.panel;
import android.net.Uri;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Button;
import android.widget.TextView;
import androidx.lifecycle.LiveData;
import androidx.slice.Slice;
import androidx.slice.widget.SliceLiveData;
import androidx.slice.widget.SliceView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import androidx.annotation.NonNull;
@@ -38,20 +39,24 @@ import androidx.fragment.app.FragmentActivity;
import com.android.settings.overlay.FeatureFactory;
import java.util.ArrayList;
import java.util.List;
public class PanelFragment extends Fragment {
private static final String TAG = "PanelFragment";
private List<SliceView> mSliceViewList;
private List<LiveData<Slice>> mSliceDataList;
private LinearLayout mPanelLayout;
private TextView mTitleView;
private Button mSeeMoreButton;
private Button mDoneButton;
private RecyclerView mPanelSlices;
@VisibleForTesting
PanelSlicesAdapter mAdapter;
private View.OnClickListener mDoneButtonListener = (v) -> {
Log.d(TAG, "Closing dialog");
getActivity().finish();
};
public PanelFragment() {
mSliceViewList = new ArrayList<>();
mSliceDataList = new ArrayList<>();
}
@Nullable
@@ -61,28 +66,37 @@ public class PanelFragment extends Fragment {
final FragmentActivity activity = getActivity();
final View view = inflater.inflate(R.layout.panel_layout, container, false);
mPanelLayout = view.findViewById(R.id.panel_parent_layout);
final Bundle arguments = getArguments();
mPanelSlices = view.findViewById(R.id.panel_parent_layout);
mSeeMoreButton = view.findViewById(R.id.see_more);
mDoneButton = view.findViewById(R.id.done);
mTitleView = view.findViewById(R.id.title);
final Bundle arguments = getArguments();
final String panelType = arguments.getString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT);
final PanelContent panel = FeatureFactory.getFactory(activity)
.getPanelFeatureProvider()
.getPanel(activity, panelType);
activity.setTitle(panel.getTitle());
mAdapter = new PanelSlicesAdapter(this, panel.getSlices());
mPanelSlices.setHasFixedSize(true);
mPanelSlices.setLayoutManager(new LinearLayoutManager((activity)));
mPanelSlices.setAdapter(mAdapter);
for (Uri uri : panel.getSlices()) {
final SliceView sliceView = new SliceView(activity);
mPanelLayout.addView(sliceView);
final LiveData<Slice> liveData = SliceLiveData.fromUri(activity, uri);
liveData.observe(this /* lifecycleOwner */, sliceView);
mTitleView.setText(panel.getTitle());
mSliceDataList.add(liveData);
mSliceViewList.add(sliceView);
}
mSeeMoreButton.setOnClickListener(getSeeMoreListener(panel.getSeeMoreIntent()));
mDoneButton.setOnClickListener(mDoneButtonListener);
return view;
}
private View.OnClickListener getSeeMoreListener(final Intent intent) {
return (v) -> {
final FragmentActivity activity = getActivity();
activity.startActivity(intent);
activity.finish();
};
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.panel;
import android.content.Context;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.LiveData;
import androidx.recyclerview.widget.RecyclerView;
import androidx.slice.Slice;
import androidx.slice.widget.SliceLiveData;
import androidx.slice.widget.SliceView;
import com.android.settings.R;
import java.util.ArrayList;
import java.util.List;
/**
* RecyclerView adapter for Slices in Settings Panels.
*/
public class PanelSlicesAdapter
extends RecyclerView.Adapter<PanelSlicesAdapter.SliceRowViewHolder> {
private final List<Uri> mSliceUris;
private final PanelFragment mPanelFragment;
public PanelSlicesAdapter(PanelFragment fragment, List<Uri> sliceUris) {
mPanelFragment = fragment;
mSliceUris = new ArrayList<>(sliceUris);
}
@NonNull
@Override
public SliceRowViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
final Context context = viewGroup.getContext();
final LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(R.layout.panel_slice_row, viewGroup, false);
return new SliceRowViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull SliceRowViewHolder sliceRowViewHolder, int position) {
sliceRowViewHolder.onBind(mPanelFragment, mSliceUris.get(position));
}
@Override
public int getItemCount() {
return mSliceUris.size();
}
@VisibleForTesting
List<Uri> getData() {
return mSliceUris;
}
/**
* ViewHolder for binding Slices to SliceViews.
*/
public static class SliceRowViewHolder extends RecyclerView.ViewHolder {
@VisibleForTesting
LiveData<Slice> sliceLiveData;
@VisibleForTesting
final SliceView sliceView;
public SliceRowViewHolder(View view) {
super(view);
sliceView = view.findViewById(R.id.slice_view);
sliceView.setMode(SliceView.MODE_LARGE);
}
public void onBind(PanelFragment fragment, Uri sliceUri) {
final Context context = sliceView.getContext();
sliceLiveData = SliceLiveData.fromUri(context, sliceUri);
sliceLiveData.observe(fragment.getViewLifecycleOwner(), sliceView);
}
}
}

View File

@@ -68,8 +68,10 @@ public interface SearchFeatureProvider {
if (activity == null || toolbar == null) {
return;
}
if (!Utils.isPackageEnabled(activity, getSettingsIntelligencePkgName(activity))) {
final ViewGroup parent = (ViewGroup)toolbar.getParent();
if (!Utils.isDeviceProvisioned(activity) ||
!Utils.isPackageEnabled(activity, getSettingsIntelligencePkgName(activity))) {
final ViewGroup parent = (ViewGroup) toolbar.getParent();
if (parent != null) {
parent.setVisibility(View.GONE);
}

View File

@@ -101,13 +101,13 @@ public class CustomSliceManager {
}
private void addSlices() {
mUriMap.put(WifiSlice.WIFI_URI, WifiSlice.class);
mUriMap.put(DataUsageSlice.DATA_USAGE_CARD_URI, DataUsageSlice.class);
mUriMap.put(DeviceInfoSlice.DEVICE_INFO_CARD_URI, DeviceInfoSlice.class);
mUriMap.put(StorageSlice.STORAGE_CARD_URI, StorageSlice.class);
mUriMap.put(BatterySlice.BATTERY_CARD_URI, BatterySlice.class);
mUriMap.put(ConnectedDeviceSlice.CONNECTED_DEVICE_URI, ConnectedDeviceSlice.class);
mUriMap.put(LowStorageSlice.LOW_STORAGE_URI, LowStorageSlice.class);
mUriMap.put(BatteryFixSlice.BATTERY_FIX_URI, BatteryFixSlice.class);
mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatterySlice.class);
mUriMap.put(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI, ConnectedDeviceSlice.class);
mUriMap.put(CustomSliceRegistry.DATA_USAGE_SLICE_URI, DataUsageSlice.class);
mUriMap.put(CustomSliceRegistry.DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
mUriMap.put(CustomSliceRegistry.LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
mUriMap.put(CustomSliceRegistry.STORAGE_SLICE_URI, StorageSlice.class);
mUriMap.put(CustomSliceRegistry.WIFI_SLICE_URI, WifiSlice.class);
}
}

View File

@@ -0,0 +1,184 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.slices;
import static android.provider.SettingsSlicesContract.KEY_LOCATION;
import static android.provider.SettingsSlicesContract.KEY_WIFI;
import static com.android.settings.notification.ZenModePreferenceController.ZEN_MODE_KEY;
import android.content.ContentResolver;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
/**
* A registry of custom slice Uris.
*/
public class CustomSliceRegistry {
/**
* Uri for Airplane mode Slice.
*/
public static final Uri AIRPLANE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
.build();
/**
* Uri for Battery Fix Slice.
*/
public static final Uri BATTERY_FIX_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
.appendPath(BatteryTipPreferenceController.PREF_NAME)
.build();
/**
* Backing Uri for the Battery info Slice.
*/
public static final Uri BATTERY_INFO_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
.appendPath("battery_card")
.build();
/**
* Backing Uri for the Bluetooth Slice.
*/
public static final Uri BLUETOOTH_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(SettingsSlicesContract.KEY_BLUETOOTH)
.build();
/**
* Backing Uri for Connected device Slice.
*/
public static final Uri CONNECTED_DEVICE_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath("connected_device")
.build();
/**
* Backing Uri for the Data usage Slice.
*/
public static final Uri DATA_USAGE_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath("data_usage_card")
.build();
/**
* Backing Uri for the Device info Slice.
*/
public static final Uri DEVICE_INFO_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath("device_info_card")
.build();
/**
* Backing Uri for the Emergency Info Slice.
*/
public static final Uri EMERGENCY_INFO_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath("emergency_info_card")
.build();
/**
* Slice Uri for Enhanced 4G slice
*/
public static final Uri ENHANCED_4G_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath("enhanced_4g_lte")
.build();
/**
* Backing Uri for the Flashlight Slice.
*/
public static final Uri FLASHLIGHT_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath("flashlight")
.build();
/**
* Backing Uri for the Location Slice.
*/
public static final Uri LOCATION_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(KEY_LOCATION)
.build();
/**
* Backing Uri for Low storage Slice.
*/
public static final Uri LOW_STORAGE_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
.appendPath("low_storage")
.build();
/**
* Backing Uri for the storage slice.
*/
public static final Uri STORAGE_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath("storage_card")
.build();
/**
* Full {@link Uri} for the Wifi Calling Slice.
*/
public static final Uri WIFI_CALLING_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(WifiCallingSliceHelper.PATH_WIFI_CALLING)
.build();
/**
* Full {@link Uri} for the Wifi Calling Preference Slice.
*/
public static final Uri WIFI_CALLING_PREFERENCE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(WifiCallingSliceHelper.PATH_WIFI_CALLING_PREFERENCE)
.build();
/**
* Backing Uri for the Wifi Slice.
*/
public static final Uri WIFI_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(KEY_WIFI)
.build();
/**
* Backing Uri for the Zen Mode Slice.
*/
public static final Uri ZEN_MODE_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(ZEN_MODE_KEY)
.build();
}

View File

@@ -44,11 +44,8 @@ import com.android.settings.core.BasePreferenceController;
import com.android.settings.flashlight.FlashlightSliceBuilder;
import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSlice;
import com.android.settings.location.LocationSliceBuilder;
import com.android.settings.network.telephony.Enhanced4gLteSliceHelper;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wifi.WifiSlice;
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
import com.android.settingslib.SliceBroadcastRelay;
import com.android.settingslib.utils.ThreadUtils;
@@ -175,23 +172,21 @@ public class SettingsSliceProvider extends SliceProvider {
if (filter != null) {
registerIntentToUri(filter, sliceUri);
}
ThreadUtils.postOnMainThread(() -> {
startBackgroundWorker(sliceable);
});
ThreadUtils.postOnMainThread(() -> startBackgroundWorker(sliceable));
return;
}
if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
registerIntentToUri(ZenModeSliceBuilder.INTENT_FILTER, sliceUri);
return;
} else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
registerIntentToUri(BluetoothSliceBuilder.INTENT_FILTER, sliceUri);
return;
} else if (FlashlightSliceBuilder.FLASHLIGHT_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.FLASHLIGHT_SLICE_URI.equals(sliceUri)) {
registerIntentToUri(FlashlightSliceBuilder.INTENT_FILTER, sliceUri);
mRegisteredUris.add(sliceUri);
return;
} else if (EmergencyInfoSlice.EMERGENCY_INFO_CARD_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI.equals(sliceUri)) {
return;
}
@@ -236,30 +231,30 @@ public class SettingsSliceProvider extends SliceProvider {
return sliceable.getSlice();
}
if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) {
if (CustomSliceRegistry.WIFI_CALLING_URI.equals(sliceUri)) {
return FeatureFactory.getFactory(getContext())
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(getContext())
.createWifiCallingSlice(sliceUri);
} else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
return ZenModeSliceBuilder.getSlice(getContext());
} else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
return BluetoothSliceBuilder.getSlice(getContext());
} else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.LOCATION_SLICE_URI.equals(sliceUri)) {
return LocationSliceBuilder.getSlice(getContext());
} else if (Enhanced4gLteSliceHelper.SLICE_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.ENHANCED_4G_SLICE_URI.equals(sliceUri)) {
return FeatureFactory.getFactory(getContext())
.getSlicesFeatureProvider()
.getNewEnhanced4gLteSliceHelper(getContext())
.createEnhanced4gLteSlice(sliceUri);
} else if (WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI.equals(sliceUri)) {
return FeatureFactory.getFactory(getContext())
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(getContext())
.createWifiCallingPreferenceSlice(sliceUri);
} else if (FlashlightSliceBuilder.FLASHLIGHT_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.FLASHLIGHT_SLICE_URI.equals(sliceUri)) {
return FlashlightSliceBuilder.getSlice(getContext());
} else if (EmergencyInfoSlice.EMERGENCY_INFO_CARD_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI.equals(sliceUri)) {
return EmergencyInfoSlice.getSlice(getContext());
}
@@ -476,16 +471,16 @@ public class SettingsSliceProvider extends SliceProvider {
private List<Uri> getSpecialCasePlatformUris() {
return Arrays.asList(
WifiSlice.WIFI_URI,
BluetoothSliceBuilder.BLUETOOTH_URI,
LocationSliceBuilder.LOCATION_URI
CustomSliceRegistry.WIFI_SLICE_URI,
CustomSliceRegistry.BLUETOOTH_URI,
CustomSliceRegistry.LOCATION_SLICE_URI
);
}
private List<Uri> getSpecialCaseOemUris() {
return Arrays.asList(
ZenModeSliceBuilder.ZEN_MODE_URI,
FlashlightSliceBuilder.FLASHLIGHT_URI
CustomSliceRegistry.ZEN_MODE_SLICE_URI,
CustomSliceRegistry.FLASHLIGHT_SLICE_URI
);
}

View File

@@ -279,7 +279,8 @@ public class SliceBuilderUtils {
.setTitle(sliceData.getTitle())
.setSubtitle(subtitleText)
.setPrimaryAction(
new SliceAction(contentIntent, icon, sliceData.getTitle()))
SliceAction.createDeeplink(contentIntent, icon,
ListBuilder.ICON_IMAGE, sliceData.getTitle()))
.addEndItem(sliceAction))
.setKeywords(keywords)
.build();
@@ -299,7 +300,9 @@ public class SliceBuilderUtils {
.setTitle(sliceData.getTitle())
.setSubtitle(subtitleText)
.setPrimaryAction(
new SliceAction(contentIntent, icon, sliceData.getTitle())))
SliceAction.createDeeplink(contentIntent, icon,
ListBuilder.ICON_IMAGE,
sliceData.getTitle())))
.setKeywords(keywords)
.build();
}
@@ -312,8 +315,8 @@ public class SliceBuilderUtils {
final IconCompat icon = getSafeIcon(context, sliceData);
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
final SliceAction primaryAction = new SliceAction(contentIntent, icon,
sliceData.getTitle());
final SliceAction primaryAction = SliceAction.createDeeplink(contentIntent, icon,
ListBuilder.ICON_IMAGE, sliceData.getTitle());
final Set<String> keywords = buildSliceKeywords(sliceData);
return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
@@ -334,7 +337,8 @@ public class SliceBuilderUtils {
final SliceAction copyableAction = getCopyableAction(context, sliceData);
final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
final IconCompat icon = getSafeIcon(context, sliceData);
final SliceAction primaryAction = new SliceAction(contentIntent, icon,
final SliceAction primaryAction = SliceAction.createDeeplink(contentIntent, icon,
ListBuilder.ICON_IMAGE,
sliceData.getTitle());
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
@@ -366,7 +370,7 @@ public class SliceBuilderUtils {
boolean isChecked) {
PendingIntent actionIntent = getActionIntent(context,
SettingsSliceProvider.ACTION_TOGGLE_CHANGED, sliceData);
return new SliceAction(actionIntent, null, isChecked);
return SliceAction.createToggle(actionIntent, null, isChecked);
}
private static PendingIntent getSliderAction(Context context, SliceData sliceData) {
@@ -378,7 +382,7 @@ public class SliceBuilderUtils {
SettingsSliceProvider.ACTION_COPY, sliceData);
final IconCompat icon = IconCompat.createWithResource(context,
R.drawable.ic_content_copy_grey600_24dp);
return new SliceAction(intent, icon, sliceData.getTitle());
return SliceAction.create(intent, icon, ListBuilder.ICON_IMAGE, sliceData.getTitle());
}
private static boolean isValidSummary(Context context, CharSequence summary) {
@@ -421,14 +425,15 @@ public class SliceBuilderUtils {
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final CharSequence summary = context.getText(R.string.disabled_dependent_setting_summary);
final IconCompat icon = getSafeIcon(context, data);
final SliceAction primaryAction = new SliceAction(getContentPendingIntent(context, data),
icon, title);
final SliceAction primaryAction = SliceAction.createDeeplink(
getContentPendingIntent(context, data),
icon, ListBuilder.ICON_IMAGE, title);
return new ListBuilder(context, data.getUri(), ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)
.setTitleItem(icon, ListBuilder.SMALL_IMAGE)
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setSubtitle(summary)
.setPrimaryAction(primaryAction))
.setKeywords(keywords)

View File

@@ -62,11 +62,11 @@ public class SliceDeepLinkSpringBoard extends Activity {
final CustomSliceable sliceable =
customSliceManager.getSliceableFromUri(sliceUri);
launchIntent = sliceable.getIntent();
} else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
launchIntent = ZenModeSliceBuilder.getIntent(this /* context */);
} else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
launchIntent = BluetoothSliceBuilder.getIntent(this /* context */);
} else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
} else if (CustomSliceRegistry.LOCATION_SLICE_URI.equals(sliceUri)) {
launchIntent = LocationSliceBuilder.getIntent(this /* context */);
} else {
final SlicesDatabaseAccessor slicesDatabaseAccessor =

View File

@@ -71,6 +71,9 @@ public class SlicesDatabaseAccessor {
*/
public SliceData getSliceDataFromUri(Uri uri) {
Pair<Boolean, String> pathData = SliceBuilderUtils.getPathData(uri);
if (pathData == null) {
throw new IllegalStateException("Invalid Slices uri: " + uri);
}
Cursor cursor = getIndexedSliceData(pathData.second /* key */);
return buildSliceData(cursor, uri, pathData.first /* isIntentOnly */);
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
/**
* A Preference to be used with the Wifi Network Detail Fragment that allows a summary text to be
* set inside the widget resource
*/
public class WifiDetailPreference extends Preference {
private String mDetailText;
public WifiDetailPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setWidgetLayoutResource(R.layout.preference_widget_summary);
}
public void setDetailText(String text) {
if (TextUtils.equals(mDetailText, text)) return;
mDetailText = text;
notifyChanged();
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
TextView textView = ((TextView) view.findViewById(R.id.widget_summary));
textView.setText(mDetailText);
textView.setPadding(0, 0, 10, 0);
}
}

View File

@@ -19,9 +19,10 @@ package com.android.settings.wifi;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static android.provider.SettingsSlicesContract.KEY_WIFI;
import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -30,7 +31,6 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid;
import android.os.Bundle;
import android.provider.SettingsSlicesContract;
import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
@@ -60,16 +60,6 @@ import java.util.List;
*/
public class WifiSlice implements CustomSliceable {
/**
* Backing Uri for the Wifi Slice.
*/
public static final Uri WIFI_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(KEY_WIFI)
.build();
@VisibleForTesting
static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
@@ -81,7 +71,7 @@ public class WifiSlice implements CustomSliceable {
@Override
public Uri getUri() {
return WIFI_URI;
return WIFI_SLICE_URI;
}
@Override
@@ -92,9 +82,6 @@ public class WifiSlice implements CustomSliceable {
return filter;
}
/**
* Return a Wifi Slice bound to {@link #WIFI_URI}.
*/
@Override
public Slice getSlice() {
final boolean isWifiEnabled = isWifiEnabled();
@@ -105,11 +92,13 @@ public class WifiSlice implements CustomSliceable {
@ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
final PendingIntent toggleAction = getBroadcastIntent(mContext);
final PendingIntent primaryAction = getPrimaryAction();
final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
isWifiEnabled);
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
ListBuilder.ICON_IMAGE, title);
final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
null /* actionTitle */, isWifiEnabled);
final ListBuilder listBuilder = new ListBuilder(mContext, WIFI_URI, ListBuilder.INFINITY)
final ListBuilder listBuilder = new ListBuilder(mContext, WIFI_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)
@@ -151,8 +140,9 @@ public class WifiSlice implements CustomSliceable {
.setSubtitle(!TextUtils.isEmpty(apSummary)
? apSummary
: mContext.getText(R.string.summary_placeholder))
.setPrimaryAction(new SliceAction(
getAccessPointAction(accessPoint), levelIcon, title));
.setPrimaryAction(SliceAction.create(
getAccessPointAction(accessPoint), levelIcon, ListBuilder.ICON_IMAGE,
title));
final IconCompat endIcon = getEndIcon(accessPoint);
if (endIcon != null) {

View File

@@ -18,9 +18,11 @@ package com.android.settings.wifi.calling;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static com.android.settings.slices.CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI;
import static com.android.settings.slices.CustomSliceRegistry.WIFI_CALLING_URI;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -42,9 +44,7 @@ import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
@@ -103,24 +103,6 @@ public class WifiCallingSliceHelper {
public static final String ACTION_WIFI_CALLING_SETTINGS_ACTIVITY =
"android.settings.WIFI_CALLING_SETTINGS";
/**
* Full {@link Uri} for the Wifi Calling Slice.
*/
public static final Uri WIFI_CALLING_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_WIFI_CALLING)
.build();
/**
* Full {@link Uri} for the Wifi Calling Preference Slice.
*/
public static final Uri WIFI_CALLING_PREFERENCE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(PATH_WIFI_CALLING_PREFERENCE)
.build();
/**
* Timeout for querying wifi calling setting from ims manager.
*/
@@ -212,12 +194,13 @@ public class WifiCallingSliceHelper {
.addRow(new RowBuilder()
.setTitle(mContext.getText(R.string.wifi_calling_settings_title))
.addEndItem(
new SliceAction(
SliceAction.createToggle(
getBroadcastIntent(ACTION_WIFI_CALLING_CHANGED),
null /* actionTitle */, isWifiCallingEnabled))
.setPrimaryAction(new SliceAction(
.setPrimaryAction(SliceAction.createDeeplink(
getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
icon,
ListBuilder.ICON_IMAGE,
mContext.getText(R.string.wifi_calling_settings_title))))
.build();
}
@@ -246,7 +229,7 @@ public class WifiCallingSliceHelper {
}
final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId,false);
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false);
final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true);
final ImsManager imsManager = getImsManager(subId);
@@ -287,8 +270,8 @@ public class WifiCallingSliceHelper {
* Returns actionable wifi calling preference slice.
*
* @param isWifiOnlySupported adds row for wifi only if this is true
* @param currentWfcPref current Preference {@link ImsConfig}
* @param sliceUri sliceUri
* @param currentWfcPref current Preference {@link ImsConfig}
* @param sliceUri sliceUri
* @return Slice for actionable wifi calling preference settings
*/
private Slice getWifiCallingPreferenceSlice(boolean isWifiOnlySupported,
@@ -299,12 +282,13 @@ public class WifiCallingSliceHelper {
ListBuilder listBuilder = new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
listBuilder.setHeader(new ListBuilder.HeaderBuilder()
.setTitle(mContext.getText(R.string.wifi_calling_mode_title))
.setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref))
.setPrimaryAction(new SliceAction(
getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
icon,
mContext.getText(R.string.wifi_calling_mode_title))));
.setTitle(mContext.getText(R.string.wifi_calling_mode_title))
.setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref))
.setPrimaryAction(SliceAction.createDeeplink(
getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
icon,
ListBuilder.ICON_IMAGE,
mContext.getText(R.string.wifi_calling_mode_title))));
if (isWifiOnlySupported) {
listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder,
@@ -329,9 +313,9 @@ public class WifiCallingSliceHelper {
/**
* Returns RowBuilder for a new row containing specific wifi calling preference.
*
* @param listBuilder ListBuilder that will be the parent for this RowBuilder
* @param listBuilder ListBuilder that will be the parent for this RowBuilder
* @param preferenceTitleResId resource Id for the preference row title
* @param action action to be added for the row
* @param action action to be added for the row
* @return RowBuilder for the row
*/
private RowBuilder wifiPreferenceRowBuilder(ListBuilder listBuilder,
@@ -340,7 +324,7 @@ public class WifiCallingSliceHelper {
IconCompat.createWithResource(mContext, R.drawable.radio_button_check);
return new RowBuilder()
.setTitle(mContext.getText(preferenceTitleResId))
.setTitleItem(new SliceAction(getBroadcastIntent(action),
.setTitleItem(SliceAction.createToggle(getBroadcastIntent(action),
icon, mContext.getText(preferenceTitleResId), checked));
}
@@ -414,8 +398,7 @@ public class WifiCallingSliceHelper {
}
// notify change in slice in any case to get re-queried. This would result in displaying
// appropriate message with the updated setting.
final Uri uri = SliceBuilderUtils.getUri(PATH_WIFI_CALLING, false /*isPlatformSlice*/);
mContext.getContentResolver().notifyChange(uri, null);
mContext.getContentResolver().notifyChange(WIFI_CALLING_URI, null);
}
/**
@@ -433,7 +416,7 @@ public class WifiCallingSliceHelper {
if (subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId,false);
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false);
final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true);
@@ -470,15 +453,13 @@ public class WifiCallingSliceHelper {
// notify change in slice in any case to get re-queried. This would result in displaying
// appropriate message.
final Uri uri = SliceBuilderUtils.getUri(PATH_WIFI_CALLING_PREFERENCE,
false /*isPlatformSlice*/);
mContext.getContentResolver().notifyChange(uri, null);
mContext.getContentResolver().notifyChange(WIFI_CALLING_PREFERENCE_URI, null);
}
/**
* Returns Slice with the title and subtitle provided as arguments with wifi signal Icon.
*
* @param title Title of the slice
* @param title Title of the slice
* @param subtitle Subtitle of the slice
* @param sliceUri slice uri
* @return Slice with title and subtitle
@@ -491,8 +472,8 @@ public class WifiCallingSliceHelper {
.addRow(new RowBuilder()
.setTitle(title)
.setSubtitle(subtitle)
.setPrimaryAction(new SliceAction(
primaryActionIntent, icon,
.setPrimaryAction(SliceAction.createDeeplink(
primaryActionIntent, icon, ListBuilder.SMALL_IMAGE,
title)))
.build();
}

View File

@@ -57,7 +57,6 @@ import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.EntityHeaderController;
import com.android.settings.wifi.WifiDetailPreference;
import com.android.settings.wifi.WifiDialog;
import com.android.settings.wifi.WifiDialog.WifiDialogListener;
import com.android.settings.wifi.WifiUtils;
@@ -133,15 +132,15 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
// UI elements - in order of appearance
private ActionButtonPreference mButtonsPref;
private EntityHeaderController mEntityHeaderController;
private WifiDetailPreference mSignalStrengthPref;
private WifiDetailPreference mLinkSpeedPref;
private WifiDetailPreference mFrequencyPref;
private WifiDetailPreference mSecurityPref;
private WifiDetailPreference mMacAddressPref;
private WifiDetailPreference mIpAddressPref;
private WifiDetailPreference mGatewayPref;
private WifiDetailPreference mSubnetPref;
private WifiDetailPreference mDnsPref;
private Preference mSignalStrengthPref;
private Preference mLinkSpeedPref;
private Preference mFrequencyPref;
private Preference mSecurityPref;
private Preference mMacAddressPref;
private Preference mIpAddressPref;
private Preference mGatewayPref;
private Preference mSubnetPref;
private Preference mDnsPref;
private PreferenceCategory mIpv6Category;
private Preference mIpv6AddressPref;
@@ -283,22 +282,21 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
.setButton2Text(R.string.wifi_sign_in_button_text)
.setButton2OnClickListener(view -> signIntoNetwork());
mSignalStrengthPref =
(WifiDetailPreference) screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
mLinkSpeedPref = (WifiDetailPreference) screen.findPreference(KEY_LINK_SPEED);
mFrequencyPref = (WifiDetailPreference) screen.findPreference(KEY_FREQUENCY_PREF);
mSecurityPref = (WifiDetailPreference) screen.findPreference(KEY_SECURITY_PREF);
mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
mLinkSpeedPref = screen.findPreference(KEY_LINK_SPEED);
mFrequencyPref = screen.findPreference(KEY_FREQUENCY_PREF);
mSecurityPref = screen.findPreference(KEY_SECURITY_PREF);
mMacAddressPref = (WifiDetailPreference) screen.findPreference(KEY_MAC_ADDRESS_PREF);
mIpAddressPref = (WifiDetailPreference) screen.findPreference(KEY_IP_ADDRESS_PREF);
mGatewayPref = (WifiDetailPreference) screen.findPreference(KEY_GATEWAY_PREF);
mSubnetPref = (WifiDetailPreference) screen.findPreference(KEY_SUBNET_MASK_PREF);
mDnsPref = (WifiDetailPreference) screen.findPreference(KEY_DNS_PREF);
mMacAddressPref = screen.findPreference(KEY_MAC_ADDRESS_PREF);
mIpAddressPref = screen.findPreference(KEY_IP_ADDRESS_PREF);
mGatewayPref = screen.findPreference(KEY_GATEWAY_PREF);
mSubnetPref = screen.findPreference(KEY_SUBNET_MASK_PREF);
mDnsPref = screen.findPreference(KEY_DNS_PREF);
mIpv6Category = (PreferenceCategory) screen.findPreference(KEY_IPV6_CATEGORY);
mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
mSecurityPref.setDetailText(mAccessPoint.getSecurityString(false /* concise */));
mSecurityPref.setSummary(mAccessPoint.getSecurityString(false /* concise */));
}
private void setupEntityHeader(PreferenceScreen screen) {
@@ -359,12 +357,12 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
refreshRssiViews();
// MAC Address Pref
mMacAddressPref.setDetailText(mWifiInfo.getMacAddress());
mMacAddressPref.setSummary(mWifiInfo.getMacAddress());
// Link Speed Pref
int linkSpeedMbps = mWifiInfo.getLinkSpeed();
mLinkSpeedPref.setVisible(linkSpeedMbps >= 0);
mLinkSpeedPref.setDetailText(mContext.getString(
mLinkSpeedPref.setSummary(mContext.getString(
R.string.link_speed, mWifiInfo.getLinkSpeed()));
// Frequency Pref
@@ -379,7 +377,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
} else {
Log.e(TAG, "Unexpected frequency " + frequency);
}
mFrequencyPref.setDetailText(band);
mFrequencyPref.setSummary(band);
updateIpLayerInfo();
}
@@ -410,16 +408,15 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
mEntityHeaderController.setIcon(wifiIcon).done(mFragment.getActivity(), true /* rebind */);
Drawable wifiIconDark = wifiIcon.getConstantState().newDrawable().mutate();
wifiIconDark.setTint(mContext.getResources().getColor(
R.color.wifi_details_icon_color, mContext.getTheme()));
wifiIconDark.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal));
mSignalStrengthPref.setIcon(wifiIconDark);
mSignalStrengthPref.setDetailText(mSignalStr[mRssiSignalLevel]);
mSignalStrengthPref.setSummary(mSignalStr[mRssiSignalLevel]);
}
private void updatePreference(WifiDetailPreference pref, String detailText) {
private void updatePreference(Preference pref, String detailText) {
if (!TextUtils.isEmpty(detailText)) {
pref.setDetailText(detailText);
pref.setSummary(detailText);
pref.setVisible(true);
} else {
pref.setVisible(false);

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi.dpp;
import android.os.Bundle;
import com.android.settings.R;
/**
* After getting Wi-Fi network information and(or) QR code, this fragment config a device to connect
* to the Wi-Fi network.
*/
public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
@Override
protected int getLayout() {
return R.layout.wifi_dpp_add_device_fragment;
}
@Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi.dpp;
import android.os.Bundle;
import com.android.settings.R;
/**
* After a camera APP scanned a Wi-Fi DPP QR code, it can trigger
* {@code WifiDppConfiguratorActivity} to start with this fragment to choose a saved Wi-Fi network.
*/
public class WifiDppChooseSavedWifiNetworkFragment extends WifiDppQrCodeBaseFragment {
@Override
protected int getLayout() {
return R.layout.wifi_dpp_choose_saved_wifi_network_fragment;
}
@Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}

View File

@@ -21,6 +21,7 @@ import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
@@ -67,25 +68,59 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.wifi_dpp_activity);
// Hide action bar
ActionBar action = getActionBar();
if (action != null) {
action.hide();
}
mFragmentManager = getSupportFragmentManager();
mFragmentTransaction = getSupportFragmentManager().beginTransaction();
final int launchMode = getIntent().getIntExtra(EXTRA_LAUNCH_MODE,
LaunchMode.LAUNCH_MODE_NOT_DEFINED.getMode());
if (launchMode == LaunchMode.LAUNCH_MODE_QR_CODE_SCANNER.getMode()) {
WifiDppQrCodeScannerFragment scanFragment = new WifiDppQrCodeScannerFragment();
mFragmentTransaction.add(R.id.fragment_container, scanFragment);
mFragmentTransaction.commit();
addQrCodeScannerFragment();
} else if (launchMode == LaunchMode.LAUNCH_MODE_QR_CODE_GENERATOR.getMode()) {
addQrCodeGeneratorFragment();
} else if (launchMode == LaunchMode.LAUNCH_MODE_CHOOSE_SAVED_WIFI_NETWORK.getMode()) {
addChooseSavedWifiNetworkFragment();
} else {
Log.e(TAG, "Launch with an invalid mode extra");
setResult(Activity.RESULT_CANCELED);
finish();
}
}
private void addQrCodeScannerFragment() {
final WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment();
mFragmentTransaction.add(R.id.fragment_container, fragment);
mFragmentTransaction.addToBackStack(/* name */ null);
mFragmentTransaction.commit();
}
private void addQrCodeGeneratorFragment() {
final WifiDppQrCodeGeneratorFragment fragment = new WifiDppQrCodeGeneratorFragment();
mFragmentTransaction.add(R.id.fragment_container, fragment);
mFragmentTransaction.addToBackStack(/* name */ null);
mFragmentTransaction.commit();
}
private void addChooseSavedWifiNetworkFragment() {
final ActionBar action = getActionBar();
if (action != null) {
action.hide();
}
WifiDppChooseSavedWifiNetworkFragment fragment =
new WifiDppChooseSavedWifiNetworkFragment();
mFragmentTransaction.add(R.id.fragment_container, fragment);
mFragmentTransaction.addToBackStack(/* name */ null);
mFragmentTransaction.commit();
}
@Override
protected void onStop() {
final Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
if (fragment != null) {
// Remove it to prevent stacking multiple fragments after screen rotated.
mFragmentManager.beginTransaction().remove(fragment).commit();
}
super.onStop();
}
}

View File

@@ -22,6 +22,9 @@ import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto;
@@ -29,13 +32,37 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.R;
/**
* There are below 4 fragments for Wi-Fi DPP UI flow, to reduce redundant code of UI components,
* this parent fragment instantiates all UI components and provides setting APIs for them.
*
* {@code WifiDppQrCodeScannerFragment}
* {@code WifiDppQrCodeGeneratorFragment}
* {@code WifiDppChooseSavedWifiNetworkFragment}
* {@code WifiDppAddDeviceFragment}
*/
public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
private TextView mTitle;
private TextView mDescription;
private SurfaceView mPreviewView;
private TextView mErrorMessage; //optional, view used to surface connectivity errors to the user
private Button mButtonLeft;
private Button mButtonRight;
private SurfaceView mPreviewView; //optional, for WifiDppQrCodeScannerFragment
private ImageView mDecorateViiew; //optional, for WifiDppQrCodeScannerFragment
private TextView mErrorMessage; //optional, for WifiDppQrCodeScannerFragment
private ImageView mBarcodeView; //optional, for WifiDppQrCodeGeneratorFragment
private ListView mSavedWifiNetworkList; //optional, for WifiDppChooseSavedWifiNetworkFragment
private ProgressBar mProgressBar; //optional, for WifiDppAddDeviceFragment
private ImageView mWifiApPictureView; //optional, for WifiDppAddDeviceFragment
private TextView mChooseDifferentNetwork;//optional, for WifiDppAddDeviceFragment
private Button mButtonLeft; //optional, for WifiDppQrCodeScannerFragment,
// WifiDppChooseSavedWifiNetworkFragment,
// WifiDppAddDeviceFragment
private Button mButtonRight; //optional, for WifiDppQrCodeScannerFragment,
// WifiDppChooseSavedWifiNetworkFragment,
// WifiDppAddDeviceFragment
abstract protected int getLayout();
@@ -61,8 +88,19 @@ public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
private void initView(View view) {
mTitle = view.findViewById(R.id.title);
mDescription = view.findViewById(R.id.description);
mPreviewView = view.findViewById(R.id.preview_view);
mDecorateViiew = view.findViewById(R.id.decorate_view);
mErrorMessage = view.findViewById(R.id.error_message);
mBarcodeView = view.findViewById(R.id.barcode_view);
mSavedWifiNetworkList = view.findViewById(R.id.saved_wifi_network_list);
mProgressBar = view.findViewById(R.id.progress_bar);
mWifiApPictureView = view.findViewById(R.id.wifi_ap_picture_view);
mChooseDifferentNetwork = view.findViewById(R.id.choose_different_network);
mButtonLeft = view.findViewById(R.id.button_left);
mButtonRight = view.findViewById(R.id.button_right);
}
@@ -75,33 +113,76 @@ public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
mDescription.setText(description);
}
/** optional, for WifiDppQrCodeScannerFragment */
protected void setErrorMessage(String errorMessage) {
if (mErrorMessage != null) {
mErrorMessage.setText(errorMessage);
}
}
/**
* optional, for WifiDppQrCodeScannerFragment,
* WifiDppChooseSavedWifiNetworkFragment,
* WifiDppAddDeviceFragment
*/
protected void setLeftButtonText(String text) {
mButtonLeft.setText(text);
if (mButtonLeft != null) {
mButtonLeft.setText(text);
}
}
/**
* optional, for WifiDppQrCodeScannerFragment,
* WifiDppChooseSavedWifiNetworkFragment,
* WifiDppAddDeviceFragment
*/
protected void setRightButtonText(String text) {
mButtonRight.setText(text);
if (mButtonRight != null) {
mButtonRight.setText(text);
}
}
/**
* optional, for WifiDppQrCodeScannerFragment,
* WifiDppChooseSavedWifiNetworkFragment,
* WifiDppAddDeviceFragment
*/
protected void hideLeftButton() {
mButtonLeft.setVisibility(View.INVISIBLE);
if (mButtonLeft != null) {
mButtonLeft.setVisibility(View.INVISIBLE);
}
}
/**
* optional, for WifiDppQrCodeScannerFragment,
* WifiDppChooseSavedWifiNetworkFragment,
* WifiDppAddDeviceFragment
*/
protected void hideRightButton() {
mButtonRight.setVisibility(View.INVISIBLE);
if (mButtonRight != null) {
mButtonRight.setVisibility(View.INVISIBLE);
}
}
/**
* optional, for WifiDppQrCodeScannerFragment,
* WifiDppChooseSavedWifiNetworkFragment,
* WifiDppAddDeviceFragment
*/
protected void setLeftButtonOnClickListener(View.OnClickListener listener) {
mButtonLeft.setOnClickListener(listener);
if (mButtonLeft != null) {
mButtonLeft.setOnClickListener(listener);
}
}
/**
* optional, for WifiDppQrCodeScannerFragment,
* WifiDppChooseSavedWifiNetworkFragment,
* WifiDppAddDeviceFragment
*/
protected void setRightButtonOnClickListener(View.OnClickListener listener) {
mButtonRight.setOnClickListener(listener);
if (mButtonRight != null) {
mButtonRight.setOnClickListener(listener);
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi.dpp;
import android.os.Bundle;
import com.android.settings.R;
/**
* After sharing a saved Wi-Fi network, {@code WifiDppConfiguratorActivity} start with this fragment
* to generate a Wi-Fi DPP QR code for other device to initiate as an enrollee.
*/
public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
@Override
protected int getLayout() {
return R.layout.wifi_dpp_qrcode_generator_fragment;
}
@Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}

View File

@@ -16,40 +16,120 @@
package com.android.settings.wifi.dpp;
import android.annotation.Nullable;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.text.TextUtils;
import android.util.Size;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import com.android.settings.R;
import com.android.settings.wifi.qrcode.QrCamera;
import com.android.settings.wifi.qrcode.QrDecorateView;
public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
SurfaceHolder.Callback,
QrCamera.ScannerCallback {
private QrCamera mCamera;
private SurfaceView mSurfaceView;
private QrDecorateView mDecorateView;
public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment {
@Override
protected int getLayout() {
return R.layout.wifi_dpp_qrcode_scanner_fragment;
}
@Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated (savedInstanceState);
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setTitle(getString(R.string.wifi_dpp_add_device_to_network));
String ssid = "";
Intent intent = getActivity().getIntent();
if (intent != null)
String ssid = null;
final Intent intent = getActivity().getIntent();
if (intent != null) {
ssid = intent.getStringExtra(WifiDppConfiguratorActivity.EXTRA_SSID);
String description = getString(R.string.wifi_dpp_center_qr_code, ssid);
setDescription(description);
}
if (TextUtils.isEmpty(ssid)) {
throw new IllegalArgumentException("Invalid SSID");
}
setDescription(getString(R.string.wifi_dpp_center_qr_code, ssid));
hideRightButton();
setLeftButtonText(getString(android.R.string.cancel));
setLeftButtonOnClickListener((view) -> {
getActivity().setResult(Activity.RESULT_CANCELED);
getActivity().finish();});
getActivity().setResult(Activity.RESULT_CANCELED);
getActivity().finish();
});
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mSurfaceView = (SurfaceView) view.findViewById(R.id.preview_view);
final SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(this);
mDecorateView = (QrDecorateView) view.findViewById(R.id.decorate_view);
}
@Override
public void surfaceCreated(final SurfaceHolder holder) {
initCamera(holder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
destroyCamera();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// Do nothing
}
@Override
public Size getViewSize() {
return new Size(mSurfaceView.getWidth(), mSurfaceView.getHeight());
}
@Override
public Rect getFramePosition(Size previewSize, int cameraOrientation) {
return new Rect(0, 0, previewSize.getHeight(), previewSize.getHeight());
}
@Override
public void handleSuccessfulResult(String qrCode) {
destroyCamera();
mDecorateView.setFocused(true);
// TODO(b/120243131): Add a network by Wi-Fi Network config shared via QR code.
}
@Override
public void handleCameraFailure() {
destroyCamera();
}
private void initCamera(SurfaceHolder holder) {
// Check if the camera has already created.
if (mCamera == null) {
mCamera = new QrCamera(getContext(), this);
mCamera.start(holder);
}
}
private void destroyCamera() {
if (mCamera != null) {
mCamera.stop();
mCamera = null;
}
}
}

View File

@@ -43,6 +43,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import androidx.annotation.VisibleForTesting;
@@ -85,14 +86,26 @@ public class QrCamera extends Handler {
mReader.setHints(HINTS);
}
void start(SurfaceHolder surfaceHolder) {
/**
* The function start camera preview and capture pictures to decode QR code continuously in a
* background task.
*
* @param surfaceHolder the Surface to be used for live preview, must already contain a surface
* when this method is called.
*/
public void start(SurfaceHolder surfaceHolder) {
if (mDecodeTask == null) {
mDecodeTask = new DecodingTask(surfaceHolder);
mDecodeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
// Execute in the separate thread pool to prevent block other AsyncTask.
mDecodeTask.executeOnExecutor(Executors.newSingleThreadExecutor());
}
}
void stop() {
/**
* The function stop camera preview and background decode task. Caller call this function when
* the surface is being destroyed.
*/
public void stop() {
removeMessages(MSG_AUTO_FOCUS);
if (mDecodeTask != null) {
mDecodeTask.cancel(true);
@@ -104,7 +117,7 @@ public class QrCamera extends Handler {
}
/** The scanner which includes this QrCamera class should implement this */
interface ScannerCallback {
public interface ScannerCallback {
/**
* The function used to handle the decoding result of the QR code.

View File

@@ -73,8 +73,16 @@
<item>fake_package/fake_service</item>
</string-array>
<!-- Settings intelligence interaction log intent action -->
<string name="config_settingsintelligence_log_action" translatable="false">
aaa.bbb.ccc
</string>
<!-- List of packages that should be whitelisted for slice uri access. Do not translate -->
<string-array name="slice_whitelist_package_names" translatable="false">
<item>com.android.settings.slice_whitelist_package</item>
</string-array>
<!-- Email address for the homepage contextual cards feedback -->
<string name="config_contextual_card_feedback_email" translatable="false">test@test.test</string>
</resources>

View File

@@ -28,9 +28,6 @@ import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings.Global;
import android.view.View;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@@ -38,16 +35,13 @@ import androidx.fragment.app.FragmentTransaction;
import com.android.settings.core.OnActivityResultListener;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
@@ -70,29 +64,6 @@ public class SettingsActivityTest {
mActivity = spy(new SettingsActivity());
}
@Test
@Config(shadows = ShadowUtils.class)
public void onCreate_deviceNotProvisioned_shouldDisableSearch() {
Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 0);
final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class)
.create(Bundle.EMPTY)
.get();
assertThat(activity.findViewById(R.id.search_bar).getVisibility())
.isEqualTo(View.INVISIBLE);
}
@Test
@Config(shadows = ShadowUtils.class)
public void onCreate_deviceProvisioned_shouldEnableSearch() {
Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class)
.create(Bundle.EMPTY)
.get();
assertThat(activity.findViewById(R.id.search_bar).getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash() {
when(mActivity.getSupportFragmentManager()).thenReturn(mFragmentManager);
@@ -101,7 +72,7 @@ public class SettingsActivityTest {
doReturn(RuntimeEnvironment.application.getClassLoader()).when(mActivity).getClassLoader();
mActivity.launchSettingFragment(null, true, mock(Intent.class));
mActivity.launchSettingFragment(null, mock(Intent.class));
}
@Test

View File

@@ -51,7 +51,6 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowPowerManager;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
@@ -93,6 +92,8 @@ public class RecentAppsPreferenceControllerTest {
private ApplicationsState.AppEntry mAppEntry;
@Mock
private ApplicationInfo mApplicationInfo;
@Mock
private PowerManager mPowerManager;
private Context mContext;
private RecentAppsPreferenceController mController;
@@ -104,6 +105,7 @@ public class RecentAppsPreferenceControllerTest {
doReturn(mUsageStatsManager).when(mContext).getSystemService(Context.USAGE_STATS_SERVICE);
doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
mController = new RecentAppsPreferenceController(mContext, mAppState, null);
when(mScreen.findPreference(anyString())).thenReturn(mCategory);
@@ -174,15 +176,15 @@ public class RecentAppsPreferenceControllerTest {
// stat1, stat2 are valid apps. stat3 is invalid.
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
.thenReturn(mAppEntry);
.thenReturn(mAppEntry);
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
.thenReturn(mAppEntry);
.thenReturn(mAppEntry);
when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId()))
.thenReturn(null);
.thenReturn(null);
when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
.thenReturn(new ResolveInfo());
.thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
.thenReturn(stats);
mAppEntry.info = mApplicationInfo;
mController.displayPreference(mScreen);
@@ -199,7 +201,7 @@ public class RecentAppsPreferenceControllerTest {
@Test
public void display_powerSaverMode_showNoRecents() {
mContext.getSystemService(PowerManager.class).setPowerSaveMode(true);
when(mPowerManager.isPowerSaveMode()).thenReturn(true);
final List<UsageStats> stats = new ArrayList<>();
final UsageStats stat1 = new UsageStats();
@@ -251,7 +253,7 @@ public class RecentAppsPreferenceControllerTest {
// Only the regular app stat1 should have its intent resolve.
when(mPackageManager.resolveActivity(argThat(intentMatcher(stat1.mPackageName)), anyInt()))
.thenReturn(new ResolveInfo());
.thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
@@ -311,13 +313,13 @@ public class RecentAppsPreferenceControllerTest {
// stat1, stat2 are not displayable
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
.thenReturn(mock(ApplicationsState.AppEntry.class));
.thenReturn(mock(ApplicationsState.AppEntry.class));
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
.thenReturn(mock(ApplicationsState.AppEntry.class));
.thenReturn(mock(ApplicationsState.AppEntry.class));
when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
.thenReturn(new ResolveInfo());
.thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
.thenReturn(stats);
mController.displayPreference(mScreen);
@@ -336,11 +338,11 @@ public class RecentAppsPreferenceControllerTest {
stats.add(stat1);
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
.thenReturn(mAppEntry);
.thenReturn(mAppEntry);
when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
.thenReturn(new ResolveInfo());
.thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
.thenReturn(stats);
mAppEntry.info = mApplicationInfo;
mController.displayPreference(mScreen);

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.development;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.provider.Settings;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
@RunWith(SettingsRobolectricTestRunner.class)
public class AllowBackgroundActivityStartsPreferenceControllerTest {
@Mock
private SwitchPreference mPreference;
@Mock
private PreferenceScreen mPreferenceScreen;
private Context mContext;
private AllowBackgroundActivityStartsPreferenceController mController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new AllowBackgroundActivityStartsPreferenceController(mContext);
when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
.thenReturn(mPreference);
mController.displayPreference(mPreferenceScreen);
}
@Test
public void onPreferenceChange_settingEnabled_allowBackgroundActivityStartsShouldBeOn() {
mController.onPreferenceChange(mPreference, true /* new value */);
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */);
assertThat(mode).isEqualTo(1);
}
@Test
public void onPreferenceChange_settingDisabled_allowBackgroundActivityStartsShouldBeOff() {
mController.onPreferenceChange(mPreference, false /* new value */);
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */);
assertThat(mode).isEqualTo(0);
}
@Test
public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 0);
mController.updateState(mPreference);
verify(mPreference).setChecked(false);
}
@Test
public void updateState_settingEnabled_preferenceShouldBeChecked() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1);
mController.updateState(mPreference);
verify(mPreference).setChecked(true);
}
@Test
public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
mController.onDeveloperOptionsSwitchDisabled();
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */);
assertThat(mode).isEqualTo(0);
verify(mPreference).setChecked(false);
verify(mPreference).setEnabled(false);
}
}

View File

@@ -21,6 +21,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.PowerManager;
@@ -37,21 +39,19 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowPowerManager;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = ShadowPowerManager.class)
public class BatterySaverButtonPreferenceControllerTest {
private BatterySaverButtonPreferenceController mController;
private Context mContext;
private Button mButtonOn;
private Button mButtonOff;
private PowerManager mPowerManager;
private TwoStateButtonPreference mPreference;
@Mock
private PowerManager mPowerManager;
@Mock
private PreferenceScreen mPreferenceScreen;
@@ -61,10 +61,11 @@ public class BatterySaverButtonPreferenceControllerTest {
mContext = spy(RuntimeEnvironment.application);
mButtonOn = new Button(mContext);
mButtonOff = new Button(mContext);
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mPreference = spy(new TwoStateButtonPreference(mContext, null /* AttributeSet */));
ReflectionHelpers.setField(mPreference, "mButtonOn", mButtonOn);
ReflectionHelpers.setField(mPreference, "mButtonOff", mButtonOff);
doReturn(mPowerManager).when(mContext).getSystemService(Context.POWER_SERVICE);
doReturn(mPreference).when(mPreferenceScreen).findPreference(anyString());
mController = new BatterySaverButtonPreferenceController(mContext, "test_key");
@@ -73,7 +74,7 @@ public class BatterySaverButtonPreferenceControllerTest {
@Test
public void updateState_lowPowerOn_preferenceIsChecked() {
mPowerManager.setPowerSaveMode(true);
when(mPowerManager.isPowerSaveMode()).thenReturn(true);
mController.updateState(mPreference);
@@ -82,7 +83,7 @@ public class BatterySaverButtonPreferenceControllerTest {
@Test
public void testUpdateState_lowPowerOff_preferenceIsUnchecked() {
mPowerManager.setPowerSaveMode(false);
when(mPowerManager.isPowerSaveMode()).thenReturn(false);
mController.updateState(mPreference);
@@ -93,13 +94,13 @@ public class BatterySaverButtonPreferenceControllerTest {
public void setChecked_on_setPowerSaveMode() {
mController.setChecked(true);
assertThat(mPowerManager.isPowerSaveMode()).isTrue();
verify(mPowerManager).setPowerSaveMode(true);
}
@Test
public void setChecked_off_unsetPowerSaveMode() {
mController.setChecked(false);
assertThat(mPowerManager.isPowerSaveMode()).isFalse();
verify(mPowerManager).setPowerSaveMode(false);
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.homepage.contextualcards;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.Intent;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
public class ContextualCardFeatureProviderImplTest {
private Context mContext;
private ContextualCardFeatureProviderImpl mImpl;
@Before
public void setUp() {
mContext = spy(RuntimeEnvironment.application);
mImpl = new ContextualCardFeatureProviderImpl();
}
@Test
public void sendBroadcast_emptyAction_notSendBroadcast() {
final Intent intent = new Intent();
mImpl.sendBroadcast(mContext, intent);
verify(mContext, never()).sendBroadcast(intent);
}
@Test
@Config(qualifiers = "mcc999")
public void sendBroadcast_hasAction_sendBroadcast() {
final Intent intent = new Intent();
mImpl.sendBroadcast(mContext, intent);
verify(mContext).sendBroadcast(intent);
}
}

View File

@@ -27,11 +27,9 @@ import static org.mockito.Mockito.spy;
import android.content.Context;
import android.net.Uri;
import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice;
import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wifi.WifiSlice;
import org.junit.Before;
import org.junit.Test;
@@ -153,7 +151,7 @@ public class ContextualCardLoaderTest {
cards.add(new ContextualCard.Builder()
.setName("test_wifi")
.setCardType(ContextualCard.CardType.SLICE)
.setSliceUri(WifiSlice.WIFI_URI)
.setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI)
.build());
cards.add(new ContextualCard.Builder()
.setName("test_flashlight")
@@ -164,7 +162,7 @@ public class ContextualCardLoaderTest {
cards.add(new ContextualCard.Builder()
.setName("test_connected")
.setCardType(ContextualCard.CardType.SLICE)
.setSliceUri(ConnectedDeviceSlice.CONNECTED_DEVICE_URI)
.setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI)
.build());
cards.add(new ContextualCard.Builder()
.setName("test_gesture")
@@ -175,7 +173,7 @@ public class ContextualCardLoaderTest {
cards.add(new ContextualCard.Builder()
.setName("test_battery")
.setCardType(ContextualCard.CardType.SLICE)
.setSliceUri(BatterySlice.BATTERY_CARD_URI)
.setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
.build());
return cards;
}
@@ -208,7 +206,7 @@ public class ContextualCardLoaderTest {
cards.add(new ContextualCard.Builder()
.setName("test_battery")
.setCardType(ContextualCard.CardType.SLICE)
.setSliceUri(BatterySlice.BATTERY_CARD_URI)
.setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
.build());
return cards;
}

View File

@@ -18,13 +18,12 @@ package com.android.settings.homepage.contextualcards;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.Mockito.doNothing;
import android.content.Context;
import android.net.Uri;
import android.util.ArrayMap;
import com.android.settings.homepage.contextualcards.conditional.ConditionFooterContextualCard;
import com.android.settings.homepage.contextualcards.conditional.ConditionHeaderContextualCard;
import com.android.settings.homepage.contextualcards.conditional.ConditionalContextualCard;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -70,7 +69,7 @@ public class ContextualCardManagerTest {
}
@Test
public void onContextualCardUpdated_emtpyMapWithExistingCards_shouldOnlyKeepConditionalCard() {
public void onContextualCardUpdated_emptyMapWithExistingCards_shouldOnlyKeepConditionalCard() {
mManager.mContextualCards.add(new ConditionalContextualCard.Builder().build());
mManager.mContextualCards.add(
buildContextualCard(TEST_SLICE_URI));
@@ -84,6 +83,31 @@ public class ContextualCardManagerTest {
.isEqualTo(ContextualCard.CardType.CONDITIONAL);
}
@Test
public void onContextualCardUpdated_hasEmptyMap_shouldKeepConditionalHeaderCard() {
mManager.mContextualCards.add(new ConditionHeaderContextualCard.Builder().build());
mManager.setListener(mListener);
mManager.onContextualCardUpdated(new ArrayMap<>());
assertThat(mManager.mContextualCards).hasSize(1);
assertThat(mManager.mContextualCards.get(0).getCardType())
.isEqualTo(ContextualCard.CardType.CONDITIONAL_HEADER);
}
@Test
public void onContextualCardUpdated_hasEmptyMap_shouldKeepConditionalFooterCard() {
mManager.mContextualCards.add(new ConditionFooterContextualCard.Builder().build());
mManager.setListener(mListener);
mManager.onContextualCardUpdated(new ArrayMap<>());
assertThat(mManager.mContextualCards).hasSize(1);
assertThat(mManager.mContextualCards.get(0).getCardType())
.isEqualTo(ContextualCard.CardType.CONDITIONAL_FOOTER);
}
private ContextualCard buildContextualCard(String sliceUri) {
return new ContextualCard.Builder()
.setName("test_name")

View File

@@ -23,15 +23,13 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.app.slice.SliceManager;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import com.android.settings.intelligence.ContextualCardProto.ContextualCard;
import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wifi.WifiSlice;
import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
@@ -48,18 +46,11 @@ public class SettingsContextualCardProviderTest {
@Mock
private SliceManager mSliceManager;
private ContentResolver mResolver;
private Uri mUri;
private SettingsContextualCardProvider mProvider;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mResolver = RuntimeEnvironment.application.getContentResolver();
mUri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsContextualCardProvider.CARD_AUTHORITY)
.build();
mProvider = spy(Robolectric.setupContentProvider(SettingsContextualCardProvider.class));
final Context context = spy(RuntimeEnvironment.application);
doReturn(mSliceManager).when(context).getSystemService(SliceManager.class);
@@ -83,7 +74,7 @@ public class SettingsContextualCardProviderTest {
final ContextualCardList cards = mProvider.getContextualCards();
ContextualCard wifiCard = null;
for (ContextualCard card : cards.getCardList()) {
if (card.getSliceUri().equals(WifiSlice.WIFI_URI.toString())) {
if (card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI.toString())) {
wifiCard = card;
}
}

View File

@@ -18,6 +18,11 @@ package com.android.settings.homepage.contextualcards.slices;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -27,14 +32,22 @@ import android.net.Uri;
import com.android.settings.homepage.contextualcards.CardContentProvider;
import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
import com.android.settings.homepage.contextualcards.ContextualCard;
import com.android.settings.homepage.contextualcards.ContextualCardFeedbackDialog;
import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;
import org.robolectric.shadows.ShadowContentResolver;
import org.robolectric.shadows.androidx.fragment.FragmentController;
@RunWith(SettingsRobolectricTestRunner.class)
public class SliceContextualCardControllerTest {
@@ -46,27 +59,27 @@ public class SliceContextualCardControllerTest {
private CardContentProvider mProvider;
private ContentResolver mResolver;
private SliceContextualCardController mController;
private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mProvider = Robolectric.setupContentProvider(CardContentProvider.class);
ShadowContentResolver.registerProviderInternal(CardContentProvider.CARD_AUTHORITY,
mProvider);
mResolver = mContext.getContentResolver();
mController = new SliceContextualCardController(mContext);
mController = spy(new SliceContextualCardController(mContext));
mFeatureFactory = FakeFeatureFactory.setupForTest();
}
@Test
public void onDismissed_cardShouldBeMarkedAsDismissed() {
final Uri providerUri = CardContentProvider.URI;
final ContextualCard card = new ContextualCard.Builder()
.setName(TEST_CARD_NAME)
.setCardType(ContextualCard.CardType.SLICE)
.setSliceUri(Uri.parse(TEST_SLICE_URI))
.build();
mResolver.insert(providerUri, generateOneRow());
doNothing().when(mController).showFeedbackDialog(any(ContextualCard.class));
final ContextualCard card = getTestSliceCard();
mController.onDismissed(card);
final String[] columns = {CardDatabaseHelper.CardColumns.CARD_DISMISSED};
@@ -78,6 +91,34 @@ public class SliceContextualCardControllerTest {
cr.close();
assertThat(qryDismissed).isEqualTo(1);
verify(mFeatureFactory.mContextualCardFeatureProvider).logContextualCardDismiss(
mContext, card);
}
@Test
public void onDismissed_noFeedbackEmail_shouldNotShowFeedbackDialog() {
mResolver.insert(CardContentProvider.URI, generateOneRow());
final ContextualCardsFragment fragment =
FragmentController.of(new ContextualCardsFragment()).create().get();
final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity());
mController.onDismissed(getTestSliceCard());
assertThat(shadowActivity.getNextStartedActivity()).isNull();
}
@Test
@Config(qualifiers = "mcc999")
public void onDismissed_hasFeedbackEmail_shouldShowFeedbackDialog() {
mResolver.insert(CardContentProvider.URI, generateOneRow());
final ContextualCardsFragment fragment =
FragmentController.of(new ContextualCardsFragment()).create().get();
final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity());
mController.onDismissed(getTestSliceCard());
assertThat(shadowActivity.getNextStartedActivity().getComponent().getClassName())
.isEqualTo(ContextualCardFeedbackDialog.class.getName());
}
private ContentValues generateOneRow() {
@@ -93,4 +134,12 @@ public class SliceContextualCardControllerTest {
return values;
}
private ContextualCard getTestSliceCard() {
return new ContextualCard.Builder()
.setName(TEST_CARD_NAME)
.setCardType(ContextualCard.CardType.SLICE)
.setSliceUri(Uri.parse(TEST_SLICE_URI))
.build();
}
}

View File

@@ -44,6 +44,7 @@ import androidx.slice.widget.SliceLiveData;
import com.android.ims.ImsManager;
import com.android.settings.R;
import com.android.settings.slices.CustomSliceManager;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SlicesFeatureProvider;
@@ -107,7 +108,7 @@ public class Enhanced4gLteSliceHelperTest {
mEnhanced4gLteSliceHelper.setDefaultVoiceSubId(-1);
final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice(
Enhanced4gLteSliceHelper.SLICE_URI);
CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
assertThat(slice).isNull();
}
@@ -117,7 +118,7 @@ public class Enhanced4gLteSliceHelperTest {
when(mMockImsManager.isVolteEnabledByPlatform()).thenReturn(false);
final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice(
Enhanced4gLteSliceHelper.SLICE_URI);
CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
assertThat(slice).isNull();
@@ -132,7 +133,7 @@ public class Enhanced4gLteSliceHelperTest {
when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null);
final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice(
Enhanced4gLteSliceHelper.SLICE_URI);
CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
testEnhanced4gLteSettingsToggleSlice(slice);
@@ -148,7 +149,7 @@ public class Enhanced4gLteSliceHelperTest {
when(mSlicesFeatureProvider.getNewEnhanced4gLteSliceHelper(mContext))
.thenReturn(mEnhanced4gLteSliceHelper);
final Slice slice = mProvider.onBindSlice(Enhanced4gLteSliceHelper.SLICE_URI);
final Slice slice = mProvider.onBindSlice(CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
testEnhanced4gLteSettingsToggleSlice(slice);

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.panel;
import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
import android.content.Intent;
import android.net.Uri;
import java.util.Arrays;
import java.util.List;
/**
* Fake PanelContent for testing.
*/
public class FakePanelContent implements PanelContent {
public static final String FAKE_KEY = "fake_key";
public static final CharSequence TITLE = "title";
public static final List<Uri> SLICE_URIS = Arrays.asList(
WIFI_SLICE_URI
);
public static final Intent INTENT = new Intent();
@Override
public CharSequence getTitle() {
return TITLE;
}
@Override
public List<Uri> getSlices() {
return SLICE_URIS;
}
@Override
public Intent getSeeMoreIntent() {
return INTENT;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.panel;
import android.content.ComponentName;
import android.content.Intent;
public class FakeSettingsPanelActivity extends SettingsPanelActivity {
@Override
public ComponentName getCallingActivity() {
return new ComponentName("fake-package", "fake-class");
}
@Override
public Intent getIntent() {
final Intent intent = new Intent();
intent.putExtra(SettingsPanelActivity.EXTRA_PANEL_TYPE, FakePanelContent.FAKE_KEY);
return intent;
}
}

View File

@@ -21,8 +21,8 @@ import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wifi.WifiSlice;
import org.junit.Before;
import org.junit.Test;
@@ -46,7 +46,12 @@ public class InternetConnectivityPanelTest {
public void getSlices_containsNecessarySlices() {
final List<Uri> uris = mPanel.getSlices();
assertThat(uris).containsExactly(WifiSlice.WIFI_URI,
InternetConnectivityPanel.AIRPLANE_URI);
assertThat(uris).containsExactly(CustomSliceRegistry.WIFI_SLICE_URI,
CustomSliceRegistry.AIRPLANE_URI);
}
@Test
public void getSeeMoreIntent_notNull() {
assertThat(mPanel.getSeeMoreIntent()).isNotNull();
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.panel;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
@RunWith(SettingsRobolectricTestRunner.class)
public class PanelFragmentTest {
private Context mContext;
private PanelFragment mPanelFragment;
private FakeFeatureFactory mFakeFeatureFactory;
private PanelFeatureProvider mPanelFeatureProvider;
private FakePanelContent mFakePanelContent;
private final String FAKE_EXTRA = "fake_extra";
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
mFakePanelContent = new FakePanelContent();
doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
ActivityController<FakeSettingsPanelActivity> activityController =
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
activityController.setup();
mPanelFragment =
spy((PanelFragment)
activityController
.get()
.getSupportFragmentManager()
.findFragmentById(R.id.main_content));
}
@Test
public void onCreateView_adapterGetsDataset() {
final Bundle bundle = new Bundle();
bundle.putString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT, FAKE_EXTRA);
doReturn(bundle).when(mPanelFragment).getArguments();
mPanelFragment.onCreateView(LayoutInflater.from(mContext),
new LinearLayout(mContext), null);
PanelSlicesAdapter adapter = mPanelFragment.mAdapter;
assertThat(adapter.getData()).containsAllIn(mFakePanelContent.getSlices());
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.panel;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.junit.Test;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
@RunWith(SettingsRobolectricTestRunner.class)
public class PanelSlicesAdapterTest {
private Context mContext;
private PanelFragment mPanelFragment;
private FakePanelContent mFakePanelContent;
private FakeFeatureFactory mFakeFeatureFactory;
private PanelFeatureProvider mPanelFeatureProvider;
private PanelSlicesAdapter mAdapter;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
final ActivityController<FakeSettingsPanelActivity> activityController =
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
activityController.setup();
mPanelFragment =
spy((PanelFragment)
activityController
.get()
.getSupportFragmentManager()
.findFragmentById(R.id.main_content));
mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
mFakePanelContent = new FakePanelContent();
doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
mAdapter = new PanelSlicesAdapter(mPanelFragment, mFakePanelContent.getSlices());
}
@Test
public void onCreateViewHolder_returnsSliceRowViewHolder() {
final ViewGroup view = new FrameLayout(mContext);
final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
mAdapter.onCreateViewHolder(view, 0);
assertThat(viewHolder.sliceView).isNotNull();
}
@Test
public void onBindViewHolder_bindsSlice() {
final int position = 0;
final ViewGroup view = new FrameLayout(mContext);
final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
mAdapter.onCreateViewHolder(view, 0 /* view type*/);
mAdapter.onBindViewHolder(viewHolder, position);
assertThat(viewHolder.sliceLiveData).isNotNull();
}
}

View File

@@ -53,6 +53,8 @@ public class SearchFeatureProviderImplTest {
mActivity = Robolectric.setupActivity(Activity.class);
mProvider = new SearchFeatureProviderImpl();
mPackageManager = Shadows.shadowOf(mActivity.getPackageManager());
Settings.Global.putInt(mActivity.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
}
@Test
@@ -82,7 +84,7 @@ public class SearchFeatureProviderImplTest {
@Test
@Config(shadows = ShadowUtils.class)
public void initSearchToolbar_NotHaveResolvedInfo_shouldNotStartActivity() {
public void initSearchToolbar_noResolvedInfo_shouldNotStartActivity() {
final Toolbar toolbar = new Toolbar(mActivity);
// This ensures navigationView is created.
toolbar.setNavigationContentDescription("test");
@@ -90,9 +92,21 @@ public class SearchFeatureProviderImplTest {
toolbar.performClick();
final Intent launchIntent = Shadows.shadowOf(mActivity).getNextStartedActivity();
assertThat(Shadows.shadowOf(mActivity).getNextStartedActivity()).isNull();
}
assertThat(launchIntent).isNull();
@Test
public void initSearchToolbar_deviceNotProvisioned_shouldNotCreateSearchBar() {
final Toolbar toolbar = new Toolbar(mActivity);
// This ensures navigationView is created.
toolbar.setNavigationContentDescription("test");
Settings.Global.putInt(mActivity.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0);
toolbar.performClick();
assertThat(Shadows.shadowOf(mActivity).getNextStartedActivity()).isNull();
}
@Test(expected = IllegalArgumentException.class)

View File

@@ -48,10 +48,6 @@ import androidx.slice.SliceProvider;
import androidx.slice.widget.SliceLiveData;
import com.android.settings.R;
import com.android.settings.bluetooth.BluetoothSliceBuilder;
import com.android.settings.flashlight.FlashlightSliceBuilder;
import com.android.settings.location.LocationSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.testutils.DatabaseTestUtils;
import com.android.settings.testutils.FakeToggleController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -113,14 +109,14 @@ public class SettingsSliceProviderTest {
private SliceManager mManager;
private static final List<Uri> SPECIAL_CASE_PLATFORM_URIS = Arrays.asList(
WifiSlice.WIFI_URI,
BluetoothSliceBuilder.BLUETOOTH_URI,
LocationSliceBuilder.LOCATION_URI
CustomSliceRegistry.WIFI_SLICE_URI,
CustomSliceRegistry.BLUETOOTH_URI,
CustomSliceRegistry.LOCATION_SLICE_URI
);
private static final List<Uri> SPECIAL_CASE_OEM_URIS = Arrays.asList(
ZenModeSliceBuilder.ZEN_MODE_URI,
FlashlightSliceBuilder.FLASHLIGHT_URI
CustomSliceRegistry.ZEN_MODE_SLICE_URI,
CustomSliceRegistry.FLASHLIGHT_SLICE_URI
);
@Before
@@ -472,9 +468,9 @@ public class SettingsSliceProviderTest {
@Test
public void bindSlice_wifiSlice_returnsWifiSlice() {
final Slice wifiSlice = mProvider.onBindSlice(WifiSlice.WIFI_URI);
final Slice wifiSlice = mProvider.onBindSlice(CustomSliceRegistry.WIFI_SLICE_URI);
assertThat(wifiSlice.getUri()).isEqualTo(WifiSlice.WIFI_URI);
assertThat(wifiSlice.getUri()).isEqualTo(CustomSliceRegistry.WIFI_SLICE_URI);
}
@Test
@@ -482,9 +478,10 @@ public class SettingsSliceProviderTest {
Settings.Secure.putInt(
mContext.getContentResolver(), Settings.Secure.FLASHLIGHT_AVAILABLE, 1);
final Slice flashlightSlice = mProvider.onBindSlice(FlashlightSliceBuilder.FLASHLIGHT_URI);
final Slice flashlightSlice = mProvider.onBindSlice(
CustomSliceRegistry.FLASHLIGHT_SLICE_URI);
assertThat(flashlightSlice.getUri()).isEqualTo(FlashlightSliceBuilder.FLASHLIGHT_URI);
assertThat(flashlightSlice.getUri()).isEqualTo(CustomSliceRegistry.FLASHLIGHT_SLICE_URI);
}
@Test
@@ -526,22 +523,22 @@ public class SettingsSliceProviderTest {
@Test
public void onSlicePinned_backgroundWorker_started() {
mProvider.onSlicePinned(WifiSlice.WIFI_URI);
mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
verify(ShadowWifiScanWorker.getWifiTracker()).onStart();
}
@Test
public void onSlicePinned_backgroundWorker_stopped() {
mProvider.onSlicePinned(WifiSlice.WIFI_URI);
mProvider.onSliceUnpinned(WifiSlice.WIFI_URI);
mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
mProvider.onSliceUnpinned(CustomSliceRegistry.WIFI_SLICE_URI);
verify(ShadowWifiScanWorker.getWifiTracker()).onStop();
}
@Test
public void shutdown_backgroundWorker_closed() {
mProvider.onSlicePinned(WifiSlice.WIFI_URI);
mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
mProvider.shutdown();
verify(ShadowWifiScanWorker.getWifiTracker()).onDestroy();

View File

@@ -28,6 +28,7 @@ import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.gestures.AssistGestureFeatureProvider;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.localepicker.LocaleFeatureProvider;
import com.android.settings.overlay.DockUpdaterFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
@@ -62,8 +63,9 @@ public class FakeFeatureFactory extends FeatureFactory {
public final UserFeatureProvider userFeatureProvider;
public final AssistGestureFeatureProvider assistGestureFeatureProvider;
public final AccountFeatureProvider mAccountFeatureProvider;
public final PanelFeatureProvider mPanelFeatureProvider;
public final ContextualCardFeatureProvider mContextualCardFeatureProvider;
public PanelFeatureProvider panelFeatureProvider;
public SlicesFeatureProvider slicesFeatureProvider;
public SearchFeatureProvider searchFeatureProvider;
@@ -104,7 +106,8 @@ public class FakeFeatureFactory extends FeatureFactory {
assistGestureFeatureProvider = mock(AssistGestureFeatureProvider.class);
slicesFeatureProvider = mock(SlicesFeatureProvider.class);
mAccountFeatureProvider = mock(AccountFeatureProvider.class);
mPanelFeatureProvider = mock(PanelFeatureProvider.class);
mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class);
panelFeatureProvider = mock(PanelFeatureProvider.class);
}
@Override
@@ -189,6 +192,10 @@ public class FakeFeatureFactory extends FeatureFactory {
@Override
public PanelFeatureProvider getPanelFeatureProvider() {
return mPanelFeatureProvider;
return panelFeatureProvider;
}
public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
return mContextualCardFeatureProvider;
}
}

Some files were not shown because too many files have changed in this diff Show More