Snap for 4793185 from c96606500f to pi-release

Change-Id: I0a96977ee310814f0b5a3036a08162b71cc8ea39
This commit is contained in:
android-build-team Robot
2018-05-20 07:22:22 +00:00
105 changed files with 2783 additions and 666 deletions

View File

@@ -3137,6 +3137,8 @@
android:value="com.android.settings.accounts.AccountDashboardFragment"/>
<meta-data android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.homepage"/>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
<activity

View File

@@ -93,7 +93,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout-land/choose_lock_pattern.xml"
line="170"
line="178"
column="17"/>
</issue>
@@ -417,22 +417,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=" &lt;color name=&quot;fingerprint_indicator_background_resting&quot;>#12000000&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="51"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -445,7 +429,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="53"
line="52"
column="5"/>
</issue>
@@ -461,7 +445,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="54"
line="53"
column="5"/>
</issue>
@@ -477,7 +461,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="56"
line="55"
column="5"/>
</issue>
@@ -493,7 +477,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="59"
line="58"
column="5"/>
</issue>
@@ -509,7 +493,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="60"
line="59"
column="5"/>
</issue>
@@ -525,7 +509,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="62"
line="61"
column="5"/>
</issue>
@@ -541,7 +525,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="63"
line="62"
column="5"/>
</issue>
@@ -557,7 +541,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="64"
line="63"
column="5"/>
</issue>
@@ -573,7 +557,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="65"
line="64"
column="5"/>
</issue>
@@ -589,7 +573,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="67"
line="66"
column="5"/>
</issue>
@@ -605,7 +589,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="70"
line="69"
column="5"/>
</issue>
@@ -621,7 +605,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="72"
line="71"
column="5"/>
</issue>
@@ -637,7 +621,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="73"
line="72"
column="5"/>
</issue>
@@ -653,7 +637,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="76"
line="75"
column="5"/>
</issue>
@@ -669,7 +653,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="77"
line="76"
column="5"/>
</issue>
@@ -685,7 +669,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="78"
line="77"
column="5"/>
</issue>
@@ -701,7 +685,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="79"
line="78"
column="5"/>
</issue>
@@ -717,7 +701,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="80"
line="79"
column="5"/>
</issue>
@@ -733,7 +717,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="83"
line="82"
column="5"/>
</issue>
@@ -749,7 +733,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="84"
line="83"
column="5"/>
</issue>
@@ -765,7 +749,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="85"
line="84"
column="5"/>
</issue>
@@ -781,7 +765,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="86"
line="85"
column="5"/>
</issue>
@@ -797,7 +781,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="87"
line="86"
column="5"/>
</issue>
@@ -813,7 +797,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="88"
line="87"
column="5"/>
</issue>
@@ -829,7 +813,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="89"
line="88"
column="5"/>
</issue>
@@ -845,7 +829,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="90"
line="89"
column="5"/>
</issue>
@@ -861,7 +845,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="91"
line="90"
column="5"/>
</issue>
@@ -877,7 +861,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="92"
line="91"
column="5"/>
</issue>
@@ -893,7 +877,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="93"
line="92"
column="5"/>
</issue>
@@ -909,7 +893,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="95"
line="94"
column="5"/>
</issue>
@@ -921,11 +905,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;gestures_setting_background_color&quot;>#f4f4f4&lt;/color>"
errorLine1=" &lt;color name=&quot;gestures_setting_background_color&quot;>#ffffff&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="98"
line="97"
column="5"/>
</issue>
@@ -941,7 +925,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="100"
line="99"
column="5"/>
</issue>
@@ -957,7 +941,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="103"
line="102"
column="5"/>
</issue>
@@ -973,7 +957,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="106"
line="105"
column="5"/>
</issue>
@@ -989,7 +973,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="109"
line="108"
column="5"/>
</issue>
@@ -1005,7 +989,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="112"
line="111"
column="5"/>
</issue>
@@ -1021,7 +1005,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="113"
line="112"
column="5"/>
</issue>
@@ -1037,7 +1021,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="116"
line="115"
column="5"/>
</issue>
@@ -1053,7 +1037,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="117"
line="116"
column="5"/>
</issue>
@@ -1069,7 +1053,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="118"
line="117"
column="5"/>
</issue>
@@ -1085,7 +1069,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="119"
line="118"
column="5"/>
</issue>
@@ -1101,7 +1085,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="120"
line="119"
column="5"/>
</issue>
@@ -1117,7 +1101,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="121"
line="120"
column="5"/>
</issue>
@@ -1133,7 +1117,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="122"
line="121"
column="5"/>
</issue>
@@ -1149,7 +1133,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="123"
line="122"
column="5"/>
</issue>
@@ -1165,7 +1149,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="124"
line="123"
column="5"/>
</issue>
@@ -1181,7 +1165,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="125"
line="124"
column="5"/>
</issue>
@@ -1197,7 +1181,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="126"
line="125"
column="5"/>
</issue>
@@ -1213,7 +1197,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="127"
line="126"
column="5"/>
</issue>
@@ -1229,7 +1213,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="128"
line="127"
column="5"/>
</issue>
@@ -1245,7 +1229,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="133"
line="132"
column="5"/>
</issue>
@@ -1261,7 +1245,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="134"
line="133"
column="5"/>
</issue>
@@ -1277,7 +1261,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="135"
line="134"
column="5"/>
</issue>
@@ -1293,7 +1277,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="136"
line="135"
column="5"/>
</issue>
@@ -1309,7 +1293,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="137"
line="136"
column="5"/>
</issue>
@@ -1325,7 +1309,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="138"
line="137"
column="5"/>
</issue>
@@ -1505,38 +1489,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:background=&quot;@color/gestures_setting_background_color&quot;"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/gesture_preference.xml"
line="57"
column="9"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:background=&quot;@color/gestures_setting_background_color&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/gesture_preference.xml"
line="78"
column="17"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -2189,7 +2141,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/radio_info.xml"
line="111"
line="116"
column="13"/>
</issue>
@@ -2205,7 +2157,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/radio_info.xml"
line="141"
line="135"
column="13"/>
</issue>
@@ -2221,7 +2173,23 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/radio_info.xml"
line="279"
line="165"
column="13"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:background=&quot;#000000&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/radio_info.xml"
line="303"
column="13"/>
</issue>
@@ -2401,22 +2369,6 @@
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:background=&quot;@color/suggestion_condition_background&quot;>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/settings_main_dashboard.xml"
line="30"
column="9"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -2477,7 +2429,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rXC/strings.xml"
line="2535"
line="2531"
column="168"/>
</issue>
@@ -2493,7 +2445,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rAU/strings.xml"
line="2536"
line="2532"
column="64"/>
</issue>
@@ -2509,7 +2461,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rCA/strings.xml"
line="2536"
line="2532"
column="64"/>
</issue>
@@ -2525,7 +2477,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rGB/strings.xml"
line="2536"
line="2532"
column="64"/>
</issue>
@@ -2541,7 +2493,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rIN/strings.xml"
line="2536"
line="2532"
column="64"/>
</issue>
@@ -2557,7 +2509,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/strings.xml"
line="5899"
line="5920"
column="36"/>
</issue>
@@ -2573,7 +2525,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="246"
line="248"
column="41"/>
</issue>
@@ -2589,7 +2541,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="436"
line="465"
column="44"/>
</issue>
@@ -2605,7 +2557,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="442"
line="471"
column="44"/>
</issue>
@@ -2621,26 +2573,10 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="443"
line="472"
column="44"/>
</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;android:background&quot;>@color/suggestion_condition_background&lt;/item>"
errorLine2=" ^">
<location
file="res/values/styles.xml"
line="461"
column="41"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -2861,7 +2797,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="348"
line="349"
column="45"/>
</issue>
@@ -2877,7 +2813,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="349"
line="350"
column="49"/>
</issue>
@@ -2893,7 +2829,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="357"
line="358"
column="45"/>
</issue>
@@ -2909,7 +2845,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="358"
line="359"
column="49"/>
</issue>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -16,10 +16,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M24.0,4.0C12.9,4.0 4.0,12.9 4.0,24.0s8.9,20.0 20.0,20.0c11.1,0.0 20.0,-8.9 20.0,-20.0S35.1,4.0 24.0,4.0zM34.0,31.2L31.2,34.0L24.0,26.8L16.8,34.0L14.0,31.2l7.2,-7.2L14.0,16.8l2.8,-2.8l7.2,7.2l7.2,-7.2l2.8,2.8L26.8,24.0L34.0,31.2z"/>
android:pathData="M12,2C6.47,2 2,6.47 2,12c0,5.53 4.47,10 10,10c5.53,0 10,-4.47 10,-10C22,6.47 17.53,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20z"/>
<path
android:fillColor="#FF000000"
android:pathData="M15.59,7l-3.59,3.59l-3.59,-3.59l-1.41,1.41l3.59,3.59l-3.59,3.59l1.41,1.41l3.59,-3.59l3.59,3.59l1.41,-1.41l-3.59,-3.59l3.59,-3.59z"/>
</vector>

View File

@@ -21,11 +21,6 @@
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M1 18v2c0 .55 .45 1 1 1h2c0-1.66-1.34-3-3-3zm0-2.94c-.01 .51 .32 .93 .82 1.02
2.08 .36 3.74 2 4.1 4.08 .09 .48 .5 .84 .99 .84 .61 0 1.09-.54 1-1.14a6.996
6.996 0 0 0-5.8-5.78c-.59-.09-1.09 .38 -1.11 .98 zm0-4.03c-.01 .52 .34 .96 .85
1.01 4.26 .43 7.68 3.82 8.1 8.08 .05 .5 .48 .88 .99 .88 .59 0 1.06-.51
1-1.1-.52-5.21-4.66-9.34-9.87-9.85-.57-.05-1.05 .4 -1.07 .98 zM21 3H3c-1.1 0-2
.9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/>
android:fillColor="#FF000000"
android:pathData="M21,3H3C1.9,3 1,3.9 1,5v3h2V5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2V5C23,3.9 22.1,3 21,3zM1,18v3h3C4,19.34 2.66,18 1,18zM1,14v2c2.76,0 5,2.24 5,5h2C8,17.13 4.87,14 1,14zM1,10v2c4.97,0 9,4.03 9,9h2C12,14.92 7.07,10 1,10z"/>
</vector>

View File

@@ -16,10 +16,16 @@ Copyright (C) 2015 The Android Open Source Project
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24.0dp"
android:height="24.0dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12.0,38.0c0.0,2.21 1.79,4.0 4.0,4.0l16.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L36.0,14.0L12.0,14.0l0.0,24.0zM38.0,8.0l-7.0,0.0l-2.0,-2.0L19.0,6.0l-2.0,2.0l-7.0,0.0l0.0,4.0l28.0,0.0L38.0,8.0z"/>
android:fillColor="#FF000000"
android:pathData="M15,4V3H9v1H4v2h1v13c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V6h1V4H15zM17,19H7V6h10V19z"/>
<path
android:fillColor="#FF000000"
android:pathData="M9,8h2v9h-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M13,8h2v9h-2z"/>
</vector>

View File

@@ -21,5 +21,5 @@
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M11.4,1.02C6.62,1.33 3,5.52 3,10.31v5.89C3,18.66 4.34,20 6,20h2c0.55,0 1,-0.45 1,-1v-6c0,-0.55 -0.45,-1 -1,-1H5v-1.71C5,6.45 7.96,3.11 11.79,3 15.76,2.89 19,6.06 19,10v2h-3c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h2c1.66,0 3,-1.34 3,-3v-7c0,-5.17 -4.36,-9.32 -9.6,-8.98z"/>
android:pathData="M19,15v3c0,0.55 -0.45,1 -1,1h-1v-4H19M7,15v4H6c-0.55,0 -1,-0.45 -1,-1v-3H7M12,2c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,-3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h3c1.66,0 3,-1.34 3,-3v-7C21,6.03 16.97,2 12,2L12,2z"/>
</vector>

View File

@@ -19,11 +19,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 16.81c-.72
0-1.3-.58-1.3-1.3s.58-1.3 1.3-1.3 1.3 .58 1.3 1.3-.58 1.3-1.3
1.3zm1.07-4.62c-.09 .52 -.59 .87 -1.13 .79 -.57-.08-.94-.66-.83-1.23 .52 -2.61
2.66-2.84 2.87-4.5 .12 -.96-.42-1.87-1.34-2.17-1.04-.33-2.21 .16 -2.55 1.37-.12
.45 -.52 .74 -.97 .74 -.66 0-1.13-.63-.96-1.27 .63 -2.25 2.91-3.38 5.05-2.74
1.71 .51 2.84 2.16 2.78 3.95-.07 2.44-2.49 2.61-2.92 5.06z"
android:fillColor="#FFFFFFFF"/>
android:fillColor="#FFFFFFFF"
android:pathData="M11,18h2v-2h-2V18zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20zM12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5C16,7.79 14.21,6 12,6z"/>
</vector>

View File

@@ -22,11 +22,11 @@
android:tint="?android:attr/textColorSecondary">
<path
android:fillColor="#FF000000"
android:pathData="M12,17L12,17c0.55,0 1,-0.45 1,-1v-4c0,-0.55 -0.45,-1 -1,-1l0,0c-0.55,0 -1,0.45 -1,1v4C11,16.55 11.45,17 12,17z"/>
android:pathData="M11,7h2v2h-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M12,2c-5.52,0 -10,4.48 -10,10s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20z"/>
android:pathData="M11,11h2v6h-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M12,9.1L12,9.1c0.61,0 1.1,-0.49 1.1,-1.1l0,0c0,-0.61 -0.49,-1.1 -1.1,-1.1l0,0c-0.61,0 -1.1,0.49 -1.1,1.1l0,0C10.9,8.61 11.39,9.1 12,9.1z"/>
android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10s10,-4.48 10,-10C22,6.48 17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8c0,-4.41 3.59,-8 8,-8s8,3.59 8,8C20,16.41 16.41,20 12,20z"/>
</vector>

View File

@@ -1,25 +0,0 @@
<!--
Copyright (C) 2015 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12.0,38.0c0.0,2.21 1.79,4.0 4.0,4.0l16.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L36.0,14.0L12.0,14.0l0.0,24.0zM38.0,8.0l-7.0,0.0l-2.0,-2.0L19.0,6.0l-2.0,2.0l-7.0,0.0l0.0,4.0l28.0,0.0L38.0,8.0z"/>
</vector>

View File

@@ -21,11 +21,11 @@
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M12,17L12,17c0.55,0 1,-0.45 1,-1v-4c0,-0.55 -0.45,-1 -1,-1l0,0c-0.55,0 -1,0.45 -1,1v4C11,16.55 11.45,17 12,17z"/>
android:pathData="M11,7h2v2h-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M12,2c-5.52,0 -10,4.48 -10,10s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20z"/>
android:pathData="M11,11h2v6h-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M12,9.1L12,9.1c0.61,0 1.1,-0.49 1.1,-1.1l0,0c0,-0.61 -0.49,-1.1 -1.1,-1.1l0,0c-0.61,0 -1.1,0.49 -1.1,1.1l0,0C10.9,8.61 11.39,9.1 12,9.1z"/>
android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10s10,-4.48 10,-10C22,6.48 17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8c0,-4.41 3.59,-8 8,-8s8,3.59 8,8C20,16.41 16.41,20 12,20z"/>
</vector>

View File

@@ -20,11 +20,11 @@
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M12,17L12,17c0.55,0 1,-0.45 1,-1v-4c0,-0.55 -0.45,-1 -1,-1l0,0c-0.55,0 -1,0.45 -1,1v4C11,16.55 11.45,17 12,17z"/>
android:pathData="M11,7h2v2h-2z"/>
<path
android:fillColor="#FFFFFF"
android:pathData="M12,2c-5.52,0 -10,4.48 -10,10s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20z"/>
android:pathData="M11,11h2v6h-2z"/>
<path
android:fillColor="#FFFFFF"
android:pathData="M12,9.1L12,9.1c0.61,0 1.1,-0.49 1.1,-1.1l0,0c0,-0.61 -0.49,-1.1 -1.1,-1.1l0,0c-0.61,0 -1.1,0.49 -1.1,1.1l0,0C10.9,8.61 11.39,9.1 12,9.1z"/>
android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10s10,-4.48 10,-10C22,6.48 17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8c0,-4.41 3.59,-8 8,-8s8,3.59 8,8C20,16.41 16.41,20 12,20z"/>
</vector>

View File

@@ -71,7 +71,7 @@
android:singleLine="true"
android:ellipsize="end"
android:textAppearance="@style/TextAppearance.SuggestionTitle"
android:textColor="?android:attr/colorAccent" />
android:textColor="?android:attr/textColorPrimary" />
<LinearLayout
android:id="@+id/additional_icons"

View File

@@ -25,6 +25,7 @@
android:id="@+id/owner_info_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/min_tap_target_size"
android:gravity="top"
android:hint="@string/owner_info_settings_edit_text_hint"
android:inputType="textMultiLine|textCapSentences"

View File

@@ -52,7 +52,7 @@
android:layout_height="fill_parent"
android:paddingStart="16dip"
android:paddingEnd="16dip"
android:src="@drawable/ic_menu_delete"
android:src="@drawable/ic_delete"
android:contentDescription="@string/user_delete_user_description"
android:layout_gravity="center"
android:background="?android:attr/selectableItemBackground" />

View File

@@ -85,7 +85,7 @@
android:layout_height="fill_parent"
android:paddingStart="16dip"
android:paddingEnd="16dip"
android:src="@drawable/ic_menu_delete"
android:src="@drawable/ic_delete"
android:contentDescription="@string/user_delete_user_description"
android:layout_gravity="center"
android:background="?android:attr/selectableItemBackground" />

View File

@@ -291,7 +291,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/wifi_item_content"
android:textSize="14sp"
android:text="@string/wifi_show_password" />
</LinearLayout>
</LinearLayout>

View File

@@ -25,8 +25,8 @@
android:layout_height="fill_parent"
android:paddingStart="16dip"
android:paddingEnd="16dip"
android:src="@drawable/ic_menu_delete"
android:src="@drawable/ic_delete"
android:contentDescription="@string/zen_mode_delete_rule"
android:layout_gravity="center"
android:background="?android:attr/selectableItemBackground" />
</LinearLayout>
</LinearLayout>

View File

@@ -17,7 +17,7 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_delete"
android:title="@string/delete"
android:icon="@android:drawable/ic_menu_delete"/>
android:icon="@drawable/ic_delete"/>
<item android:id="@+id/action_select_all"
android:title="@string/select_all"
android:showAsAction="ifRoom" />

Binary file not shown.

View File

@@ -235,6 +235,22 @@
<item>@string/wifi_security_psk_generic</item>
</string-array>
<!-- Security types for wireless tether -->
<string-array name="wifi_tether_security">
<!-- Do not translate. -->
<item>@string/wifi_security_wpa2</item>
<!-- Do not translate. -->
<item>@string/wifi_security_none</item>
</string-array>
<!-- Values for security type for wireless tether -->
<string-array name="wifi_tether_security_values">
<!-- Do not translate. -->
<item>4</item>
<!-- Do not translate. -->
<item>0</item>
</string-array>
<!-- Match this with the constants in WifiDialog. --> <skip />
<!-- Wi-Fi settings. The type of EAP method a Wi-Fi network has. -->
<string-array name="wifi_eap_method">

View File

@@ -44,6 +44,9 @@
<!-- Whether to show Camera laser sensor switch in Developer Options -->
<bool name="config_show_camera_laser_sensor">false</bool>
<!-- Whether to show logical camera default switch in Developer Options -->
<bool name="config_show_logical_camera_default">false</bool>
<!-- Whether to show Connected MAC Randomization in Developer Options
as not all devices can support dynamic MAC address change. -->
<bool name="config_wifi_support_connected_mac_randomization">false</bool>
@@ -131,4 +134,7 @@
<!-- List of a11y components on the device allowed to be enabled by Settings Slices -->
<string-array name="config_settings_slices_accessibility_components" translatable="false"/>
<!-- Whether or not to show the night light suggestion. -->
<bool name="config_night_light_suggestion_enabled">true</bool>
</resources>

View File

@@ -402,6 +402,17 @@
<!-- Summary for bluetooth item in connection detail page. (phone)-->
<string name="bluetooth_pref_summary" product="default">Allow your phone to communicate with nearby Bluetooth devices</string>
<!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=40] -->
<string name="bluetooth_disable_a2dp_hw_offload">Disable Bluetooth A2DP hardware offload</string>
<!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=20] -->
<string name="bluetooth_disable_a2dp_hw_offload_dialog_title">Restart Device?</string>
<!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=60] -->
<string name="bluetooth_disable_a2dp_hw_offload_dialog_message">You need to restart your device to change this setting.</string>
<!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=10] -->
<string name="bluetooth_disable_a2dp_hw_offload_dialog_confirm">Restart</string>
<!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=10] -->
<string name="bluetooth_disable_a2dp_hw_offload_dialog_cancel">Cancel</string>
<!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]-->
<string name="connected_device_available_media_title">Available media devices</string>
<!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]-->
@@ -9113,6 +9124,9 @@
<!-- Title for Camera laser sensor switch [CHAR LIMIT=NONE] -->
<string name="camera_laser_sensor_switch">Camera Laser Sensor</string>
<!-- Title for logical camera default switch [CHAR LIMIT=NONE] -->
<string name="logical_camera_default_switch">Logical Camera As Default</string>
<!-- Title of the setting to disable the automatic update -->
<string name="ota_disable_automatic_update">Automatic system updates</string>

View File

@@ -200,6 +200,7 @@
<item name="android:textAlignment">viewStart</item>
<item name="android:textAppearance">@android:style/TextAppearance.Material.Subhead</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:minHeight">@dimen/min_tap_target_size</item>
</style>
<style name="wifi_item_spinner" parent="wifi_item_content">
@@ -219,6 +220,7 @@
<item name="android:layout_marginStart">4dip</item>
<item name="android:textSize">18sp</item>
<item name="android:textAlignment">viewStart</item>
<item name="android:minHeight">@dimen/min_tap_target_size</item>
</style>
<style name="wifi_section">
@@ -285,6 +287,7 @@
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
<item name="android:singleLine">true</item>
<item name="android:textAlignment">viewStart</item>
<item name="android:minHeight">@dimen/min_tap_target_size</item>
</style>
<style name="vpn_warning">

View File

@@ -284,6 +284,7 @@
<style name="Widget.SwitchBar.Switch" parent="@android:style/Widget.Material.CompoundButton.Switch">
<item name="android:trackTint">@color/switchbar_switch_track_tint</item>
<item name="android:thumbTint">@color/switchbar_switch_thumb_tint</item>
<item name="android:minHeight">@dimen/min_tap_target_size</item>
</style>
<style name="Theme.CryptKeeper" parent="@android:style/Theme.Material.NoActionBar">

View File

@@ -16,12 +16,14 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/bluetooth_pairing_pref_title">
<Preference
android:key="bt_pair_rename_devices"
android:title="@string/bluetooth_device_name"
android:summary="@string/summary_placeholder" />
android:summary="@string/summary_placeholder"
settings:controller="com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController"/>
<com.android.settings.bluetooth.BluetoothProgressCategory
android:key="available_devices"

View File

@@ -19,6 +19,12 @@
android:key="bluetooth_switchbar_screen"
android:title="@string/bluetooth_settings_title">
<Preference
android:key="bluetooth_screen_bt_pair_rename_devices"
android:title="@string/bluetooth_device_name"
android:summary="@string/summary_placeholder"
settings:controller="com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController"/>
<com.android.settingslib.RestrictedPreference
android:key="bluetooth_screen_add_bt_devices"
android:title="@string/bluetooth_pairing_pref_title"

View File

@@ -46,26 +46,13 @@
android:title="@string/connected_device_previously_connected_title"
android:icon="@drawable/ic_devices_other_black"
android:fragment="com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment"
settings:allowDividerAbove="true"/>
<Preference
android:fragment="com.android.settings.connecteddevice.BluetoothDashboardFragment"
android:key="bluetooth_settings"
android:title="@string/bluetooth_settings_title"
android:icon="@drawable/ic_settings_bluetooth"/>
<PreferenceCategory
android:key="dashboard_tile_placeholder" />
<SwitchPreference
android:key="toggle_nfc"
android:title="@string/nfc_quick_toggle_title"
android:icon="@drawable/ic_nfc"
android:summary="@string/nfc_quick_toggle_summary"/>
settings:allowDividerAbove="true"
settings:controller="com.android.settings.connecteddevice.PreviouslyConnectedDevicePreferenceController"/>
<Preference
android:key="connection_preferences"
android:title="@string/connected_device_connections_title"
android:fragment="com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment"/>
android:fragment="com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment"
settings:controller="com.android.settings.connecteddevice.AdvancedConnectedDeviceController"/>
</PreferenceScreen>

View File

@@ -20,12 +20,26 @@
android:key="connected_devices_advanced_screen"
android:title="@string/connected_device_connections_title">
<Preference
android:fragment="com.android.settings.connecteddevice.BluetoothDashboardFragment"
android:key="bluetooth_settings"
android:title="@string/bluetooth_settings_title"
android:icon="@drawable/ic_settings_bluetooth"
android:order="-9"/>
<SwitchPreference
android:key="toggle_nfc"
android:title="@string/nfc_quick_toggle_title"
android:icon="@drawable/ic_nfc"
android:summary="@string/nfc_quick_toggle_summary"
android:order="-7"/>
<com.android.settingslib.RestrictedPreference
android:fragment="com.android.settings.nfc.AndroidBeam"
android:key="android_beam_settings"
android:title="@string/android_beam_settings_title"
android:icon="@drawable/ic_android"
android:order="-4"/>
android:order="-6"/>
<SwitchPreference
android:key="bluetooth_on_while_driving"
@@ -33,7 +47,7 @@
android:icon="@drawable/ic_settings_bluetooth"
android:summary="@string/bluetooth_on_while_driving_summary"
settings:controller="com.android.settings.connecteddevice.BluetoothOnWhileDrivingPreferenceController"
android:order="-2"/>
android:order="-4"/>
<com.android.settingslib.RestrictedPreference
android:key="connected_device_printing"
@@ -41,7 +55,7 @@
android:summary="@string/summary_placeholder"
android:icon="@drawable/ic_settings_print"
android:fragment="com.android.settings.print.PrintSettingsFragment"
android:order="-1"/>
android:order="-3"/>
<Preference
android:key="bt_received_files"
@@ -50,6 +64,6 @@
<PreferenceCategory
android:key="dashboard_tile_placeholder"
android:order="50"/>
android:order="-8"/>
</PreferenceScreen>

View File

@@ -192,6 +192,10 @@
android:key="camera_laser_sensor_switch"
android:title="@string/camera_laser_sensor_switch" />
<SwitchPreference
android:key="logical_camera_default_switch"
android:title="@string/logical_camera_default_switch" />
<Preference
android:key="feature_flags_dashboard"
android:title="@string/feature_flags_dashboard_title"
@@ -254,6 +258,10 @@
android:title="@string/bluetooth_disable_absolute_volume"
android:summary="@string/bluetooth_disable_absolute_volume_summary" />
<SwitchPreference
android:key="bluetooth_disable_a2dp_hw_offload"
android:title="@string/bluetooth_disable_a2dp_hw_offload" />
<ListPreference
android:key="bluetooth_select_avrcp_version"
android:title="@string/bluetooth_select_avrcp_version_string"

View File

@@ -109,8 +109,7 @@
android:dialogTitle="@string/ringtone_title"
android:summary="@string/summary_placeholder"
android:ringtoneType="ringtone"
android:order="-100"
settings:allowDividerAbove="true"/>
android:order="-100"/>
<!-- Default notification ringtone -->
<com.android.settings.DefaultRingtonePreference

View File

@@ -43,7 +43,7 @@
<com.android.settingslib.RestrictedPreference
android:key="forget_vpn"
android:title="@string/vpn_forget_long"
android:icon="@drawable/ic_menu_delete"
android:icon="@drawable/ic_delete"
settings:userRestriction="no_config_vpn"
settings:useAdminDisabledSummary="true" />
</PreferenceScreen>

View File

@@ -19,13 +19,20 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/wifi_hotspot_checkbox_text"
settings:initialExpandedChildrenCount="2">
settings:initialExpandedChildrenCount="3">
<com.android.settings.widget.ValidatedEditTextPreference
android:key="wifi_tether_network_name"
android:title="@string/wifi_hotspot_name_title"
android:summary="@string/summary_placeholder" />
<ListPreference
android:key="wifi_tether_security"
android:title="@string/wifi_security"
android:summary="@string/summary_placeholder"
android:entries="@array/wifi_tether_security"
android:entryValues="@array/wifi_tether_security_values" />
<com.android.settings.widget.ValidatedEditTextPreference
android:key="wifi_tether_network_password"
android:persistent="false"
@@ -34,7 +41,7 @@
<SwitchPreference
android:key="wifi_tether_auto_turn_off"
android:title="@string/wifi_hotspot_auto_off_title"
android:summary="@string/wifi_hotspot_auto_off_summary"/>
android:summary="@string/wifi_hotspot_auto_off_summary" />
<com.android.settings.widget.HotspotApBandSelectionPreference
android:key="wifi_tether_network_ap_band"
@@ -42,5 +49,5 @@
android:dialogLayout="@layout/hotspot_ap_band_selection_dialog"
android:dialogTitle="@string/wifi_hotspot_ap_band_title"
android:negativeButtonText="@string/cancel"
android:positiveButtonText="@string/apply"/>
android:positiveButtonText="@string/apply" />
</PreferenceScreen>

View File

@@ -361,7 +361,7 @@ public class AccountPreferenceController extends AbstractPreferenceController
RestrictedPreference preference = new RestrictedPreference(
mParent.getPreferenceManager().getContext());
preference.setTitle(R.string.remove_managed_profile_label);
preference.setIcon(R.drawable.ic_menu_delete);
preference.setIcon(R.drawable.ic_delete);
preference.setOnPreferenceClickListener(this);
preference.setOrder(ORDER_LAST);
return preference;

View File

@@ -32,7 +32,6 @@ import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
@@ -44,16 +43,16 @@ public class BluetoothDeviceNamePreferenceController extends BasePreferenceContr
LifecycleObserver, OnStart, OnStop {
private static final String TAG = "BluetoothNamePrefCtrl";
public static final String KEY_DEVICE_NAME = "device_name";
@VisibleForTesting
Preference mPreference;
private LocalBluetoothManager mLocalManager;
private LocalBluetoothAdapter mLocalAdapter;
public BluetoothDeviceNamePreferenceController(Context context, Lifecycle lifecycle) {
this(context, (LocalBluetoothAdapter) null);
/**
* Constructor exclusively used for Slice.
*/
public BluetoothDeviceNamePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mLocalManager = Utils.getLocalBtManager(context);
if (mLocalManager == null) {
@@ -61,22 +60,12 @@ public class BluetoothDeviceNamePreferenceController extends BasePreferenceContr
return;
}
mLocalAdapter = mLocalManager.getBluetoothAdapter();
if (lifecycle != null) {
lifecycle.addObserver(this);
}
}
/**
* Constructor exclusively used for Slice.
*/
public BluetoothDeviceNamePreferenceController(Context context) {
this(context, (Lifecycle) null);
}
@VisibleForTesting
BluetoothDeviceNamePreferenceController(Context context, LocalBluetoothAdapter localAdapter) {
super(context, KEY_DEVICE_NAME);
BluetoothDeviceNamePreferenceController(Context context, LocalBluetoothAdapter localAdapter,
String preferenceKey) {
super(context, preferenceKey);
mLocalAdapter = localAdapter;
}
@@ -102,11 +91,6 @@ public class BluetoothDeviceNamePreferenceController extends BasePreferenceContr
return mLocalAdapter != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public String getPreferenceKey() {
return KEY_DEVICE_NAME;
}
@Override
public void updateState(Preference preference) {
updateDeviceName(preference);
@@ -134,7 +118,7 @@ public class BluetoothDeviceNamePreferenceController extends BasePreferenceContr
public Preference createBluetoothDeviceNamePreference(PreferenceScreen screen, int order) {
mPreference = new Preference(screen.getContext());
mPreference.setOrder(order);
mPreference.setKey(KEY_DEVICE_NAME);
mPreference.setKey(getPreferenceKey());
screen.addPreference(mPreference);
return mPreference;

View File

@@ -26,44 +26,35 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class BluetoothDeviceRenamePreferenceController extends
BluetoothDeviceNamePreferenceController {
private final Fragment mFragment;
private String mPrefKey;
private Fragment mFragment;
private MetricsFeatureProvider mMetricsFeatureProvider;
public BluetoothDeviceRenamePreferenceController(Context context, String prefKey,
Fragment fragment, Lifecycle lifecycle) {
super(context, lifecycle);
mPrefKey = prefKey;
mFragment = fragment;
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
/**
* Constructor exclusively used for Slice.
*/
public BluetoothDeviceRenamePreferenceController(Context context, String prefKey) {
super(context, (Lifecycle) null);
mPrefKey = prefKey;
mFragment = null;
}
@VisibleForTesting
BluetoothDeviceRenamePreferenceController(Context context, String prefKey, Fragment fragment,
LocalBluetoothAdapter localAdapter) {
super(context, localAdapter);
mPrefKey = prefKey;
mFragment = fragment;
public BluetoothDeviceRenamePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
@Override
public String getPreferenceKey() {
return mPrefKey;
@VisibleForTesting
BluetoothDeviceRenamePreferenceController(Context context, LocalBluetoothAdapter localAdapter,
String preferenceKey) {
super(context, localAdapter, preferenceKey);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
/**
* Set the {@link Fragment} that used to show {@link LocalDeviceNameDialogFragment}
* in {@code handlePreferenceTreeClick}
*/
@VisibleForTesting
public void setFragment(Fragment fragment) {
mFragment = fragment;
}
@Override
@@ -78,7 +69,7 @@ public class BluetoothDeviceRenamePreferenceController extends
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (TextUtils.equals(mPrefKey, preference.getKey()) && mFragment != null) {
if (TextUtils.equals(getPreferenceKey(), preference.getKey()) && mFragment != null) {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_BLUETOOTH_RENAME);
LocalDeviceNameDialogFragment.newInstance()

View File

@@ -30,12 +30,8 @@ import com.android.settings.R;
import com.android.settings.search.Indexable;
import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.widget.FooterPreference;
import java.util.ArrayList;
import java.util.List;
/**
* BluetoothPairingDetail is a page to scan bluetooth devices and pair them.
*/
@@ -47,7 +43,6 @@ public class BluetoothPairingDetail extends DeviceListPreferenceFragment impleme
static final String KEY_AVAIL_DEVICES = "available_devices";
@VisibleForTesting
static final String KEY_FOOTER_PREF = "footer_preference";
private static final String KEY_RENAME_DEVICES = "bt_pair_rename_devices";
@VisibleForTesting
BluetoothProgressCategory mAvailableDevicesCategory;
@@ -80,6 +75,12 @@ public class BluetoothPairingDetail extends DeviceListPreferenceFragment impleme
mAvailableDevicesCategory.setProgress(mLocalAdapter.isDiscovering());
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
use(BluetoothDeviceRenamePreferenceController.class).setFragment(this);
}
@VisibleForTesting
void updateBluetooth() {
if (mLocalAdapter.isEnabled()) {
@@ -199,16 +200,6 @@ public class BluetoothPairingDetail extends DeviceListPreferenceFragment impleme
return R.xml.bluetooth_pairing_detail;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(
new BluetoothDeviceRenamePreferenceController(context, KEY_RENAME_DEVICES, this,
getLifecycle()));
return controllers;
}
@Override
public String getDeviceListKey() {
return KEY_AVAIL_DEVICES;

View File

@@ -0,0 +1,81 @@
/*
* Copyright 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.connecteddevice;
import android.content.Context;
import android.support.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.nfc.NfcPreferenceController;
/**
* Controller that used to show which component is available
*/
public class AdvancedConnectedDeviceController extends BasePreferenceController {
public AdvancedConnectedDeviceController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public CharSequence getSummary() {
return mContext.getText(getConnectedDevicesSummaryResourceId(mContext));
}
/**
* Get Connected Devices summary that depend on {@link NfcPreferenceController} or
* diving mode are available
*/
public static int getConnectedDevicesSummaryResourceId(Context context) {
final NfcPreferenceController nfcPreferenceController =
new NfcPreferenceController(context);
final boolean isDrivingModeAvailable = false;
return getConnectedDevicesSummaryResourceId(nfcPreferenceController,
isDrivingModeAvailable);
}
@VisibleForTesting
static int getConnectedDevicesSummaryResourceId(NfcPreferenceController
nfcPreferenceController, boolean isDrivingModeAvailable) {
final int resId;
if (nfcPreferenceController.isAvailable()) {
if (isDrivingModeAvailable) {
// NFC available, driving mode available
resId = R.string.connected_devices_dashboard_summary;
} else {
// NFC available, driving mode not available
resId = R.string.connected_devices_dashboard_no_driving_mode_summary;
}
} else {
if (isDrivingModeAvailable) {
// NFC not available, driving mode available
resId = R.string.connected_devices_dashboard_no_nfc_summary;
} else {
// NFC not available, driving mode not available
resId = R.string.connected_devices_dashboard_no_driving_mode_no_nfc_summary;
}
}
return resId;
}
}

View File

@@ -24,6 +24,7 @@ import com.android.settings.R;
import com.android.settings.bluetooth.BluetoothFilesPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.nfc.AndroidBeamPreferenceController;
import com.android.settings.nfc.NfcPreferenceController;
import com.android.settings.print.PrintSettingPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -78,10 +79,16 @@ public class AdvancedConnectedDeviceDashboardFragment extends DashboardFragment
final PrintSettingPreferenceController printerController =
new PrintSettingPreferenceController(context);
final NfcPreferenceController nfcPreferenceController =
new NfcPreferenceController(context);
if (lifecycle != null) {
lifecycle.addObserver(beamPreferenceController);
lifecycle.addObserver(printerController);
lifecycle.addObserver(nfcPreferenceController);
}
controllers.add(nfcPreferenceController);
controllers.add(printerController);
return controllers;

View File

@@ -24,6 +24,7 @@ import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController;
import com.android.settings.bluetooth.BluetoothSwitchPreferenceController;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.TogglePreferenceController;
@@ -78,6 +79,12 @@ public class BluetoothDashboardFragment extends DashboardFragment {
mFooterPreference = mFooterPreferenceMixin.createFooterPreference();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
use(BluetoothDeviceRenamePreferenceController.class).setFragment(this);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

View File

@@ -26,10 +26,7 @@ import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.nfc.NfcPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -62,30 +59,12 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
return R.xml.connected_devices;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context, getLifecycle());
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
final NfcPreferenceController nfcPreferenceController =
new NfcPreferenceController(context);
controllers.add(nfcPreferenceController);
if (lifecycle != null) {
lifecycle.addObserver(nfcPreferenceController);
}
return controllers;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
use(AvailableMediaDeviceGroupController.class).init(this);
use(ConnectedDeviceGroupController.class).init(this);
use(PreviouslyConnectedDevicePreferenceController.class).init(this);
}
@VisibleForTesting
@@ -138,12 +117,6 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
return Arrays.asList(sir);
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(Context
context) {
return buildPreferenceControllers(context, null /* lifecycle */);
}
@Override
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context);

View File

@@ -0,0 +1,110 @@
/*
* Copyright 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.connecteddevice;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.SavedBluetoothDeviceUpdater;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.utils.ThreadUtils;
public class PreviouslyConnectedDevicePreferenceController extends BasePreferenceController
implements LifecycleObserver, OnStart, OnStop, DevicePreferenceCallback {
private Preference mPreference;
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
private int mPreferenceSize;
public PreviouslyConnectedDevicePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
? AVAILABLE
: CONDITIONALLY_UNAVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
if (isAvailable()) {
mPreference = screen.findPreference(getPreferenceKey());
mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
}
}
@Override
public void onStart() {
mBluetoothDeviceUpdater.registerCallback();
updatePreferenceOnSizeChanged();
}
@Override
public void onStop() {
mBluetoothDeviceUpdater.unregisterCallback();
}
public void init(DashboardFragment fragment) {
mBluetoothDeviceUpdater = new SavedBluetoothDeviceUpdater(fragment.getContext(),
fragment, PreviouslyConnectedDevicePreferenceController.this);
}
@Override
public void onDeviceAdded(Preference preference) {
mPreferenceSize++;
updatePreferenceOnSizeChanged();
}
@Override
public void onDeviceRemoved(Preference preference) {
mPreferenceSize--;
updatePreferenceOnSizeChanged();
}
@VisibleForTesting
void setBluetoothDeviceUpdater(BluetoothDeviceUpdater bluetoothDeviceUpdater) {
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
}
@VisibleForTesting
void setPreferenceSize(int size) {
mPreferenceSize = size;
}
@VisibleForTesting
void setPreference(Preference preference) {
mPreference = preference;
}
private void updatePreferenceOnSizeChanged() {
if (isAvailable()) {
mPreference.setEnabled(mPreferenceSize != 0);
}
}
}

View File

@@ -15,6 +15,7 @@ package com.android.settings.core;
import android.annotation.IntDef;
import android.content.Context;
import android.content.IntentFilter;
import android.text.TextUtils;
import android.util.Log;
@@ -220,6 +221,14 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
return SliceData.SliceType.INTENT;
}
/**
* @return an {@link IntentFilter} that includes all broadcasts which can affect the state of
* this Setting.
*/
public IntentFilter getIntentFilter() {
return null;
}
/**
* Updates non-indexable keys for search provider.
*

View File

@@ -0,0 +1,82 @@
/*
* Copyright 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.os.SystemProperties;
import android.support.annotation.VisibleForTesting;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
public class BluetoothA2dpHwOffloadPreferenceController extends DeveloperOptionsPreferenceController
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
private static final String PREFERENCE_KEY = "bluetooth_disable_a2dp_hw_offload";
private final DevelopmentSettingsDashboardFragment mFragment;
static final String A2DP_OFFLOAD_DISABLED_PROPERTY = "persist.bluetooth.a2dp_offload.disabled";
static final String A2DP_OFFLOAD_SUPPORTED_PROPERTY = "ro.bluetooth.a2dp_offload.supported";
public BluetoothA2dpHwOffloadPreferenceController(Context context,
DevelopmentSettingsDashboardFragment fragment) {
super(context);
mFragment = fragment;
}
@Override
public String getPreferenceKey() {
return PREFERENCE_KEY;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
BluetoothA2dpHwOffloadRebootDialog.show(mFragment, this);
return false;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
final boolean offloadSupported =
SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false);
if (offloadSupported) {
final boolean offloadDisabled =
SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
((SwitchPreference) mPreference).setChecked(offloadDisabled);
} else {
mPreference.setEnabled(false);
((SwitchPreference) mPreference).setChecked(true);
}
}
@Override
protected void onDeveloperOptionsSwitchDisabled() {
super.onDeveloperOptionsSwitchDisabled();
((SwitchPreference) mPreference).setChecked(true);
SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, "true");
}
public void onA2dpHwDialogConfirmed() {
final boolean offloadDisabled =
SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(!offloadDisabled));
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 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.app.AlertDialog;
import android.app.Dialog;
import android.app.FragmentManager;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.PowerManager;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public class BluetoothA2dpHwOffloadRebootDialog extends InstrumentedDialogFragment
implements DialogInterface.OnClickListener {
public static final String TAG = "BluetoothA2dpHwOffloadReboot";
public static void show(DevelopmentSettingsDashboardFragment host,
BluetoothA2dpHwOffloadPreferenceController controller) {
final FragmentManager manager = host.getActivity().getFragmentManager();
if (manager.findFragmentByTag(TAG) == null) {
final BluetoothA2dpHwOffloadRebootDialog dialog =
new BluetoothA2dpHwOffloadRebootDialog();
dialog.setTargetFragment(host, 0 /* requestCode */);
dialog.show(manager, TAG);
}
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DIALOG_BLUETOOTH_DISABLE_A2DP_HW_OFFLOAD;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setMessage(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message)
.setTitle(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title)
.setPositiveButton(
R.string.bluetooth_disable_a2dp_hw_offload_dialog_confirm, this)
.setNegativeButton(
R.string.bluetooth_disable_a2dp_hw_offload_dialog_cancel, this)
.create();
}
@Override
public void onClick(DialogInterface dialog, int which) {
final OnA2dpHwDialogConfirmedListener host =
(OnA2dpHwDialogConfirmedListener) getTargetFragment();
if (host == null) {
return;
}
if (which == DialogInterface.BUTTON_POSITIVE) {
host.onA2dpHwDialogConfirmed();
PowerManager pm = getContext().getSystemService(PowerManager.class);
pm.reboot(null);
}
}
public interface OnA2dpHwDialogConfirmedListener {
/**
* Called when the user presses reboot on the warning dialog.
*/
void onA2dpHwDialogConfirmed();
}
}

View File

@@ -56,7 +56,8 @@ import java.util.List;
public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment
implements SwitchBar.OnSwitchChangeListener, OemUnlockDialogHost, AdbDialogHost,
AdbClearKeysDialogHost, LogPersistDialogHost {
AdbClearKeysDialogHost, LogPersistDialogHost,
BluetoothA2dpHwOffloadRebootDialog.OnA2dpHwDialogConfirmedListener {
private static final String TAG = "DevSettingsDashboard";
@@ -269,6 +270,13 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
controller.onDisableLogPersistDialogRejected();
}
@Override
public void onA2dpHwDialogConfirmed() {
final BluetoothA2dpHwOffloadPreferenceController controller =
getDevelopmentOptionsController(BluetoothA2dpHwOffloadPreferenceController.class);
controller.onA2dpHwDialogConfirmed();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
boolean handledResult = false;
@@ -397,6 +405,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
controllers.add(new LogPersistPreferenceController(context, fragment, lifecycle));
controllers.add(new ConnectivityMonitorPreferenceController(context));
controllers.add(new CameraLaserSensorPreferenceController(context));
controllers.add(new LogicalCameraDefaultPreferenceController(context));
controllers.add(new WifiDisplayCertificationPreferenceController(context));
controllers.add(new WifiVerboseLoggingPreferenceController(context));
controllers.add(new WifiConnectedMacRandomizationPreferenceController(context));
@@ -405,6 +414,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
controllers.add(new BluetoothDeviceNoNamePreferenceController(context));
controllers.add(new BluetoothAbsoluteVolumePreferenceController(context));
controllers.add(new BluetoothAvrcpVersionPreferenceController(context));
controllers.add(new BluetoothA2dpHwOffloadPreferenceController(context, fragment));
controllers.add(new BluetoothAudioCodecPreferenceController(context, lifecycle,
bluetoothA2dpConfigStore));
controllers.add(new BluetoothAudioSampleRatePreferenceController(context, lifecycle,

View File

@@ -0,0 +1,90 @@
/*
* 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.os.SystemProperties;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
public class LogicalCameraDefaultPreferenceController extends DeveloperOptionsPreferenceController
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
private static final String KEY_LOGICAL_CAMERA_DEFAULT_SWITCH = "logical_camera_default_switch";
@VisibleForTesting
static final String BUILD_TYPE = "ro.build.type";
@VisibleForTesting
static final String PROPERTY_LOGICAL_CAMERA_DEFAULT = "persist.camera.logical.default";
@VisibleForTesting
static final int ENABLED = 1;
@VisibleForTesting
static final int DISABLED = 0;
@VisibleForTesting
static final String USERDEBUG_BUILD = "userdebug";
@VisibleForTesting
static final String ENG_BUILD = "eng";
@VisibleForTesting
static final String USER_BUILD = "user";
public LogicalCameraDefaultPreferenceController(Context context) {
super(context);
}
@Override
public boolean isAvailable() {
return mContext.getResources().getBoolean(R.bool.config_show_logical_camera_default);
}
@Override
public String getPreferenceKey() {
return KEY_LOGICAL_CAMERA_DEFAULT_SWITCH;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean isEnabled = (Boolean) newValue;
String value = Integer.toString(isEnabled ? ENABLED : DISABLED);
SystemProperties.set(PROPERTY_LOGICAL_CAMERA_DEFAULT, value);
return true;
}
@Override
public void updateState(Preference preference) {
final boolean enabled = isLogicalCameraDefault();
((SwitchPreference) mPreference).setChecked(enabled);
}
@Override
protected void onDeveloperOptionsSwitchDisabled() {
super.onDeveloperOptionsSwitchDisabled();
SystemProperties.set(PROPERTY_LOGICAL_CAMERA_DEFAULT, Integer.toString(DISABLED));
((SwitchPreference) mPreference).setChecked(false);
}
private boolean isLogicalCameraDefault() {
final String prop = SystemProperties.get(PROPERTY_LOGICAL_CAMERA_DEFAULT,
Integer.toString(DISABLED));
return TextUtils.equals(Integer.toString(ENABLED), prop);
}
}

View File

@@ -18,6 +18,7 @@ import android.content.Context;
import com.android.internal.app.ColorDisplayController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settings.R;
public class NightDisplayPreferenceController extends AbstractPreferenceController implements
PreferenceControllerMixin {
@@ -29,6 +30,12 @@ public class NightDisplayPreferenceController extends AbstractPreferenceControll
}
public static boolean isSuggestionComplete(Context context) {
final boolean isEnabled = context.getResources().getBoolean(
R.bool.config_night_light_suggestion_enabled);
// The suggestion is always complete if not enabled.
if (!isEnabled) {
return true;
}
final ColorDisplayController controller = new ColorDisplayController(context);
return controller.getAutoMode() != ColorDisplayController.AUTO_MODE_DISABLED;
}

View File

@@ -45,6 +45,8 @@ import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.fuelgauge.anomaly.Anomaly;
import com.android.settings.fuelgauge.batterytip.AnomalyInfo;
import com.android.settings.fuelgauge.batterytip.StatsManagerConfig;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
@@ -511,10 +513,25 @@ public class BatteryUtils {
return false;
}
public boolean isPreOApp(final String[] packageNames) {
if (ArrayUtils.isEmpty(packageNames)) {
return false;
}
for (String packageName : packageNames) {
if (isPreOApp(packageName)) {
return true;
}
}
return false;
}
/**
* Return {@code true} if we should hide anomaly app represented by {@code uid}
*/
public boolean shouldHideAnomaly(PowerWhitelistBackend powerWhitelistBackend, int uid) {
public boolean shouldHideAnomaly(PowerWhitelistBackend powerWhitelistBackend, int uid,
AnomalyInfo anomalyInfo) {
final String[] packageNames = mPackageManager.getPackagesForUid(uid);
if (ArrayUtils.isEmpty(packageNames)) {
// Don't show it if app has been uninstalled
@@ -522,7 +539,13 @@ public class BatteryUtils {
}
return isSystemUid(uid) || powerWhitelistBackend.isWhitelisted(packageNames)
|| (isSystemApp(mPackageManager, packageNames) && !hasLauncherEntry(packageNames));
|| (isSystemApp(mPackageManager, packageNames) && !hasLauncherEntry(packageNames))
|| (isExcessiveBackgroundAnomaly(anomalyInfo) && !isPreOApp(packageNames));
}
private boolean isExcessiveBackgroundAnomaly(AnomalyInfo anomalyInfo) {
return anomalyInfo.anomalyType
== StatsManagerConfig.AnomalyType.EXCESSIVE_BACKGROUND_SERVICE;
}
private boolean isSystemUid(int uid) {

View File

@@ -155,44 +155,36 @@ public class AnomalyDetectionJobService extends JobService {
final String packageName = batteryUtils.getPackageName(uid);
final long versionCode = batteryUtils.getAppLongVersionCode(packageName);
final boolean anomalyDetected;
if (isExcessiveBackgroundAnomaly(anomalyInfo)) {
anomalyDetected = batteryUtils.isPreOApp(packageName);
if (batteryUtils.shouldHideAnomaly(powerWhitelistBackend, uid, anomalyInfo)) {
metricsFeatureProvider.action(context,
MetricsProto.MetricsEvent.ACTION_ANOMALY_IGNORED,
packageName,
Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT,
anomalyInfo.anomalyType),
Pair.create(MetricsProto.MetricsEvent.FIELD_APP_VERSION_CODE,
versionCode));
} else {
anomalyDetected = true;
if (autoFeatureOn && anomalyInfo.autoRestriction) {
// Auto restrict this app
batteryUtils.setForceAppStandby(uid, packageName,
AppOpsManager.MODE_IGNORED);
databaseManager.insertAnomaly(uid, packageName, anomalyInfo.anomalyType,
AnomalyDatabaseHelper.State.AUTO_HANDLED,
timeMs);
} else {
databaseManager.insertAnomaly(uid, packageName, anomalyInfo.anomalyType,
AnomalyDatabaseHelper.State.NEW,
timeMs);
}
metricsFeatureProvider.action(context,
MetricsProto.MetricsEvent.ACTION_ANOMALY_TRIGGERED,
packageName,
Pair.create(MetricsProto.MetricsEvent.FIELD_ANOMALY_TYPE,
anomalyInfo.anomalyType),
Pair.create(MetricsProto.MetricsEvent.FIELD_APP_VERSION_CODE,
versionCode));
}
if (anomalyDetected) {
if (batteryUtils.shouldHideAnomaly(powerWhitelistBackend, uid)) {
metricsFeatureProvider.action(context,
MetricsProto.MetricsEvent.ACTION_ANOMALY_IGNORED,
packageName,
Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT,
anomalyInfo.anomalyType),
Pair.create(MetricsProto.MetricsEvent.FIELD_APP_VERSION_CODE,
versionCode));
} else {
if (autoFeatureOn && anomalyInfo.autoRestriction) {
// Auto restrict this app
batteryUtils.setForceAppStandby(uid, packageName,
AppOpsManager.MODE_IGNORED);
databaseManager.insertAnomaly(uid, packageName, anomalyInfo.anomalyType,
AnomalyDatabaseHelper.State.AUTO_HANDLED,
timeMs);
} else {
databaseManager.insertAnomaly(uid, packageName, anomalyInfo.anomalyType,
AnomalyDatabaseHelper.State.NEW,
timeMs);
}
metricsFeatureProvider.action(context,
MetricsProto.MetricsEvent.ACTION_ANOMALY_TRIGGERED,
packageName,
Pair.create(MetricsProto.MetricsEvent.FIELD_ANOMALY_TYPE,
anomalyInfo.anomalyType),
Pair.create(MetricsProto.MetricsEvent.FIELD_APP_VERSION_CODE,
versionCode));
}
}
} catch (NullPointerException | IndexOutOfBoundsException e) {
Log.e(TAG, "Parse stats dimensions value error.", e);
}
@@ -229,11 +221,6 @@ public class AnomalyDetectionJobService extends JobService {
return UID_NULL;
}
private boolean isExcessiveBackgroundAnomaly(AnomalyInfo anomalyInfo) {
return anomalyInfo.anomalyType
== StatsManagerConfig.AnomalyType.EXCESSIVE_BACKGROUND_SERVICE;
}
@VisibleForTesting
JobWorkItem dequeueWork(JobParameters parameters) {
synchronized (mLock) {

View File

@@ -103,6 +103,7 @@ public class RestrictAppTip extends BatteryTip {
} else {
mState = tip.getState();
mShowDialog = tip.shouldShowDialog();
mRestrictAppList = ((RestrictAppTip) tip).mRestrictAppList;
}
}

View File

@@ -721,7 +721,7 @@ public class ApnEditor extends SettingsPreferenceFragment
// If it's a new APN, then cancel will delete the new entry in onPause
if (!mNewApn && !mReadOnlyApn) {
menu.add(0, MENU_DELETE, 0, R.string.menu_delete)
.setIcon(R.drawable.ic_menu_delete);
.setIcon(R.drawable.ic_delete);
}
menu.add(0, MENU_SAVE, 0, R.string.menu_save)
.setIcon(android.R.drawable.ic_menu_save);

View File

@@ -17,6 +17,8 @@
package com.android.settings.notification;
import android.content.Context;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.v7.preference.Preference;
@@ -57,4 +59,12 @@ public abstract class AdjustVolumeRestrictedPreferenceController extends
UserManager.DISALLOW_ADJUST_VOLUME, UserHandle.myUserId());
}
@Override
public IntentFilter getIntentFilter() {
final IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION);
filter.addAction(AudioManager.MASTER_MUTE_CHANGED_ACTION);
return filter;
}
}

View File

@@ -26,16 +26,22 @@ import android.os.UserHandle;
import android.preference.SeekBarVolumizer;
import android.provider.SearchIndexableResource;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.RingtonePreference;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.sound.HandsFreeProfileOutputPreferenceController;
import com.android.settings.sound.MediaOutputPreferenceController;
import com.android.settings.widget.PreferenceCategoryController;
import com.android.settings.widget.UpdatableListPreferenceDialogFragment;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.Instrumentable;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
@@ -68,6 +74,9 @@ public class SoundSettings extends DashboardFragment {
};
private RingtonePreference mRequestPreference;
private UpdatableListPreferenceDialogFragment mDialogFragment;
private String mMediaOutputControllerKey;
private String mHfpOutputControllerKey;
@Override
public int getMetricsCategory() {
@@ -82,6 +91,11 @@ public class SoundSettings extends DashboardFragment {
if (!TextUtils.isEmpty(selectedPreference)) {
mRequestPreference = (RingtonePreference) findPreference(selectedPreference);
}
UpdatableListPreferenceDialogFragment dialogFragment =
(UpdatableListPreferenceDialogFragment) getFragmentManager()
.findFragmentByTag(TAG);
mDialogFragment = dialogFragment;
}
}
@@ -111,6 +125,23 @@ public class SoundSettings extends DashboardFragment {
return super.onPreferenceTreeClick(preference);
}
@Override
public void onDisplayPreferenceDialog(Preference preference) {
final int metricsCategory;
if (mHfpOutputControllerKey.equals(preference.getKey())) {
metricsCategory = MetricsProto.MetricsEvent.DIALOG_SWITCH_HFP_DEVICES;
} else if (mMediaOutputControllerKey.equals(preference.getKey())) {
metricsCategory = MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES;
} else {
metricsCategory = Instrumentable.METRICS_CATEGORY_UNKNOWN;
}
mDialogFragment = UpdatableListPreferenceDialogFragment.
newInstance(preference.getKey(), metricsCategory);
mDialogFragment.setTargetFragment(this, 0);
mDialogFragment.show(getFragmentManager(), TAG);
}
@Override
protected String getLogTag() {
return TAG;
@@ -152,6 +183,14 @@ public class SoundSettings extends DashboardFragment {
volumeControllers.add(use(NotificationVolumePreferenceController.class));
volumeControllers.add(use(CallVolumePreferenceController.class));
use(MediaOutputPreferenceController.class).setCallback(listPreference ->
onPreferenceDataChanged(listPreference));
mMediaOutputControllerKey = use(MediaOutputPreferenceController.class).getPreferenceKey();
use(HandsFreeProfileOutputPreferenceController.class).setCallback(listPreference ->
onPreferenceDataChanged(listPreference));
mHfpOutputControllerKey =
use(HandsFreeProfileOutputPreferenceController.class).getPreferenceKey();
for (VolumeSeekBarPreferenceController controller : volumeControllers) {
controller.setCallback(mVolumeCallback);
getLifecycle().addObserver(controller);
@@ -287,4 +326,10 @@ public class SoundSettings extends DashboardFragment {
workSoundController.enableWorkSync();
}
}
}
private void onPreferenceDataChanged(ListPreference preference) {
if (mDialogFragment != null) {
mDialogFragment.onListPreferenceUpdated(preference);
}
}
}

View File

@@ -0,0 +1,158 @@
/*
* 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.notification;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
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 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.search.DatabaseIndexingUtils;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
import android.support.v4.graphics.drawable.IconCompat;
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.
*/
public static final String ACTION_ZEN_MODE_SLICE_CHANGED =
"com.android.settings.notification.ZEN_MODE_CHANGED";
public static final IntentFilter INTENT_FILTER = new IntentFilter();
static {
INTENT_FILTER.addAction(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
INTENT_FILTER.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
INTENT_FILTER.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL);
}
private ZenModeSliceBuilder() {
}
/**
* Return a ZenMode Slice bound to {@link #ZEN_MODE_URI}.
* <p>
* Note that you should register a listener for {@link #INTENT_FILTER} to get changes for
* ZenMode.
*/
public static Slice getSlice(Context context) {
final boolean isZenModeEnabled = isZenModeEnabled(context);
final CharSequence title = context.getText(R.string.zen_mode_settings_title);
@ColorInt final int color = Utils.getColorAccent(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 */,
isZenModeEnabled);
return new ListBuilder(context, ZEN_MODE_URI, ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(b -> b
.setTitle(title)
.addEndItem(toggleSliceAction)
.setPrimaryAction(primarySliceAction))
.build();
}
/**
* Update the current ZenMode status to the boolean value keyed by
* {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
*/
public static void handleUriChange(Context context, Intent intent) {
final boolean zenModeOn = intent.getBooleanExtra(EXTRA_TOGGLE_STATE, false);
final int zenMode;
if (zenModeOn) {
zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
} else {
zenMode = Settings.Global.ZEN_MODE_OFF;
}
NotificationManager.from(context).setZenMode(zenMode, null /* conditionId */, TAG);
// Do not notifyChange on Uri. The service takes longer to update the current value than it
// does for the Slice to check the current value again. Let {@link SliceBroadcastRelay}
// handle it.
}
private static boolean isZenModeEnabled(Context context) {
final NotificationManager manager = context.getSystemService(NotificationManager.class);
final int zenMode = manager.getZenMode();
switch (zenMode) {
case Settings.Global.ZEN_MODE_ALARMS:
case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
return true;
case Settings.Global.ZEN_MODE_OFF:
default:
return false;
}
}
private static PendingIntent getPrimaryAction(Context context) {
final String screenTitle = context.getText(R.string.zen_mode_settings_title).toString();
final Uri contentUri = new Uri.Builder().appendPath(ZEN_MODE_KEY).build();
final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
ZenModeSettings.class.getName(), ZEN_MODE_KEY, screenTitle,
MetricsEvent.NOTIFICATION_ZEN_MODE)
.setClassName(context.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
return PendingIntent.getActivity(context, 0 /* requestCode */,
intent, 0 /* flags */);
}
private static PendingIntent getBroadcastIntent(Context context) {
final Intent intent = new Intent(ACTION_ZEN_MODE_SLICE_CHANGED)
.setClass(context, SliceBroadcastReceiver.class);
return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
}
}

View File

@@ -28,6 +28,9 @@ public class ZenModeVisEffectsAllPreferenceController
extends AbstractZenModePreferenceController
implements ZenCustomRadioButtonPreference.OnRadioButtonClickListener {
private final String KEY;
private ZenCustomRadioButtonPreference mPreference;
protected static final int EFFECTS = Policy.SUPPRESSED_EFFECT_SCREEN_OFF
| Policy.SUPPRESSED_EFFECT_SCREEN_ON
| Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
@@ -41,6 +44,14 @@ public class ZenModeVisEffectsAllPreferenceController
public ZenModeVisEffectsAllPreferenceController(Context context, Lifecycle lifecycle,
String key) {
super(context, key, lifecycle);
KEY = key;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(KEY);
mPreference.setOnRadioButtonClickListener(this);
}
@Override
@@ -54,17 +65,7 @@ public class ZenModeVisEffectsAllPreferenceController
boolean everythingBlocked = Policy.areAllVisualEffectsSuppressed(
mBackend.mPolicy.suppressedVisualEffects);
ZenCustomRadioButtonPreference pref = (ZenCustomRadioButtonPreference) preference;
pref.setOnRadioButtonClickListener(this);
pref.setChecked(everythingBlocked);
}
protected void deselect(PreferenceScreen screen) {
ZenCustomRadioButtonPreference preference =
(ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
if (preference != null) {
preference.setChecked(false);
}
mPreference.setChecked(everythingBlocked);
}
@Override

View File

@@ -19,6 +19,7 @@ package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
@@ -28,6 +29,9 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeVisEffectsCustomPreferenceController
extends AbstractZenModePreferenceController {
private final String KEY;
private ZenCustomRadioButtonPreference mPreference;
protected static final int INTERRUPTIVE_EFFECTS = Policy.SUPPRESSED_EFFECT_AMBIENT
| Policy.SUPPRESSED_EFFECT_PEEK
| Policy.SUPPRESSED_EFFECT_LIGHTS
@@ -36,6 +40,7 @@ public class ZenModeVisEffectsCustomPreferenceController
public ZenModeVisEffectsCustomPreferenceController(Context context, Lifecycle lifecycle,
String key) {
super(context, key, lifecycle);
KEY = key;
}
@Override
@@ -43,20 +48,25 @@ public class ZenModeVisEffectsCustomPreferenceController
return true;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(KEY);
mPreference.setOnGearClickListener(p -> {
launchCustomSettings();
});
mPreference.setOnRadioButtonClickListener(p -> {
launchCustomSettings();
});
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
ZenCustomRadioButtonPreference pref = (ZenCustomRadioButtonPreference) preference;
pref.setChecked(areCustomOptionsSelected());
pref.setOnGearClickListener(p -> {
launchCustomSettings();
});
pref.setOnRadioButtonClickListener(p -> {
launchCustomSettings();
});
mPreference.setChecked(areCustomOptionsSelected());
}
protected boolean areCustomOptionsSelected() {

View File

@@ -28,6 +28,9 @@ public class ZenModeVisEffectsNonePreferenceController
extends AbstractZenModePreferenceController
implements ZenCustomRadioButtonPreference.OnRadioButtonClickListener {
private final String KEY;
private ZenCustomRadioButtonPreference mPreference;
protected static final int EFFECTS = Policy.SUPPRESSED_EFFECT_SCREEN_OFF
| Policy.SUPPRESSED_EFFECT_SCREEN_ON
| Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
@@ -41,6 +44,14 @@ public class ZenModeVisEffectsNonePreferenceController
public ZenModeVisEffectsNonePreferenceController(Context context, Lifecycle lifecycle,
String key) {
super(context, key, lifecycle);
KEY = key;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(KEY);
mPreference.setOnRadioButtonClickListener(this);
}
@Override
@@ -53,9 +64,7 @@ public class ZenModeVisEffectsNonePreferenceController
super.updateState(preference);
boolean nothingBlocked = mBackend.mPolicy.suppressedVisualEffects == 0;
ZenCustomRadioButtonPreference pref = (ZenCustomRadioButtonPreference) preference;
pref.setOnRadioButtonClickListener(this);
pref.setChecked(nothingBlocked);
mPreference.setChecked(nothingBlocked);
}
@Override
@@ -64,12 +73,4 @@ public class ZenModeVisEffectsNonePreferenceController
MetricsProto.MetricsEvent.ACTION_ZEN_SOUND_ONLY, true);
mBackend.saveVisualEffectsPolicy(EFFECTS, false);
}
protected void deselect(PreferenceScreen screen) {
ZenCustomRadioButtonPreference preference =
(ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
if (preference != null) {
preference.setChecked(false);
}
}
}

View File

@@ -24,8 +24,10 @@ import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.slices.SettingsSliceProvider;
import java.util.List;
@@ -48,6 +50,12 @@ public interface DeviceIndexFeatureProvider {
default void updateIndex(Context context, boolean force) {
if (!isIndexingEnabled()) {
Log.w(TAG, "Skipping: device index is not enabled");
return;
}
if (!Utils.isDeviceProvisioned(context)) {
Log.w(TAG, "Skipping: device is not provisioned");
return;
}

View File

@@ -18,41 +18,40 @@ package com.android.settings.slices;
import static android.Manifest.permission.READ_SEARCH_INDEXABLES;
import static com.android.settings.wifi.calling.WifiCallingSliceHelper.PATH_WIFI_CALLING;
import android.app.PendingIntent;
import android.app.slice.SliceManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.content.IntentFilter;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.provider.Settings;
import android.provider.SettingsSlicesContract;
import android.support.annotation.VisibleForTesting;
import android.support.v4.graphics.drawable.IconCompat;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import androidx.slice.Slice;
import androidx.slice.SliceProvider;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.wifi.WifiSliceBuilder;
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settingslib.SliceBroadcastRelay;
import com.android.settingslib.utils.ThreadUtils;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import androidx.slice.Slice;
import androidx.slice.SliceProvider;
/**
* A {@link SliceProvider} for Settings to enabled inline results in system apps.
*
@@ -84,10 +83,6 @@ public class SettingsSliceProvider extends SliceProvider {
*/
public static final String SLICE_AUTHORITY = "com.android.settings.slices";
public static final String PATH_WIFI = "wifi";
public static final String ACTION_WIFI_CHANGED =
"com.android.settings.slice.action.WIFI_CHANGED";
/**
* Action passed for changes to Toggle Slices.
*/
@@ -111,8 +106,6 @@ public class SettingsSliceProvider extends SliceProvider {
public static final String EXTRA_SLICE_PLATFORM_DEFINED =
"com.android.settings.slice.extra.platform";
// TODO -- Associate slice URI with search result instead of separate hardcoded thing
@VisibleForTesting
SlicesDatabaseAccessor mSlicesDatabaseAccessor;
@@ -121,6 +114,8 @@ public class SettingsSliceProvider extends SliceProvider {
@VisibleForTesting
Map<Uri, SliceData> mSliceDataCache;
final Set<Uri> mRegisteredUris = new ArraySet<>();
public SettingsSliceProvider() {
super(READ_SEARCH_INDEXABLES);
}
@@ -146,28 +141,42 @@ public class SettingsSliceProvider extends SliceProvider {
@Override
public void onSlicePinned(Uri sliceUri) {
if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) {
registerIntentToUri(WifiSliceBuilder.INTENT_FILTER , sliceUri);
return;
} else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
registerIntentToUri(ZenModeSliceBuilder.INTENT_FILTER, sliceUri);
mRegisteredUris.add(sliceUri);
return;
}
// Start warming the slice, we expect someone will want it soon.
loadSliceInBackground(sliceUri);
}
@Override
public void onSliceUnpinned(Uri sliceUri) {
if (mRegisteredUris.contains(sliceUri)) {
Log.d(TAG, "Unregistering uri broadcast relay: " + sliceUri);
SliceBroadcastRelay.unregisterReceivers(getContext(), sliceUri);
mRegisteredUris.remove(sliceUri);
}
mSliceDataCache.remove(sliceUri);
}
@Override
public Slice onBindSlice(Uri sliceUri) {
String path = sliceUri.getPath();
// If adding a new Slice, do not directly match Slice URIs.
// Use {@link SlicesDatabaseAccessor}.
switch (path) {
case "/" + PATH_WIFI:
return createWifiSlice(sliceUri);
case "/" + PATH_WIFI_CALLING:
return FeatureFactory.getFactory(getContext())
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(getContext())
.createWifiCallingSlice(sliceUri);
if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) {
return FeatureFactory.getFactory(getContext())
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(getContext())
.createWifiCallingSlice(sliceUri);
} else if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) {
return WifiSliceBuilder.getSlice(getContext());
} else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
return ZenModeSliceBuilder.getSlice(getContext());
}
SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);
@@ -223,11 +232,12 @@ public class SettingsSliceProvider extends SliceProvider {
true /* isPlatformSlice */);
final List<String> oemKeys = mSlicesDatabaseAccessor.getSliceKeys(
false /* isPlatformSlice */);
final List<Uri> allUris = buildUrisFromKeys(platformKeys,
SettingsSlicesContract.AUTHORITY);
allUris.addAll(buildUrisFromKeys(oemKeys, SettingsSliceProvider.SLICE_AUTHORITY));
descendants.addAll(buildUrisFromKeys(platformKeys, SettingsSlicesContract.AUTHORITY));
descendants.addAll(buildUrisFromKeys(oemKeys, SettingsSliceProvider.SLICE_AUTHORITY));
descendants.addAll(getSpecialCaseUris(true /* isPlatformSlice */));
descendants.addAll(getSpecialCaseUris(false /* isPlatformSlice */));
return allUris;
return descendants;
}
// Path is anything but empty, "action", or "intent". Return empty list.
@@ -242,7 +252,9 @@ public class SettingsSliceProvider extends SliceProvider {
// Can assume authority belongs to the provider. Return all Uris for the authority.
final boolean isPlatformUri = TextUtils.equals(authority, SettingsSlicesContract.AUTHORITY);
final List<String> keys = mSlicesDatabaseAccessor.getSliceKeys(isPlatformUri);
return buildUrisFromKeys(keys, authority);
descendants.addAll(buildUrisFromKeys(keys, authority));
descendants.addAll(getSpecialCaseUris(isPlatformUri));
return descendants;
}
private List<Uri> buildUrisFromKeys(List<String> keys, String authority) {
@@ -267,7 +279,15 @@ public class SettingsSliceProvider extends SliceProvider {
long startBuildTime = System.currentTimeMillis();
final SliceData sliceData = mSlicesDatabaseAccessor.getSliceDataFromUri(uri);
List<Uri> pinnedSlices = getContext().getSystemService(
final BasePreferenceController controller = SliceBuilderUtils.getPreferenceController(
getContext(), sliceData);
final IntentFilter filter = controller.getIntentFilter();
if (filter != null) {
registerIntentToUri(filter, uri);
}
final List<Uri> pinnedSlices = getContext().getSystemService(
SliceManager.class).getPinnedSlices();
if (pinnedSlices.contains(uri)) {
mSliceDataCache.put(uri, sliceData);
@@ -295,55 +315,34 @@ public class SettingsSliceProvider extends SliceProvider {
return new Slice.Builder(uri).build();
}
// TODO (b/70622039) remove this when the proper wifi slice is enabled.
private Slice createWifiSlice(Uri sliceUri) {
// Get wifi state
WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
int wifiState = wifiManager.getWifiState();
boolean wifiEnabled = false;
String state;
switch (wifiState) {
case WifiManager.WIFI_STATE_DISABLED:
case WifiManager.WIFI_STATE_DISABLING:
state = getContext().getString(R.string.disconnected);
break;
case WifiManager.WIFI_STATE_ENABLED:
case WifiManager.WIFI_STATE_ENABLING:
state = wifiManager.getConnectionInfo().getSSID();
wifiEnabled = true;
break;
case WifiManager.WIFI_STATE_UNKNOWN:
default:
state = ""; // just don't show anything?
break;
private List<Uri> getSpecialCaseUris(boolean isPlatformUri) {
if (isPlatformUri) {
return getSpecialCasePlatformUris();
}
boolean finalWifiEnabled = wifiEnabled;
return new ListBuilder(getContext(), sliceUri)
.setColor(R.color.material_blue_500)
.addRow(b -> b
.setTitle(getContext().getString(R.string.wifi_settings))
.setTitleItem(Icon.createWithResource(getContext(), R.drawable.wifi_signal))
.setSubtitle(state)
.addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED),
null, finalWifiEnabled))
.setPrimaryAction(
new SliceAction(getIntent(Settings.ACTION_WIFI_SETTINGS),
(IconCompat) null, null)))
.build();
return getSpecialCaseOemUris();
}
private PendingIntent getIntent(String action) {
Intent intent = new Intent(action);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, intent, 0);
return pi;
private List<Uri> getSpecialCasePlatformUris() {
return Arrays.asList(
WifiSliceBuilder.WIFI_URI
);
}
private PendingIntent getBroadcastIntent(String action) {
Intent intent = new Intent(action);
intent.setClass(getContext(), SliceBroadcastReceiver.class);
return PendingIntent.getBroadcast(getContext(), 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
private List<Uri> getSpecialCaseOemUris() {
return Arrays.asList(
ZenModeSliceBuilder.ZEN_MODE_URI
);
}
@VisibleForTesting
/**
* Registers an IntentFilter in SysUI to notify changes to {@param sliceUri} when broadcasts to
* {@param intentFilter} happen.
*/
void registerIntentToUri(IntentFilter intentFilter, Uri sliceUri) {
Log.d(TAG, "Registering Uri for broadcast relay: " + sliceUri);
mRegisteredUris.add(sliceUri);
SliceBroadcastRelay.registerReceiver(getContext(), sliceUri, SliceBroadcastReceiver.class,
intentFilter);
}
}

View File

@@ -16,20 +16,19 @@
package com.android.settings.slices;
import static com.android.settings.notification.ZenModeSliceBuilder.ACTION_ZEN_MODE_SLICE_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_SLIDER_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_TOGGLE_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_WIFI_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED;
import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED;
import static com.android.settings.wifi.WifiSliceBuilder.ACTION_WIFI_SLICE_CHANGED;
import android.app.slice.Slice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.provider.SettingsSlicesContract;
import android.text.TextUtils;
import android.util.Log;
@@ -39,7 +38,10 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SliderPreferenceController;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wifi.WifiSliceBuilder;
import com.android.settingslib.SliceBroadcastRelay;
/**
* Responds to actions performed on slices and notifies slices of updates in state changes.
@@ -48,9 +50,6 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
private static String TAG = "SettSliceBroadcastRec";
/**
* TODO (b/) move wifi action into generalized case.
*/
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
@@ -67,25 +66,24 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
final int newPosition = intent.getIntExtra(Slice.EXTRA_RANGE_VALUE, -1);
handleSliderAction(context, key, newPosition, isPlatformSlice);
break;
case ACTION_WIFI_CHANGED:
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
boolean newState = intent.getBooleanExtra(Slice.EXTRA_TOGGLE_STATE,
wm.isWifiEnabled());
wm.setWifiEnabled(newState);
// Wait a bit for wifi to update (TODO: is there a better way to do this?)
Handler h = new Handler();
h.postDelayed(() -> {
Uri uri = SliceBuilderUtils.getUri(SettingsSliceProvider.PATH_WIFI,
false /* isPlatformSlice */);
context.getContentResolver().notifyChange(uri, null);
}, 1000);
case ACTION_WIFI_SLICE_CHANGED:
WifiSliceBuilder.handleUriChange(context, intent);
break;
case ACTION_WIFI_CALLING_CHANGED:
FeatureFactory.getFactory(context)
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(context)
.handleWifiCallingChanged(intent);
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(context)
.handleWifiCallingChanged(intent);
break;
case ACTION_ZEN_MODE_SLICE_CHANGED:
ZenModeSliceBuilder.handleUriChange(context, intent);
break;
default:
final String uriString = intent.getStringExtra(SliceBroadcastRelay.EXTRA_URI);
if (!TextUtils.isEmpty(uriString)) {
final Uri uri = Uri.parse(uriString);
context.getContentResolver().notifyChange(uri, null /* observer */);
}
}
}

View File

@@ -39,7 +39,6 @@ import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
@@ -47,6 +46,7 @@ import com.android.settings.core.SliderPreferenceController;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.DatabaseIndexingUtils;
import com.android.settingslib.SliceBroadcastRelay;
import com.android.settingslib.core.AbstractPreferenceController;
import android.support.v4.graphics.drawable.IconCompat;
@@ -54,6 +54,7 @@ import android.support.v4.graphics.drawable.IconCompat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
@@ -345,7 +346,10 @@ public class SliceBuilderUtils {
final String keywordString = data.getKeywords();
if (keywordString != null) {
final String[] keywordArray = keywordString.split(",");
keywords.addAll(Arrays.asList(keywordArray));
final List<String> strippedKeywords = Arrays.stream(keywordArray)
.map(s -> s = s.trim())
.collect(Collectors.toList());
keywords.addAll(strippedKeywords);
}
return keywords;

View File

@@ -45,7 +45,11 @@ public class SliceDeepLinkSpringBoard extends Activity {
// This shouldn't matter since the slice is shown instead of the device
// index caring about the launch uri.
Uri slice = Uri.parse(intent.getStringExtra(EXTRA_SLICE));
Log.e(TAG, "Slice intent launched: " + slice);
SlicesDatabaseAccessor slicesDatabaseAccessor = new SlicesDatabaseAccessor(this);
// Sadly have to block here because we don't know where to go.
final SliceData sliceData = slicesDatabaseAccessor.getSliceDataFromUri(slice);
Intent launchIntent = SliceBuilderUtils.getContentIntent(this, sliceData);
startActivity(launchIntent);
} else {
startActivity(intent);
}

View File

@@ -78,6 +78,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
protected final LocalBluetoothProfileManager mProfileManager;
protected int mSelectedIndex;
protected Preference mPreference;
protected AudioSwitchCallback mAudioSwitchPreferenceCallback;
private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback;
private final LocalBluetoothManager mLocalBluetoothManager;
@@ -85,6 +86,10 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
private final WiredHeadsetBroadcastReceiver mReceiver;
private final Handler mHandler;
public interface AudioSwitchCallback {
void onPreferenceDataChanged(ListPreference preference);
}
public AudioSwitchPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -131,7 +136,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
final BluetoothDevice btDevice = mConnectedDevices.get(connectedDeviceIndex);
mSelectedIndex = connectedDeviceIndex;
setActiveBluetoothDevice(btDevice);
listPreference.setSummary(btDevice.getName());
listPreference.setSummary(btDevice.getAliasName());
}
return true;
}
@@ -207,6 +212,10 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
}
public void setCallback(AudioSwitchCallback callback) {
mAudioSwitchPreferenceCallback = callback;
}
protected boolean isStreamFromOutputDevice(int streamType, int device) {
return (device & mAudioManager.getDevicesForStream(streamType)) != 0;
}
@@ -319,7 +328,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
mediaValues[mSelectedIndex] = mContext.getText(R.string.media_output_default_summary);
for (int i = 0, size = mConnectedDevices.size(); i < size; i++) {
final BluetoothDevice btDevice = mConnectedDevices.get(i);
mediaOutputs[i] = btDevice.getName();
mediaOutputs[i] = btDevice.getAliasName();
mediaValues[i] = btDevice.getAddress();
if (btDevice.equals(activeDevice)) {
// select the active connected device.
@@ -335,6 +344,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
listPreference.setEntryValues(mediaValues);
listPreference.setValueIndex(mSelectedIndex);
listPreference.setSummary(mediaOutputs[mSelectedIndex]);
mAudioSwitchPreferenceCallback.onPreferenceDataChanged(listPreference);
}
private int getConnectedDeviceIndex(String hardwareAddress) {

View File

@@ -66,7 +66,11 @@ public class HandsFreeProfileOutputPreferenceController extends
if (numDevices == 0) {
// No connected devices, disable switch entry.
mPreference.setVisible(false);
preference.setSummary(mContext.getText(R.string.media_output_default_summary));
final CharSequence summary = mContext.getText(R.string.media_output_default_summary);
final CharSequence[] defaultMediaOutput = new CharSequence[]{summary};
mSelectedIndex = getDefaultDeviceIndex();
preference.setSummary(summary);
setPreference(defaultMediaOutput, defaultMediaOutput, preference);
return;
}

View File

@@ -78,7 +78,11 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro
if (numDevices == 0) {
// Disable switch entry if there is no connected devices.
mPreference.setVisible(false);
preference.setSummary(mContext.getText(R.string.media_output_default_summary));
final CharSequence summary = mContext.getText(R.string.media_output_default_summary);
final CharSequence[] defaultMediaOutput = new CharSequence[]{summary};
mSelectedIndex = getDefaultDeviceIndex();
preference.setSummary(summary);
setPreference(defaultMediaOutput, defaultMediaOutput, preference);
return;
}

View File

@@ -35,6 +35,7 @@ import android.support.annotation.IntDef;
import android.support.annotation.VisibleForTesting;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.IconDrawableFactory;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -146,9 +147,7 @@ public class EntityHeaderController {
* accessibility purposes.
*/
public EntityHeaderController setIcon(ApplicationsState.AppEntry appEntry) {
if (appEntry.icon != null) {
mIcon = appEntry.icon.getConstantState().newDrawable(mAppContext.getResources());
}
mIcon = IconDrawableFactory.newInstance(mAppContext).getBadgedIcon(appEntry.info);
return this;
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright 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.widget;
import android.app.AlertDialog;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
import android.support.v14.preference.PreferenceDialogFragment;
import android.support.v7.preference.ListPreference;
import android.widget.ArrayAdapter;
import com.android.settingslib.core.instrumentation.Instrumentable;
import java.util.ArrayList;
/**
* {@link PreferenceDialogFragment} that updates the available options
* when {@code onListPreferenceUpdated} is called."
*/
public class UpdatableListPreferenceDialogFragment extends PreferenceDialogFragment implements
Instrumentable {
private static final String SAVE_STATE_INDEX = "UpdatableListPreferenceDialogFragment.index";
private static final String SAVE_STATE_ENTRIES =
"UpdatableListPreferenceDialogFragment.entries";
private static final String SAVE_STATE_ENTRY_VALUES =
"UpdatableListPreferenceDialogFragment.entryValues";
private static final String METRICS_CATEGORY_KEY = "metrics_category_key";
private ArrayAdapter mAdapter;
private int mClickedDialogEntryIndex;
private ArrayList<CharSequence> mEntries;
private CharSequence[] mEntryValues;
private int mMetricsCategory = Instrumentable.METRICS_CATEGORY_UNKNOWN;
public static UpdatableListPreferenceDialogFragment newInstance(
String key, int metricsCategory) {
UpdatableListPreferenceDialogFragment fragment =
new UpdatableListPreferenceDialogFragment();
Bundle args = new Bundle(1);
args.putString(ARG_KEY, key);
args.putInt(METRICS_CATEGORY_KEY, metricsCategory);
fragment.setArguments(args);
return fragment;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle bundle = getArguments();
mMetricsCategory =
bundle.getInt(METRICS_CATEGORY_KEY, Instrumentable.METRICS_CATEGORY_UNKNOWN);
if (savedInstanceState == null) {
mEntries = new ArrayList<>();
setPreferenceData(getListPreference());
} else {
mClickedDialogEntryIndex = savedInstanceState.getInt(SAVE_STATE_INDEX, 0);
mEntries = savedInstanceState.getCharSequenceArrayList(SAVE_STATE_ENTRIES);
mEntryValues =
savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SAVE_STATE_INDEX, mClickedDialogEntryIndex);
outState.putCharSequenceArrayList(SAVE_STATE_ENTRIES, mEntries);
outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues);
}
@Override
public void onDialogClosed(boolean positiveResult) {
final ListPreference preference = getListPreference();
if (positiveResult && mClickedDialogEntryIndex >= 0) {
final String value = mEntryValues[mClickedDialogEntryIndex].toString();
if (preference.callChangeListener(value)) {
preference.setValue(value);
}
}
}
@VisibleForTesting
void setAdapter(ArrayAdapter adapter) {
mAdapter = adapter;
}
@VisibleForTesting
void setEntries(ArrayList<CharSequence> entries) {
mEntries = entries;
}
@VisibleForTesting
ArrayAdapter getAdapter() {
return mAdapter;
}
@VisibleForTesting
void setMetricsCategory(Bundle bundle) {
mMetricsCategory =
bundle.getInt(METRICS_CATEGORY_KEY, Instrumentable.METRICS_CATEGORY_UNKNOWN);
}
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
final TypedArray a = getContext().obtainStyledAttributes(
null,
com.android.internal.R.styleable.AlertDialog,
com.android.internal.R.attr.alertDialogStyle, 0);
mAdapter = new ArrayAdapter<>(
getContext(),
a.getResourceId(
com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout,
com.android.internal.R.layout.select_dialog_singlechoice),
mEntries);
builder.setSingleChoiceItems(mAdapter, mClickedDialogEntryIndex,
(dialog, which) -> {
mClickedDialogEntryIndex = which;
onClick(dialog, -1);
dialog.dismiss();
});
builder.setPositiveButton(null, null);
a.recycle();
}
@Override
public int getMetricsCategory() {
return mMetricsCategory;
}
private ListPreference getListPreference() {
return (ListPreference) getPreference();
}
private void setPreferenceData(ListPreference preference) {
mEntries.clear();
mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
for (CharSequence entry : preference.getEntries()) {
mEntries.add(entry);
}
mEntryValues = preference.getEntryValues();
}
public void onListPreferenceUpdated(ListPreference preference) {
if (mAdapter != null) {
setPreferenceData(preference);
mAdapter.notifyDataSetChanged();
}
}
}

View File

@@ -0,0 +1,178 @@
/*
* 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;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static android.provider.SettingsSlicesContract.KEY_WIFI;
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.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid;
import android.provider.SettingsSlicesContract;
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.search.DatabaseIndexingUtils;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
import android.support.v4.graphics.drawable.IconCompat;
import android.text.TextUtils;
/**
* Utility class to build a Wifi Slice, and handle all associated actions.
*/
public class WifiSliceBuilder {
/**
* 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();
/**
* Action notifying a change on the Wifi Slice.
*/
public static final String ACTION_WIFI_SLICE_CHANGED =
"com.android.settings.wifi.action.WIFI_CHANGED";
public static final IntentFilter INTENT_FILTER = new IntentFilter();
static {
INTENT_FILTER.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
INTENT_FILTER.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
}
private WifiSliceBuilder() {
}
/**
* Return a Wifi Slice bound to {@link #WIFI_URI}.
* <p>
* Note that you should register a listener for {@link #INTENT_FILTER} to get changes for Wifi.
*/
public static Slice getSlice(Context context) {
final boolean isWifiEnabled = isWifiEnabled(context);
final IconCompat icon = IconCompat.createWithResource(context,
R.drawable.ic_settings_wireless);
final String title = context.getString(R.string.wifi_settings);
final CharSequence summary = getSummary(context);
@ColorInt final int color = Utils.getColorAccent(context);
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 */,
isWifiEnabled);
return new ListBuilder(context, WIFI_URI, ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(b -> b
.setTitle(title)
.setSubtitle(summary)
.addEndItem(toggleSliceAction)
.setPrimaryAction(primarySliceAction))
.build();
}
/**
* Update the current wifi status to the boolean value keyed by
* {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
*/
public static void handleUriChange(Context context, Intent intent) {
final WifiManager wifiManager = context.getSystemService(WifiManager.class);
final boolean newState = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
wifiManager.isWifiEnabled());
wifiManager.setWifiEnabled(newState);
// Do not notifyChange on Uri. The service takes longer to update the current value than it
// does for the Slice to check the current value again. Let {@link SliceBroadcastRelay}
// handle it.
}
private static boolean isWifiEnabled(Context context) {
final WifiManager wifiManager = context.getSystemService(WifiManager.class);
switch (wifiManager.getWifiState()) {
case WifiManager.WIFI_STATE_ENABLED:
case WifiManager.WIFI_STATE_ENABLING:
return true;
case WifiManager.WIFI_STATE_DISABLED:
case WifiManager.WIFI_STATE_DISABLING:
case WifiManager.WIFI_STATE_UNKNOWN:
default:
return false;
}
}
private static CharSequence getSummary(Context context) {
final WifiManager wifiManager = context.getSystemService(WifiManager.class);
switch (wifiManager.getWifiState()) {
case WifiManager.WIFI_STATE_ENABLED:
final String ssid = WifiInfo.removeDoubleQuotes(wifiManager.getConnectionInfo()
.getSSID());
if (TextUtils.equals(ssid, WifiSsid.NONE)) {
return context.getText(R.string.disconnected);
}
return ssid;
case WifiManager.WIFI_STATE_ENABLING:
return context.getText(R.string.disconnected);
case WifiManager.WIFI_STATE_DISABLED:
case WifiManager.WIFI_STATE_DISABLING:
return context.getText(R.string.switch_off_text);
case WifiManager.WIFI_STATE_UNKNOWN:
default:
return "";
}
}
private static PendingIntent getPrimaryAction(Context context) {
final String screenTitle = context.getText(R.string.wifi_settings).toString();
final Uri contentUri = new Uri.Builder().appendPath(KEY_WIFI).build();
final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
WifiSettings.class.getName(), KEY_WIFI, screenTitle,
MetricsEvent.DIALOG_WIFI_AP_EDIT);
intent.setClassName(context.getPackageName(), SubSettings.class.getName());
intent.setData(contentUri);
return PendingIntent.getActivity(context, 0 /* requestCode */,
intent, 0 /* flags */);
}
private static PendingIntent getBroadcastIntent(Context context) {
final Intent intent = new Intent(ACTION_WIFI_SLICE_CHANGED);
intent.setClass(context, SliceBroadcastReceiver.class);
return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
}
}

View File

@@ -52,7 +52,7 @@ public class WifiUtils {
public static boolean isHotspotPasswordValid(String password) {
if (TextUtils.isEmpty(password)) {
return true;
return false;
}
final int length = password.length();

View File

@@ -20,6 +20,7 @@ import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -38,6 +39,7 @@ import androidx.slice.builders.SliceAction;
import com.android.ims.ImsManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
@@ -76,16 +78,20 @@ 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();
/**
* Timeout for querying wifi calling setting from ims manager.
*/
private static final int TIMEOUT_MILLIS = 2000;
/**
* Time for which data contained in the slice can remain fresh.
*/
private static final int SLICE_TTL_MILLIS = 60000;
protected SubscriptionManager mSubscriptionManager;
private final Context mContext;
@@ -182,7 +188,7 @@ public class WifiCallingSliceHelper {
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal);
final String title = mContext.getString(R.string.wifi_calling_settings_title);
return new ListBuilder(mContext, sliceUri, SLICE_TTL_MILLIS)
return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.setColor(R.color.material_blue_500)
.addRow(b -> b
.setTitle(title)
@@ -260,7 +266,7 @@ public class WifiCallingSliceHelper {
private Slice getNonActionableWifiCallingSlice(String title, String subtitle, Uri sliceUri,
PendingIntent primaryActionIntent) {
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal);
return new ListBuilder(mContext, sliceUri, SLICE_TTL_MILLIS)
return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.setColor(R.color.material_blue_500)
.addRow(b -> b
.setTitle(title)

View File

@@ -31,7 +31,6 @@ import java.util.UUID;
public class WifiTetherPasswordPreferenceController extends WifiTetherBasePreferenceController
implements ValidatedEditTextPreference.Validator {
private static final String TAG = "WifiTetherPswdPref";
private static final String PREF_KEY = "wifi_tether_network_password";
private String mPassword;
@@ -49,10 +48,11 @@ public class WifiTetherPasswordPreferenceController extends WifiTetherBasePrefer
@Override
public void updateDisplay() {
final WifiConfiguration config = mWifiManager.getWifiApConfiguration();
if (config != null) {
mPassword = config.preSharedKey;
} else {
if (config == null || (config.getAuthType() == WifiConfiguration.KeyMgmt.WPA2_PSK
&& TextUtils.isEmpty(config.preSharedKey))) {
mPassword = generateRandomPassword();
} else {
mPassword = config.preSharedKey;
}
((ValidatedEditTextPreference) mPreference).setValidator(this);
((ValidatedEditTextPreference) mPreference).setIsPassword(true);
@@ -68,17 +68,27 @@ public class WifiTetherPasswordPreferenceController extends WifiTetherBasePrefer
return true;
}
public String getPassword() {
/**
* This method returns the current password if it is valid for the indicated security type. If
* the password currently set is invalid it will forcefully set a random password that is valid.
*
* @param securityType The security type for the password.
* @return The current password if it is valid for the indicated security type. A new randomly
* generated password if it is not.
*/
public String getPasswordValidated(int securityType) {
// don't actually overwrite unless we get a new config in case it was accidentally toggled.
if (securityType == WifiConfiguration.KeyMgmt.NONE) {
return "";
} else if (!isTextValid(mPassword)) {
mPassword = generateRandomPassword();
updatePasswordDisplay((EditTextPreference) mPreference);
}
return mPassword;
}
public int getSecuritySettingForPassword() {
// We should return NONE when no password is set
if (TextUtils.isEmpty(mPassword)) {
return WifiConfiguration.KeyMgmt.NONE;
}
// Only other currently supported type is WPA2 so we'll try that
return WifiConfiguration.KeyMgmt.WPA2_PSK;
public void updateVisibility(int securityType) {
mPreference.setVisible(securityType != WifiConfiguration.KeyMgmt.NONE);
}
@Override
@@ -98,9 +108,11 @@ public class WifiTetherPasswordPreferenceController extends WifiTetherBasePrefer
if (!TextUtils.isEmpty(mPassword)) {
pref.setIsSummaryPassword(true);
pref.setSummary(mPassword);
pref.setVisible(true);
} else {
pref.setIsSummaryPassword(false);
pref.setSummary(R.string.wifi_hotspot_no_password_subtext);
pref.setVisible(false);
}
}
}

View File

@@ -44,6 +44,7 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
private static final String WIFI_TETHER_SETTINGS = "wifi_tether";
private static final IntentFilter AIRPLANE_INTENT_FILTER = new IntentFilter(
Intent.ACTION_AIRPLANE_MODE_CHANGED);
private static final int ID_NULL = -1;
private final ConnectivityManager mConnectivityManager;
private final String[] mWifiRegexs;
@@ -152,7 +153,7 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
clearSummaryForAirplaneMode();
clearSummaryForAirplaneMode(R.string.wifi_hotspot_off_subtext);
}
}
};
@@ -194,10 +195,16 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
}
private void clearSummaryForAirplaneMode() {
clearSummaryForAirplaneMode(ID_NULL);
}
private void clearSummaryForAirplaneMode(int defaultId) {
boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
if (isAirplaneMode) {
mPreference.setSummary(R.string.wifi_tether_disabled_by_airplane);
} else if (defaultId != ID_NULL){
mPreference.setSummary(defaultId);
}
}
//

View File

@@ -0,0 +1,63 @@
package com.android.settings.wifi.tether;
import android.content.Context;
import android.content.res.Resources;
import android.net.wifi.WifiConfiguration;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import com.android.settings.R;
public class WifiTetherSecurityPreferenceController extends WifiTetherBasePreferenceController {
private static final String PREF_KEY = "wifi_tether_security";
private final String[] mSecurityEntries;
private int mSecurityValue;
public WifiTetherSecurityPreferenceController(Context context,
OnTetherConfigUpdateListener listener) {
super(context, listener);
mSecurityEntries = mContext.getResources().getStringArray(R.array.wifi_tether_security);
}
@Override
public String getPreferenceKey() {
return PREF_KEY;
}
@Override
public void updateDisplay() {
final WifiConfiguration config = mWifiManager.getWifiApConfiguration();
if (config != null && config.getAuthType() == WifiConfiguration.KeyMgmt.NONE) {
mSecurityValue = WifiConfiguration.KeyMgmt.NONE;
} else {
mSecurityValue = WifiConfiguration.KeyMgmt.WPA2_PSK;
}
final ListPreference preference = (ListPreference) mPreference;
preference.setSummary(getSummaryForSecurityType(mSecurityValue));
preference.setValue(String.valueOf(mSecurityValue));
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mSecurityValue = Integer.parseInt((String) newValue);
preference.setSummary(getSummaryForSecurityType(mSecurityValue));
mListener.onTetherConfigUpdated();
return true;
}
public int getSecurityType() {
return mSecurityValue;
}
private String getSummaryForSecurityType(int securityType) {
if (securityType == WifiConfiguration.KeyMgmt.NONE) {
return mSecurityEntries[1];
}
// WPA2 PSK
return mSecurityEntries[0];
}
}

View File

@@ -28,7 +28,6 @@ import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
@@ -41,7 +40,6 @@ import com.android.settingslib.core.AbstractPreferenceController;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class WifiTetherSettings extends RestrictedDashboardFragment
implements WifiTetherBasePreferenceController.OnTetherConfigUpdateListener {
@@ -54,6 +52,7 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
private WifiTetherSSIDPreferenceController mSSIDPreferenceController;
private WifiTetherPasswordPreferenceController mPasswordPreferenceController;
private WifiTetherApBandPreferenceController mApBandPreferenceController;
private WifiTetherSecurityPreferenceController mSecurityPreferenceController;
private WifiManager mWifiManager;
private boolean mRestartWifiApAfterConfigChange;
@@ -128,10 +127,12 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
mSSIDPreferenceController = new WifiTetherSSIDPreferenceController(context, this);
mSecurityPreferenceController = new WifiTetherSecurityPreferenceController(context, this);
mPasswordPreferenceController = new WifiTetherPasswordPreferenceController(context, this);
mApBandPreferenceController = new WifiTetherApBandPreferenceController(context, this);
controllers.add(mSSIDPreferenceController);
controllers.add(mSecurityPreferenceController);
controllers.add(mPasswordPreferenceController);
controllers.add(mApBandPreferenceController);
controllers.add(
@@ -142,6 +143,8 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
@Override
public void onTetherConfigUpdated() {
final WifiConfiguration config = buildNewConfig();
mPasswordPreferenceController.updateVisibility(config.getAuthType());
/**
* if soft AP is stopped, bring up
* else restart with new config
@@ -158,11 +161,11 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
private WifiConfiguration buildNewConfig() {
final WifiConfiguration config = new WifiConfiguration();
final int securityType = mSecurityPreferenceController.getSecurityType();
config.SSID = mSSIDPreferenceController.getSSID();
config.preSharedKey = mPasswordPreferenceController.getPassword();
config.allowedKeyManagement.set(
mPasswordPreferenceController.getSecuritySettingForPassword());
config.allowedKeyManagement.set(securityType);
config.preSharedKey = mPasswordPreferenceController.getPasswordValidated(securityType);
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
config.apBand = mApBandPreferenceController.getBandIndex();
return config;
@@ -176,6 +179,8 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
private void updateDisplayWithNewConfig() {
use(WifiTetherSSIDPreferenceController.class)
.updateDisplay();
use(WifiTetherSecurityPreferenceController.class)
.updateDisplay();
use(WifiTetherPasswordPreferenceController.class)
.updateDisplay();
use(WifiTetherApBandPreferenceController.class)

View File

@@ -62,6 +62,7 @@
<bool name="config_show_wifi_ip_address">false</bool>
<bool name="config_show_wifi_mac_address">false</bool>
<bool name="config_disable_uninstall_update">true</bool>
<bool name="config_show_logical_camera_default">false</bool>
<!-- List of a11y components on the device allowed to be enabled by Settings Slices -->
<string-array name="config_settings_slices_accessibility_components" translatable="false">

View File

@@ -22,4 +22,5 @@
<bool name="config_show_connectivity_monitor">true</bool>
<bool name="config_display_recent_apps">true</bool>
<bool name="config_wifi_support_connected_mac_randomization">true</bool>
</resources>
<bool name="config_show_logical_camera_default">true</bool>
</resources>

View File

@@ -43,6 +43,7 @@ public class BluetoothDeviceNamePreferenceControllerTest {
private static final String DEVICE_NAME = "Nightshade";
private static final int ORDER = 1;
private static final String KEY_DEVICE_NAME = "test_key_name";
private Context mContext;
@Mock
@@ -61,8 +62,9 @@ public class BluetoothDeviceNamePreferenceControllerTest {
when(mPreferenceScreen.getContext()).thenReturn(mContext);
mPreference = new Preference(mContext);
mPreference.setKey(BluetoothDeviceNamePreferenceController.KEY_DEVICE_NAME);
mController = spy(new BluetoothDeviceNamePreferenceController(mContext, mLocalAdapter));
mPreference.setKey(KEY_DEVICE_NAME);
mController = spy(new BluetoothDeviceNamePreferenceController(mContext, mLocalAdapter,
KEY_DEVICE_NAME));
doReturn(DEVICE_NAME).when(mController).getDeviceName();
}
@@ -82,7 +84,7 @@ public class BluetoothDeviceNamePreferenceControllerTest {
Preference preference =
mController.createBluetoothDeviceNamePreference(mPreferenceScreen, ORDER);
assertThat(preference.getKey()).isEqualTo(mController.KEY_DEVICE_NAME);
assertThat(preference.getKey()).isEqualTo(mController.getPreferenceKey());
assertThat(preference.getOrder()).isEqualTo(ORDER);
verify(mPreferenceScreen).addPreference(preference);
}

View File

@@ -67,8 +67,9 @@ public class BluetoothDeviceRenamePreferenceControllerTest {
mPreference = new Preference(mContext);
mPreference.setKey(PREF_KEY);
mController = spy(new BluetoothDeviceRenamePreferenceController(
mContext, PREF_KEY, mFragment, mLocalAdapter));
mController = spy(new BluetoothDeviceRenamePreferenceController(mContext, mLocalAdapter,
PREF_KEY));
mController.setFragment(mFragment);
doReturn(DEVICE_NAME).when(mController).getDeviceName();
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 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.connecteddevice;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import android.content.Context;
import com.android.settings.R;
import com.android.settings.nfc.NfcPreferenceController;
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.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowNfcAdapter;
import org.robolectric.util.ReflectionHelpers;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.robolectric.Shadows.shadowOf;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = ShadowNfcAdapter.class)
public class AdvancedConnectedDeviceControllerTest {
private static final String KEY = "test_key";
private Context mContext;
private NfcPreferenceController mNfcController;
private ShadowNfcAdapter mShadowNfcAdapter;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mNfcController = new NfcPreferenceController(mContext);
mShadowNfcAdapter = shadowOf(ShadowNfcAdapter.getNfcAdapter(mContext));
}
@Test
public void getAvailabilityStatus_returnStatusIsAvailable() {
AdvancedConnectedDeviceController controller =
new AdvancedConnectedDeviceController(mContext, KEY);
assertThat(controller.getAvailabilityStatus()).isEqualTo(
AVAILABLE);
}
@Test
public void getConnectedDevicesSummaryResourceId_NFCAndDrivingModeAvailable() {
// NFC available, driving mode available
final boolean isDrivingModeAvailable = true;
mShadowNfcAdapter.setEnabled(true);
assertThat(AdvancedConnectedDeviceController
.getConnectedDevicesSummaryResourceId(mNfcController, isDrivingModeAvailable))
.isEqualTo(R.string.connected_devices_dashboard_summary);
}
@Test
public void getConnectedDevicesSummaryResourceId_NFCAvailableAndDrivingModeNotAvailable() {
// NFC is available, driving mode not available
final boolean isDrivingModeAvailable = false;
mShadowNfcAdapter.setEnabled(true);
assertThat(AdvancedConnectedDeviceController
.getConnectedDevicesSummaryResourceId(mNfcController, isDrivingModeAvailable))
.isEqualTo(R.string.connected_devices_dashboard_no_driving_mode_summary);
}
@Test
public void getConnectedDevicesSummaryResourceId_NFCNotAvailableDrivingModeAvailable() {
// NFC not available, driving mode available
final boolean isDrivingModeAvailable = true;
ReflectionHelpers.setField(mNfcController, "mNfcAdapter", null);
assertThat(AdvancedConnectedDeviceController
.getConnectedDevicesSummaryResourceId(mNfcController, isDrivingModeAvailable))
.isEqualTo(R.string.connected_devices_dashboard_no_nfc_summary);
}
@Test
public void getConnectedDevicesSummaryResourceId_NFCAndDrivingModeNotAvailable() {
// NFC not available, driving mode not available
final boolean isDrivingModeAvailable = false;
ReflectionHelpers.setField(mNfcController, "mNfcAdapter", null);
assertThat(AdvancedConnectedDeviceController
.getConnectedDevicesSummaryResourceId(mNfcController, isDrivingModeAvailable))
.isEqualTo(R.string.connected_devices_dashboard_no_driving_mode_no_nfc_summary);
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright 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.connecteddevice;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v7.preference.Preference;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.dashboard.DashboardFragment;
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 static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.*;
@RunWith(SettingsRobolectricTestRunner.class)
public class PreviouslyConnectedDevicePreferenceControllerTest {
private final String KEY = "test_key";
@Mock
private DashboardFragment mDashboardFragment;
@Mock
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
@Mock
private PackageManager mPackageManager;
private Context mContext;
private PreviouslyConnectedDevicePreferenceController mPreConnectedDeviceController;
private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
doReturn(mContext).when(mDashboardFragment).getContext();
doReturn(mPackageManager).when(mContext).getPackageManager();
mPreConnectedDeviceController =
new PreviouslyConnectedDevicePreferenceController(mContext, KEY);
mPreConnectedDeviceController.setBluetoothDeviceUpdater(mBluetoothDeviceUpdater);
mPreference = new Preference(mContext);
mPreConnectedDeviceController.setPreference(mPreference);
}
@Test
public void callbackCanRegisterAndUnregister() {
// register the callback in onStart()
mPreConnectedDeviceController.onStart();
verify(mBluetoothDeviceUpdater).registerCallback();
// unregister the callback in onStop()
mPreConnectedDeviceController.onStop();
verify(mBluetoothDeviceUpdater).unregisterCallback();
}
@Test
public void getAvailabilityStatus_noBluetoothFeature_returnUnSupported() {
doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
assertThat(mPreConnectedDeviceController.getAvailabilityStatus()).isEqualTo(
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_hasBluetoothFeature_returnSupported() {
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
assertThat(mPreConnectedDeviceController.getAvailabilityStatus()).isEqualTo(
AVAILABLE);
}
@Test
public void onDeviceAdded_addFirstDevice_preferenceIsEnable() {
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
mPreConnectedDeviceController.setPreferenceSize(0);
mPreConnectedDeviceController.onDeviceAdded(mPreference);
assertThat(mPreference.isEnabled()).isTrue();
}
@Test
public void onDeviceRemoved_removeLastDevice_preferenceIsDisable() {
doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
mPreConnectedDeviceController.setPreferenceSize(1);
mPreConnectedDeviceController.onDeviceRemoved(mPreference);
assertThat(mPreference.isEnabled()).isFalse();
}
}

View File

@@ -162,13 +162,6 @@ public class SuggestionFeatureProviderImplTest {
assertThat(suggestions).hasSize(3);
}
@Test
public void nightDisplaySuggestion_isNotCompleted_byDefault() {
final ComponentName componentName =
new ComponentName(mContext, NightDisplaySuggestionActivity.class);
assertThat(mProvider.isSuggestionComplete(mContext, componentName)).isFalse();
}
@Test
public void testGetSmartSuggestionEnabledTaggedData_disabled() {
assertThat(mProvider.getLoggingTaggedData(mContext)).asList().containsExactly(

View File

@@ -0,0 +1,74 @@
/*
* 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.android.settings.development.BluetoothA2dpHwOffloadPreferenceController.A2DP_OFFLOAD_DISABLED_PROPERTY;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.SystemProperties;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.PreferenceScreen;
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;
@RunWith(SettingsRobolectricTestRunner.class)
public class BluetoothA2dpHwOffloadPreferenceControllerTest {
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock
private DevelopmentSettingsDashboardFragment mFragment;
private Context mContext;
private SwitchPreference mPreference;
private BluetoothA2dpHwOffloadPreferenceController mController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mPreference = new SwitchPreference(mContext);
mController = spy(new BluetoothA2dpHwOffloadPreferenceController(mContext, mFragment));
when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
.thenReturn(mPreference);
mController.displayPreference(mPreferenceScreen);
}
@Test
public void onA2dpHwDialogConfirmed_shouldChangeProperty() {
SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(false));
mController.onA2dpHwDialogConfirmed();
final boolean mode = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
assertThat(mode).isTrue();
mController.onA2dpHwDialogConfirmed();
final boolean mode2 = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
assertThat(mode2).isFalse();
}
}

View File

@@ -0,0 +1,140 @@
/*
* 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.android.settings.development.LogicalCameraDefaultPreferenceController.ENG_BUILD;
import static com.android.settings.development.LogicalCameraDefaultPreferenceController.USERDEBUG_BUILD;
import static com.android.settings.development.LogicalCameraDefaultPreferenceController.USER_BUILD;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.os.SystemProperties;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.PreferenceScreen;
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 org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
public class LogicalCameraDefaultPreferenceControllerTest {
@Mock
private PreferenceScreen mScreen;
@Mock
private SwitchPreference mPreference;
private LogicalCameraDefaultPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = new LogicalCameraDefaultPreferenceController(RuntimeEnvironment.application);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
mController.displayPreference(mScreen);
}
@Test
@Config(qualifiers = "mcc999")
public void isAvailable_withConfigNoShow_shouldReturnFalse() {
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_withUserdebugBuild_shouldReturnTrue() {
SystemProperties.set(LogicalCameraDefaultPreferenceController.BUILD_TYPE, USERDEBUG_BUILD);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_withEngBuild_shouldReturnTrue() {
SystemProperties.set(LogicalCameraDefaultPreferenceController.BUILD_TYPE, ENG_BUILD);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_withUserBuild_shouldReturnTrue() {
SystemProperties.set(LogicalCameraDefaultPreferenceController.BUILD_TYPE, USER_BUILD);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void updateState_logicalCameraDefaultEnabled_shouldCheckedPreference() {
SystemProperties.set(LogicalCameraDefaultPreferenceController.PROPERTY_LOGICAL_CAMERA_DEFAULT,
Integer.toString(LogicalCameraDefaultPreferenceController.ENABLED));
SystemProperties.set(LogicalCameraDefaultPreferenceController.BUILD_TYPE, USERDEBUG_BUILD);
mController.updateState(mScreen);
verify(mPreference).setChecked(true);
}
@Test
public void updateState_logicalCameraDefaultEnabled_shouldUncheckedPreference() {
SystemProperties.set(LogicalCameraDefaultPreferenceController.PROPERTY_LOGICAL_CAMERA_DEFAULT,
Integer.toString(LogicalCameraDefaultPreferenceController.DISABLED));
SystemProperties.set(
LogicalCameraDefaultPreferenceController.BUILD_TYPE, USERDEBUG_BUILD);
mController.updateState(mScreen);
verify(mPreference).setChecked(false);
}
@Test
public void onPreferenceChange_preferenceChecked_shouldEnableLogicalCameraDefault() {
mController.onPreferenceChange(mPreference, true);
assertThat(Integer.toString(LogicalCameraDefaultPreferenceController.ENABLED)).isEqualTo(
SystemProperties.get(
LogicalCameraDefaultPreferenceController.PROPERTY_LOGICAL_CAMERA_DEFAULT,
Integer.toString(LogicalCameraDefaultPreferenceController.ENABLED)));
}
@Test
public void onPreferenceChange_preferenceUnchecked_shouldDisableLogicalCameraDefault() {
mController.onPreferenceChange(mPreference, false);
assertThat(Integer.toString(LogicalCameraDefaultPreferenceController.DISABLED)).isEqualTo(
SystemProperties.get(
LogicalCameraDefaultPreferenceController.PROPERTY_LOGICAL_CAMERA_DEFAULT,
Integer.toString(LogicalCameraDefaultPreferenceController.ENABLED)));
}
@Test
public void onDeveloperOptionsSwitchDisabled_preferenceShouldBeEnabled() {
mController.onDeveloperOptionsSwitchDisabled();
verify(mPreference).setEnabled(false);
verify(mPreference).setChecked(false);
assertThat(Integer.toString(LogicalCameraDefaultPreferenceController.DISABLED)).isEqualTo(
SystemProperties.get(
LogicalCameraDefaultPreferenceController.PROPERTY_LOGICAL_CAMERA_DEFAULT,
Integer.toString(LogicalCameraDefaultPreferenceController.ENABLED)));
}
}

View File

@@ -6,15 +6,22 @@ import android.app.Application;
import android.content.ComponentName;
import android.provider.Settings.Secure;
import com.android.internal.app.ColorDisplayController;
import com.android.settings.R;
import com.android.settings.Settings.NightDisplaySuggestionActivity;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {
SettingsShadowResources.class
})
public class NightDisplayPreferenceControllerTest {
private NightDisplayPreferenceController mPreferenceController;
@@ -27,6 +34,7 @@ public class NightDisplayPreferenceControllerTest {
@After
public void tearDown() {
mPreferenceController = null;
SettingsShadowResources.reset();
}
@Test
@@ -58,4 +66,16 @@ public class NightDisplayPreferenceControllerTest {
new ComponentName(context, NightDisplaySuggestionActivity.class);
assertThat(mPreferenceController.isSuggestionComplete(context)).isTrue();
}
@Test
public void nightDisplaySuggestion_isCompleted_ifDisabled() {
final Application context = RuntimeEnvironment.application;
Secure.putInt(context.getContentResolver(),
Secure.NIGHT_DISPLAY_AUTO_MODE, ColorDisplayController.AUTO_MODE_DISABLED);
SettingsShadowResources.overrideResource(R.bool.config_night_light_suggestion_enabled, false);
final ComponentName componentName =
new ComponentName(context, NightDisplaySuggestionActivity.class);
assertThat(mPreferenceController.isSuggestionComplete(context)).isTrue();
}
}

View File

@@ -53,6 +53,8 @@ import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.fuelgauge.anomaly.Anomaly;
import com.android.settings.fuelgauge.batterytip.AnomalyInfo;
import com.android.settings.fuelgauge.batterytip.StatsManagerConfig;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
@@ -106,6 +108,9 @@ public class BatteryUtilsTest {
private static final String HIGH_SDK_PACKAGE = "com.android.package.high";
private static final String LOW_SDK_PACKAGE = "com.android.package.low";
private static final String INFO_EXCESSIVE = "anomaly_type=4,auto_restriction=false";
private static final String INFO_WAKELOCK = "anomaly_type=1,auto_restriction=false";
@Mock
private BatteryStats.Uid mUid;
@Mock
@@ -146,6 +151,7 @@ public class BatteryUtilsTest {
private ApplicationInfo mLowApplicationInfo;
@Mock
private PowerWhitelistBackend mPowerWhitelistBackend;
private AnomalyInfo mAnomalyInfo;
private BatteryUtils mBatteryUtils;
private FakeFeatureFactory mFeatureFactory;
private PowerUsageFeatureProvider mProvider;
@@ -211,6 +217,7 @@ public class BatteryUtilsTest {
mBatteryUtils.mPowerUsageFeatureProvider = mProvider;
doReturn(0L).when(mBatteryUtils)
.getForegroundServiceTotalTimeUs(any(BatteryStats.Uid.class), anyLong());
mAnomalyInfo = new AnomalyInfo(INFO_WAKELOCK);
mUsageList = new ArrayList<>();
mUsageList.add(mNormalBatterySipper);
@@ -532,15 +539,26 @@ public class BatteryUtilsTest {
}
@Test
public void testIsLegacyApp_SdkLowerThanO_ReturnTrue() {
public void testIsPreOApp_SdkLowerThanO_ReturnTrue() {
assertThat(mBatteryUtils.isPreOApp(LOW_SDK_PACKAGE)).isTrue();
}
@Test
public void testIsLegacyApp_SdkLargerOrEqualThanO_ReturnFalse() {
public void testIsPreOApp_SdkLargerOrEqualThanO_ReturnFalse() {
assertThat(mBatteryUtils.isPreOApp(HIGH_SDK_PACKAGE)).isFalse();
}
@Test
public void testIsPreOApp_containPreOApp_ReturnTrue() {
assertThat(
mBatteryUtils.isPreOApp(new String[]{HIGH_SDK_PACKAGE, LOW_SDK_PACKAGE})).isTrue();
}
@Test
public void testIsPreOApp_emptyList_ReturnFalse() {
assertThat(mBatteryUtils.isPreOApp(new String[]{})).isFalse();
}
@Test
public void testSetForceAppStandby_forcePreOApp_forceTwoRestrictions() {
mBatteryUtils.setForceAppStandby(UID, LOW_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
@@ -591,7 +609,8 @@ public class BatteryUtilsTest {
doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
mHighApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID)).isTrue();
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
mAnomalyInfo)).isTrue();
}
@Test
@@ -600,7 +619,8 @@ public class BatteryUtilsTest {
doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
mHighApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID)).isTrue();
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
mAnomalyInfo)).isTrue();
}
@Test
@@ -608,7 +628,8 @@ public class BatteryUtilsTest {
final int systemUid = Process.ROOT_UID;
doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(systemUid);
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, systemUid)).isTrue();
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, systemUid,
mAnomalyInfo)).isTrue();
}
@Test
@@ -616,13 +637,33 @@ public class BatteryUtilsTest {
doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
doReturn(true).when(mPowerWhitelistBackend).isWhitelisted(new String[]{HIGH_SDK_PACKAGE});
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID)).isTrue();
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
mAnomalyInfo)).isTrue();
}
@Test
public void testShouldHideAnomaly_normalApp_returnFalse() {
doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID)).isFalse();
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
mAnomalyInfo)).isFalse();
}
@Test
public void testShouldHideAnomaly_excessivePriorOApp_returnFalse() {
doReturn(new String[]{LOW_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
mAnomalyInfo = new AnomalyInfo(INFO_EXCESSIVE);
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
mAnomalyInfo)).isFalse();
}
@Test
public void testShouldHideAnomaly_excessiveOApp_returnTrue() {
doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
mAnomalyInfo = new AnomalyInfo(INFO_EXCESSIVE);
assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID,
mAnomalyInfo)).isTrue();
}
}

View File

@@ -165,7 +165,7 @@ public class AnomalyDetectionJobServiceTest {
doReturn(false).when(mPowerWhitelistBackend).isSysWhitelisted(SYSTEM_PACKAGE);
doReturn(Process.FIRST_APPLICATION_UID).when(
mAnomalyDetectionJobService).extractUidFromStatsDimensionsValue(any());
doReturn(true).when(mBatteryUtils).shouldHideAnomaly(any(), anyInt());
doReturn(true).when(mBatteryUtils).shouldHideAnomaly(any(), anyInt(), any());
mAnomalyDetectionJobService.saveAnomalyToDatabase(mContext,
mUserManager, mBatteryDatabaseManager, mBatteryUtils, mPolicy,

View File

@@ -60,6 +60,7 @@ public class RestrictAppTipTest {
private RestrictAppTip mHandledBatteryTip;
private RestrictAppTip mInvisibleBatteryTip;
private List<AppInfo> mUsageAppList;
private AppInfo mAppInfo;
@Mock
private ApplicationInfo mApplicationInfo;
@Mock
@@ -77,15 +78,16 @@ public class RestrictAppTipTest {
PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_ANY_USER);
doReturn(DISPLAY_NAME).when(mApplicationInfo).loadLabel(mPackageManager);
mUsageAppList = new ArrayList<>();
mUsageAppList.add(new AppInfo.Builder()
mAppInfo = new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
.addAnomalyType(ANOMALY_WAKEUP)
.addAnomalyType(ANOMALY_WAKELOCK)
.build());
.build();
mUsageAppList = new ArrayList<>();
mUsageAppList.add(mAppInfo);
mNewBatteryTip = new RestrictAppTip(BatteryTip.StateType.NEW, mUsageAppList);
mHandledBatteryTip = new RestrictAppTip(BatteryTip.StateType.HANDLED, mUsageAppList);
mInvisibleBatteryTip = new RestrictAppTip(BatteryTip.StateType.INVISIBLE, mUsageAppList);
mInvisibleBatteryTip = new RestrictAppTip(BatteryTip.StateType.INVISIBLE, new ArrayList<>());
}
@Test
@@ -164,6 +166,13 @@ public class RestrictAppTipTest {
assertThat(mHandledBatteryTip.getState()).isEqualTo(BatteryTip.StateType.NEW);
}
@Test
public void update_newHandledAnomalyComes_containHandledAnomaly() {
mInvisibleBatteryTip.updateState(mHandledBatteryTip);
assertThat(mInvisibleBatteryTip.getState()).isEqualTo(BatteryTip.StateType.HANDLED);
assertThat(mInvisibleBatteryTip.getRestrictAppList()).containsExactly(mAppInfo);
}
@Test
public void toString_containsAppData() {
assertThat(mNewBatteryTip.toString()).isEqualTo(

View File

@@ -0,0 +1,112 @@
/*
* 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.notification;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.provider.Settings;
import android.support.v4.graphics.drawable.IconCompat;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.SliceTester;
import com.android.settings.testutils.shadow.ShadowNotificationManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.List;
import androidx.slice.Slice;
import androidx.slice.SliceItem;
import androidx.slice.SliceMetadata;
import androidx.slice.SliceProvider;
import androidx.slice.core.SliceAction;
import androidx.slice.widget.SliceLiveData;
@Config(shadows = ShadowNotificationManager.class)
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModeSliceBuilderTest {
private Context mContext;
@Before
public void setUp() {
mContext = spy(RuntimeEnvironment.application);
// Prevent crash in SliceMetadata.
Resources resources = spy(mContext.getResources());
doReturn(60).when(resources).getDimensionPixelSize(anyInt());
doReturn(resources).when(mContext).getResources();
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
}
@Test
public void getZenModeSlice_correctSliceContent() {
final Slice dndSlice = ZenModeSliceBuilder.getSlice(mContext);
final SliceMetadata metadata = SliceMetadata.from(mContext, dndSlice);
final List<SliceAction> toggles = metadata.getToggles();
assertThat(toggles).hasSize(1);
final SliceAction primaryAction = metadata.getPrimaryAction();
assertThat(primaryAction.getIcon()).isNull();
final List<SliceItem> sliceItems = dndSlice.getItems();
SliceTester.assertTitle(sliceItems, mContext.getString(R.string.zen_mode_settings_title));
}
@Test
public void handleUriChange_turnOn_zenModeTurnsOn() {
final Intent intent = new Intent();
intent.putExtra(EXTRA_TOGGLE_STATE, true);
NotificationManager.from(mContext).setZenMode(Settings.Global.ZEN_MODE_OFF, null, "");
ZenModeSliceBuilder.handleUriChange(mContext, intent);
final int zenMode = NotificationManager.from(mContext).getZenMode();
assertThat(zenMode).isEqualTo(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
}
@Test
public void handleUriChange_turnOff_zenModeTurnsOff() {
final Intent intent = new Intent();
intent.putExtra(EXTRA_TOGGLE_STATE, false);
NotificationManager.from(mContext).setZenMode(
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, "");
ZenModeSliceBuilder.handleUriChange(mContext, intent);
final int zenMode = NotificationManager.from(mContext).getZenMode();
assertThat(zenMode).isEqualTo(Settings.Global.ZEN_MODE_OFF);
}
}

View File

@@ -85,6 +85,7 @@ public class ZenModeVisEffectsCustomPreferenceControllerTest {
ReflectionHelpers.setField(mController, "mBackend", mBackend);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
mController.displayPreference(mScreen);
}
@Test

View File

@@ -15,7 +15,6 @@
package com.android.settings.search;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -24,6 +23,7 @@ import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.job.JobScheduler;
import android.provider.Settings;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -47,7 +47,7 @@ public class DeviceIndexFeatureProviderTest {
}
@Test
public void verifyDisabled() {
public void updateIndex_disabled_shouldDoNothing() {
when(mProvider.isIndexingEnabled()).thenReturn(false);
mProvider.updateIndex(mActivity, false);
@@ -55,7 +55,20 @@ public class DeviceIndexFeatureProviderTest {
}
@Test
public void verifyIndexing() {
public void updateIndex_enabled_unprovisioned_shouldDoNothing() {
when(mProvider.isIndexingEnabled()).thenReturn(true);
Settings.Global.putInt(mActivity.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0);
mProvider.updateIndex(mActivity, false);
verify(mProvider, never()).index(any(), any(), any(), any(), any());
}
@Test
public void updateIndex_enabled_provisioned_shouldIndex() {
Settings.Global.putInt(mActivity.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
JobScheduler jobScheduler = mock(JobScheduler.class);
when(mProvider.isIndexingEnabled()).thenReturn(true);
when(mActivity.getSystemService(JobScheduler.class)).thenReturn(jobScheduler);

View File

@@ -18,9 +18,13 @@
package com.android.settings.slices;
import static android.content.ContentResolver.SCHEME_CONTENT;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.slice.SliceManager;
@@ -31,6 +35,8 @@ import android.net.Uri;
import android.os.StrictMode;
import android.provider.SettingsSlicesContract;
import com.android.settings.wifi.WifiSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.testutils.DatabaseTestUtils;
import com.android.settings.testutils.FakeToggleController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -45,6 +51,8 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import androidx.slice.Slice;
@@ -70,6 +78,14 @@ public class SettingsSliceProviderTest {
private SQLiteDatabase mDb;
private SliceManager mManager;
private static final List<Uri> SPECIAL_CASE_PLATFORM_URIS = Arrays.asList(
WifiSliceBuilder.WIFI_URI
);
private static final List<Uri> SPECIAL_CASE_OEM_URIS = Arrays.asList(
ZenModeSliceBuilder.ZEN_MODE_URI
);
@Before
public void setUp() {
mContext = spy(RuntimeEnvironment.application);
@@ -94,7 +110,7 @@ public class SettingsSliceProviderTest {
@Test
public void testInitialSliceReturned_emptySlice() {
insertSpecialCase(KEY);
Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
Slice slice = mProvider.onBindSlice(uri);
assertThat(slice.getUri()).isEqualTo(uri);
@@ -104,7 +120,7 @@ public class SettingsSliceProviderTest {
@Test
public void testLoadSlice_returnsSliceFromAccessor() {
insertSpecialCase(KEY);
Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
mProvider.loadSlice(uri);
SliceData data = mProvider.mSliceWeakDataCache.get(uri);
@@ -114,9 +130,19 @@ public class SettingsSliceProviderTest {
}
@Test
public void testLoadSlice_doesntCacheWithoutPin() {
public void loadSlice_registersIntentFilter() {
insertSpecialCase(KEY);
Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
mProvider.loadSlice(uri);
verify(mProvider).registerIntentToUri(eq(FakeToggleController.INTENT_FILTER), eq(uri));
}
@Test
public void testLoadSlice_doesNotCacheWithoutPin() {
insertSpecialCase(KEY);
final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
mProvider.loadSlice(uri);
SliceData data = mProvider.mSliceDataCache.get(uri);
@@ -127,7 +153,7 @@ public class SettingsSliceProviderTest {
@Test
public void testLoadSlice_cachesWithPin() {
insertSpecialCase(KEY);
Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
when(mManager.getPinnedSlices()).thenReturn(Arrays.asList(uri));
mProvider.loadSlice(uri);
@@ -213,6 +239,7 @@ public class SettingsSliceProviderTest {
.build();
final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
descendants.removeAll(SPECIAL_CASE_OEM_URIS);
assertThat(descendants).isEmpty();
}
@@ -226,6 +253,7 @@ public class SettingsSliceProviderTest {
.build();
final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
descendants.removeAll(SPECIAL_CASE_PLATFORM_URIS);
assertThat(descendants).isEmpty();
}
@@ -239,6 +267,7 @@ public class SettingsSliceProviderTest {
.build();
final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
descendants.removeAll(SPECIAL_CASE_OEM_URIS);
assertThat(descendants).isEmpty();
}
@@ -252,16 +281,18 @@ public class SettingsSliceProviderTest {
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.build();
final Uri expectedUri = new Uri.Builder()
final Collection<Uri> expectedUris = new HashSet<>();
expectedUris.addAll(SPECIAL_CASE_OEM_URIS);
expectedUris.add(new Uri.Builder()
.scheme(SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(key)
.build();
.build());
final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
assertThat(descendants).containsExactly(expectedUri);
assertThat(descendants).containsExactlyElementsIn(expectedUris);
}
@Test
@@ -272,16 +303,18 @@ public class SettingsSliceProviderTest {
.scheme(SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.build();
final Uri expectedUri = new Uri.Builder()
final Collection<Uri> expectedUris = new HashSet<>();
expectedUris.addAll(SPECIAL_CASE_OEM_URIS);
expectedUris.add(new Uri.Builder()
.scheme(SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(key)
.build();
.build());
final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
assertThat(descendants).containsExactly(expectedUri);
assertThat(descendants).containsExactlyElementsIn(expectedUris);
}
@Test
@@ -293,16 +326,18 @@ public class SettingsSliceProviderTest {
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.build();
final Uri expectedUri = new Uri.Builder()
final Collection<Uri> expectedUris = new HashSet<>();
expectedUris.addAll(SPECIAL_CASE_PLATFORM_URIS);
expectedUris.add(new Uri.Builder()
.scheme(SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(key)
.build();
.build());
final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
assertThat(descendants).containsExactly(expectedUri);
assertThat(descendants).containsExactlyElementsIn(expectedUris);
}
@Test
@@ -313,16 +348,18 @@ public class SettingsSliceProviderTest {
.scheme(SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.build();
final Uri expectedUri = new Uri.Builder()
final Collection<Uri> expectedUris = new HashSet<>();
expectedUris.addAll(SPECIAL_CASE_PLATFORM_URIS);
expectedUris.add(new Uri.Builder()
.scheme(SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(key)
.build();
.build());
final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
assertThat(descendants).containsExactly(expectedUri);
assertThat(descendants).containsExactlyElementsIn(expectedUris);
}
@Test
@@ -334,22 +371,32 @@ public class SettingsSliceProviderTest {
final Uri uri = new Uri.Builder()
.scheme(SCHEME_CONTENT)
.build();
final Uri expectedPlatformUri = new Uri.Builder()
final Collection<Uri> expectedUris = new HashSet<>();
expectedUris.addAll(SPECIAL_CASE_PLATFORM_URIS);
expectedUris.addAll(SPECIAL_CASE_OEM_URIS);
expectedUris.add(new Uri.Builder()
.scheme(SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(platformKey)
.build();
final Uri expectedOemUri = new Uri.Builder()
.build());
expectedUris.add(new Uri.Builder()
.scheme(SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(oemKey)
.build();
.build());
final Collection<Uri> descendants = mProvider.onGetSliceDescendants(uri);
assertThat(descendants).containsExactly(expectedPlatformUri, expectedOemUri);
assertThat(descendants).containsExactlyElementsIn(expectedUris);
}
@Test
public void bindSlice_wifiSlice_returnsWifiSlice() {
final Slice wifiSlice = mProvider.onBindSlice(WifiSliceBuilder.WIFI_URI);
assertThat(wifiSlice.getUri()).isEqualTo(WifiSliceBuilder.WIFI_URI);
}
private void insertSpecialCase(String key) {
@@ -364,7 +411,7 @@ public class SettingsSliceProviderTest {
values.put(SlicesDatabaseHelper.IndexColumns.SCREENTITLE, "s");
values.put(SlicesDatabaseHelper.IndexColumns.ICON_RESOURCE, 1234);
values.put(SlicesDatabaseHelper.IndexColumns.FRAGMENT, "test");
values.put(SlicesDatabaseHelper.IndexColumns.CONTROLLER, "test");
values.put(SlicesDatabaseHelper.IndexColumns.CONTROLLER, PREF_CONTROLLER);
values.put(SlicesDatabaseHelper.IndexColumns.PLATFORM_SLICE, isPlatformSlice);
values.put(SlicesDatabaseHelper.IndexColumns.SLICE_TYPE, SliceData.SliceType.INTENT);

View File

@@ -226,7 +226,7 @@ public class AudioOutputSwitchPreferenceControllerTest {
mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_1);
assertThat(mPreference.getSummary()).isEqualTo(mBluetoothDevice.getName());
assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1);
}
/**
@@ -246,7 +246,7 @@ public class AudioOutputSwitchPreferenceControllerTest {
mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_2);
assertThat(mPreference.getSummary()).isEqualTo(secondBluetoothDevice.getName());
assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2);
}
/**

View File

@@ -16,7 +16,6 @@
package com.android.settings.sound;
import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID;
import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET;
@@ -93,6 +92,8 @@ public class HandsFreeProfileOutputPreferenceControllerTest {
private HeadsetProfile mHeadsetProfile;
@Mock
private HearingAidProfile mHearingAidProfile;
@Mock
private AudioSwitchPreferenceController.AudioSwitchCallback mAudioSwitchPreferenceCallback;
private Context mContext;
private PreferenceScreen mScreen;
@@ -156,6 +157,7 @@ public class HandsFreeProfileOutputPreferenceControllerTest {
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mScreen.addPreference(mPreference);
mController.displayPreference(mScreen);
mController.setCallback(mAudioSwitchPreferenceCallback);
}
@After
@@ -251,7 +253,7 @@ public class HandsFreeProfileOutputPreferenceControllerTest {
mController.updateState(mPreference);
assertThat(mPreference.isVisible()).isTrue();
assertThat(mPreference.getSummary()).isEqualTo(mBluetoothDevice.getName());
assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1);
}
/**
@@ -273,7 +275,7 @@ public class HandsFreeProfileOutputPreferenceControllerTest {
mController.updateState(mPreference);
assertThat(mPreference.isVisible()).isTrue();
assertThat(mPreference.getSummary()).isEqualTo(mSecondBluetoothDevice.getName());
assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2);
}
/**

View File

@@ -94,6 +94,8 @@ public class MediaOutputPreferenceControllerTest {
private A2dpProfile mA2dpProfile;
@Mock
private HearingAidProfile mHearingAidProfile;
@Mock
private AudioSwitchPreferenceController.AudioSwitchCallback mAudioSwitchPreferenceCallback;
private Context mContext;
private PreferenceScreen mScreen;
@@ -157,6 +159,7 @@ public class MediaOutputPreferenceControllerTest {
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mScreen.addPreference(mPreference);
mController.displayPreference(mScreen);
mController.setCallback(mAudioSwitchPreferenceCallback);
}
@After
@@ -302,7 +305,7 @@ public class MediaOutputPreferenceControllerTest {
mController.updateState(mPreference);
assertThat(mPreference.isVisible()).isTrue();
assertThat(mPreference.getSummary()).isEqualTo(mBluetoothDevice.getName());
assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_1);
}
/**
@@ -323,7 +326,7 @@ public class MediaOutputPreferenceControllerTest {
mController.updateState(mPreference);
assertThat(mPreference.isVisible()).isTrue();
assertThat(mPreference.getSummary()).isEqualTo(mSecondBluetoothDevice.getName());
assertThat(mPreference.getSummary()).isEqualTo(TEST_DEVICE_NAME_2);
}
/**

View File

@@ -18,6 +18,8 @@
package com.android.settings.testutils;
import android.content.Context;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
import android.provider.Settings;
import com.android.settings.core.TogglePreferenceController;
@@ -28,6 +30,9 @@ public class FakeToggleController extends TogglePreferenceController {
public static final String AVAILABILITY_KEY = "fake_toggle_availability_key";
public static final IntentFilter INTENT_FILTER = new IntentFilter(
WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
private final int ON = 1;
private final int OFF = 0;
@@ -52,4 +57,9 @@ public class FakeToggleController extends TogglePreferenceController {
return Settings.Global.getInt(mContext.getContentResolver(),
AVAILABILITY_KEY, AVAILABLE);
}
@Override
public IntentFilter getIntentFilter() {
return INTENT_FILTER;
}
}

View File

@@ -0,0 +1,35 @@
/*
* 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.testutils;
import android.content.pm.ApplicationInfo;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.IconDrawableFactory;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(IconDrawableFactory.class)
public class ShadowIconDrawableFactory {
@Implementation
public Drawable getBadgedIcon(ApplicationInfo appInfo) {
return new ColorDrawable(Color.BLUE);
}
}

View File

@@ -35,6 +35,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import androidx.slice.Slice;
import androidx.slice.SliceItem;
@@ -211,7 +212,7 @@ public class SliceTester {
assertKeywords(metadata, sliceData);
}
private static void assertTitle(List<SliceItem> sliceItems, String title) {
public static void assertTitle(List<SliceItem> sliceItems, String title) {
boolean hasTitle = false;
for (SliceItem item : sliceItems) {
List<SliceItem> titleItems = SliceQuery.findAll(item, FORMAT_TEXT, HINT_TITLE,
@@ -230,8 +231,9 @@ public class SliceTester {
private static void assertKeywords(SliceMetadata metadata, SliceData data) {
final List<String> keywords = metadata.getSliceKeywords();
final Set<String> expectedKeywords = new HashSet<>(
Arrays.asList(data.getKeywords().split(",")));
final Set<String> expectedKeywords = Arrays.stream(data.getKeywords().split(","))
.map(s -> s = s.trim())
.collect(Collectors.toSet());
expectedKeywords.add(data.getTitle());
expectedKeywords.add(data.getScreenTitle().toString());
assertThat(keywords).containsExactlyElementsIn(expectedKeywords);

View File

@@ -31,6 +31,7 @@ import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.ColorDrawable;
@@ -39,12 +40,14 @@ import android.support.v7.preference.Preference;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.ShadowIconDrawableFactory;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
@@ -53,6 +56,7 @@ import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
public class EntityHeaderControllerTest {
@@ -68,12 +72,10 @@ public class EntityHeaderControllerTest {
private LayoutInflater mLayoutInflater;
private PackageInfo mInfo;
private EntityHeaderController mController;
private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mFeatureFactory = FakeFeatureFactory.setupForTest();
mShadowContext = RuntimeEnvironment.application;
when(mActivity.getApplicationContext()).thenReturn(mShadowContext);
when(mContext.getApplicationContext()).thenReturn(mContext);
@@ -254,6 +256,23 @@ public class EntityHeaderControllerTest {
.isEqualTo(description);
}
@Test
@Config(shadows = ShadowIconDrawableFactory.class)
public void setIcon_usingAppEntry_shouldLoadIconFromDrawableFactory() {
final View view = mLayoutInflater
.inflate(R.layout.settings_entity_header, null /* root */);
final ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
entry.info = new ApplicationInfo();
mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
mController.setIcon(entry).done(mActivity);
final ImageView iconView = view.findViewById(R.id.entity_header_icon);
// Icon is set
assertThat(iconView.getDrawable()).isNotNull();
// ... and entry.icon is still empty. This means the icon didn't come from cache.
assertThat(entry.icon).isNull();
}
@Test
public void bindButton_hasAppNotifIntent_shouldShowButton() {
final View appLinks = mLayoutInflater

View File

@@ -0,0 +1,90 @@
/*
* Copyright 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.widget;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.support.v7.preference.ListPreference;
import android.widget.ArrayAdapter;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
import static org.mockito.Mockito.spy;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = ShadowBluetoothUtils.class)
public class UpdatableListPreferenceDialogFragmentTest {
private Context mContext;
private UpdatableListPreferenceDialogFragment mUpdatableListPrefDlgFragment;
private static final String KEY = "Test_Key";
private ArrayAdapter mAdapter;
private ArrayList<CharSequence> mEntries;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mUpdatableListPrefDlgFragment = UpdatableListPreferenceDialogFragment
.newInstance(KEY, MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES);
mEntries = spy(new ArrayList<>());
mUpdatableListPrefDlgFragment.setEntries(mEntries);
mUpdatableListPrefDlgFragment.
setMetricsCategory(mUpdatableListPrefDlgFragment.getArguments());
initAdapter();
}
private void initAdapter() {
mAdapter = spy(new ArrayAdapter<>(
mContext,
com.android.internal.R.layout.select_dialog_singlechoice,
mEntries));
mUpdatableListPrefDlgFragment.setAdapter(mAdapter);
}
@Test
public void getMetricsCategory() {
assertThat(mUpdatableListPrefDlgFragment.getMetricsCategory())
.isEqualTo(MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES);
}
@Test
public void onListPreferenceUpdated_verifyAdapterCanBeUpdate() {
assertThat(mUpdatableListPrefDlgFragment.getAdapter().getCount()).
isEqualTo(0);
ListPreference listPreference = new ListPreference(mContext);
final CharSequence[] charSequences = {"Test_DEVICE_1", "Test_DEVICE_2"};
listPreference.setEntries(charSequences);
mUpdatableListPrefDlgFragment.onListPreferenceUpdated(listPreference);
assertThat(mUpdatableListPrefDlgFragment.getAdapter().getCount()).
isEqualTo(2);
}
}

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