Snap for 4696032 from a62df616f9 to pi-release

Change-Id: Ieecef95e84d12234f67b1a8496a5cf905f26d02a
This commit is contained in:
android-build-team Robot
2018-04-03 07:22:38 +00:00
83 changed files with 2031 additions and 1551 deletions

View File

@@ -525,7 +525,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="64" line="62"
column="5"/> column="5"/>
</issue> </issue>
@@ -541,7 +541,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="65" line="63"
column="5"/> column="5"/>
</issue> </issue>
@@ -557,7 +557,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="66" line="64"
column="5"/> column="5"/>
</issue> </issue>
@@ -573,7 +573,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="67" line="65"
column="5"/> column="5"/>
</issue> </issue>
@@ -589,7 +589,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="69" line="67"
column="5"/> column="5"/>
</issue> </issue>
@@ -605,7 +605,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="72" line="70"
column="5"/> column="5"/>
</issue> </issue>
@@ -621,7 +621,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="74" line="72"
column="5"/> column="5"/>
</issue> </issue>
@@ -637,7 +637,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="75" line="73"
column="5"/> column="5"/>
</issue> </issue>
@@ -653,7 +653,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="78" line="76"
column="5"/> column="5"/>
</issue> </issue>
@@ -669,7 +669,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="79" line="77"
column="5"/> column="5"/>
</issue> </issue>
@@ -685,7 +685,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="80" line="78"
column="5"/> column="5"/>
</issue> </issue>
@@ -701,7 +701,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="81" line="79"
column="5"/> column="5"/>
</issue> </issue>
@@ -717,7 +717,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="82" line="80"
column="5"/> column="5"/>
</issue> </issue>
@@ -733,7 +733,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="85" line="83"
column="5"/> column="5"/>
</issue> </issue>
@@ -749,7 +749,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="86" line="84"
column="5"/> column="5"/>
</issue> </issue>
@@ -765,7 +765,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="87" line="85"
column="5"/> column="5"/>
</issue> </issue>
@@ -781,7 +781,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="88" line="86"
column="5"/> column="5"/>
</issue> </issue>
@@ -797,7 +797,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="89" line="87"
column="5"/> column="5"/>
</issue> </issue>
@@ -813,7 +813,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="90" line="88"
column="5"/> column="5"/>
</issue> </issue>
@@ -829,7 +829,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="91" line="89"
column="5"/> column="5"/>
</issue> </issue>
@@ -845,7 +845,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="92" line="90"
column="5"/> column="5"/>
</issue> </issue>
@@ -861,7 +861,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="93" line="91"
column="5"/> column="5"/>
</issue> </issue>
@@ -877,7 +877,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="94" line="92"
column="5"/> column="5"/>
</issue> </issue>
@@ -893,23 +893,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="95" line="93"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;importance_secondary_slider_color&quot;>#858383&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="98"
column="5"/> column="5"/>
</issue> </issue>
@@ -925,7 +909,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="100" line="95"
column="5"/> column="5"/>
</issue> </issue>
@@ -941,7 +925,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="103" line="98"
column="5"/> column="5"/>
</issue> </issue>
@@ -957,7 +941,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="105" line="100"
column="5"/> column="5"/>
</issue> </issue>
@@ -973,7 +957,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="108" line="103"
column="5"/> column="5"/>
</issue> </issue>
@@ -989,7 +973,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="111" line="106"
column="5"/> column="5"/>
</issue> </issue>
@@ -1005,7 +989,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="114" line="109"
column="5"/> column="5"/>
</issue> </issue>
@@ -1021,7 +1005,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="117" line="112"
column="5"/> column="5"/>
</issue> </issue>
@@ -1037,7 +1021,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="118" line="113"
column="5"/> column="5"/>
</issue> </issue>
@@ -1053,7 +1037,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="121" line="116"
column="5"/> column="5"/>
</issue> </issue>
@@ -1069,7 +1053,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="122" line="117"
column="5"/> column="5"/>
</issue> </issue>
@@ -1085,7 +1069,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="123" line="118"
column="5"/> column="5"/>
</issue> </issue>
@@ -1101,7 +1085,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="124" line="119"
column="5"/> column="5"/>
</issue> </issue>
@@ -1117,7 +1101,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="125" line="120"
column="5"/> column="5"/>
</issue> </issue>
@@ -1133,7 +1117,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="126" line="121"
column="5"/> column="5"/>
</issue> </issue>
@@ -1149,7 +1133,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="127" line="122"
column="5"/> column="5"/>
</issue> </issue>
@@ -1165,7 +1149,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="128" line="123"
column="5"/> column="5"/>
</issue> </issue>
@@ -1181,7 +1165,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="129" line="124"
column="5"/> column="5"/>
</issue> </issue>
@@ -1197,7 +1181,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="130" line="125"
column="5"/> column="5"/>
</issue> </issue>
@@ -1213,7 +1197,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="131" line="126"
column="5"/> column="5"/>
</issue> </issue>
@@ -1229,7 +1213,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="132" line="127"
column="5"/> column="5"/>
</issue> </issue>
@@ -1243,6 +1227,22 @@
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." explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;homepage_generic_icon_background&quot;>#1A73E8&lt;/color>" errorLine1=" &lt;color name=&quot;homepage_generic_icon_background&quot;>#1A73E8&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="128"
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;battery_good_color_light&quot;>#43a047&lt;/color> &lt;!-- Material Green 600 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/colors.xml" file="res/values/colors.xml"
line="133" line="133"
@@ -1257,11 +1257,75 @@
priority="4" priority="4"
summary="Using hardcoded color" 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." 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/condition_card_background&quot;" errorLine1=" &lt;color name=&quot;battery_maybe_color_light&quot;>#ef6c00&lt;/color> &lt;!-- Material Orange 800 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="134"
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;battery_bad_color_light&quot;>#f44336&lt;/color> &lt;!-- Material Red 500 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/layout/condition_tile.xml" file="res/values/colors.xml"
line="22" line="135"
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;battery_good_color_dark&quot;>#4caf50&lt;/color> &lt;!-- Material Green 500 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="136"
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;battery_maybe_color_dark&quot;>#fdd835&lt;/color> &lt;!-- Material Yellow 600 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="137"
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;battery_bad_color_dark&quot;>#f44336&lt;/color> &lt;!-- Material Red 500 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="138"
column="5"/> column="5"/>
</issue> </issue>
@@ -2173,7 +2237,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/layout/running_processes_header.xml" file="res/layout/running_processes_header.xml"
line="55" line="56"
column="13"/> column="13"/>
</issue> </issue>
@@ -2189,7 +2253,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/layout/running_processes_header.xml" file="res/layout/running_processes_header.xml"
line="145" line="146"
column="13"/> column="13"/>
</issue> </issue>
@@ -2337,22 +2401,6 @@
column="17"/> column="17"/>
</issue> </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/search_panel.xml"
line="28"
column="9"/>
</issue>
<issue <issue
id="HardCodedColor" id="HardCodedColor"
severity="Error" severity="Error"
@@ -2417,6 +2465,22 @@
column="9"/> column="9"/>
</issue> </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;string name=&quot;sync_plug&quot; msgid=&quot;3905078969081888738&quot;>&quot;&quot;&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;Welcome to Google sync!&quot;&lt;/font>&quot; \nA Google approach to syncing data to allow access to your contacts, appointments, and more from wherever you are.&quot;&lt;/string>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rXC/strings.xml"
line="2535"
column="168"/>
</issue>
<issue <issue
id="HardCodedColor" id="HardCodedColor"
severity="Error" severity="Error"
@@ -2429,7 +2493,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values-en-rAU/strings.xml" file="res/values-en-rAU/strings.xml"
line="2395" line="2536"
column="64"/> column="64"/>
</issue> </issue>
@@ -2445,7 +2509,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values-en-rCA/strings.xml" file="res/values-en-rCA/strings.xml"
line="2395" line="2536"
column="64"/> column="64"/>
</issue> </issue>
@@ -2461,7 +2525,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values-en-rGB/strings.xml" file="res/values-en-rGB/strings.xml"
line="2395" line="2536"
column="64"/> column="64"/>
</issue> </issue>
@@ -2477,26 +2541,10 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values-en-rIN/strings.xml" file="res/values-en-rIN/strings.xml"
line="2395" line="2536"
column="64"/> column="64"/>
</issue> </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;string name=&quot;sync_plug&quot; msgid=&quot;3905078969081888738&quot;>&quot;&quot;&lt;font fgcolor=&quot;#ffffffff&quot;>&quot;Welcome to Google sync!&quot;&lt;/font>&quot; \nA Google approach to syncing data to allow access to your contacts, appointments, and more from wherever you are.&quot;&lt;/string>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rXC/strings.xml"
line="2396"
column="168"/>
</issue>
<issue <issue
id="HardCodedColor" id="HardCodedColor"
severity="Error" severity="Error"
@@ -2509,7 +2557,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~"> errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location <location
file="res/values/strings.xml" file="res/values/strings.xml"
line="5638" line="5899"
column="36"/> column="36"/>
</issue> </issue>
@@ -2541,7 +2589,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/styles.xml" file="res/values/styles.xml"
line="442" line="436"
column="44"/> column="44"/>
</issue> </issue>
@@ -2557,7 +2605,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/styles.xml" file="res/values/styles.xml"
line="448" line="442"
column="44"/> column="44"/>
</issue> </issue>
@@ -2573,7 +2621,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/styles.xml" file="res/values/styles.xml"
line="449" line="443"
column="44"/> column="44"/>
</issue> </issue>
@@ -2589,7 +2637,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/styles.xml" file="res/values/styles.xml"
line="472" line="461"
column="41"/> column="41"/>
</issue> </issue>
@@ -2605,7 +2653,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="33" line="31"
column="40"/> column="40"/>
</issue> </issue>
@@ -2621,7 +2669,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="52" line="49"
column="40"/> column="40"/>
</issue> </issue>
@@ -2637,7 +2685,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="70" line="67"
column="40"/> column="40"/>
</issue> </issue>
@@ -2653,7 +2701,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="89" line="85"
column="40"/> column="40"/>
</issue> </issue>
@@ -2669,7 +2717,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="107" line="103"
column="40"/> column="40"/>
</issue> </issue>
@@ -2685,7 +2733,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="126" line="121"
column="40"/> column="40"/>
</issue> </issue>
@@ -2701,7 +2749,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="200" line="197"
column="43"/> column="43"/>
</issue> </issue>
@@ -2717,7 +2765,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="201" line="198"
column="42"/> column="42"/>
</issue> </issue>
@@ -2733,10 +2781,58 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="202" line="199"
column="45"/> column="45"/>
</issue> </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;batteryGoodColor&quot;>@color/battery_good_color_light&lt;/item>"
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="240"
column="39"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item name=&quot;batteryMaybeColor&quot;>@color/battery_maybe_color_light&lt;/item>"
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="241"
column="40"/>
</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;batteryBadColor&quot;>@color/battery_bad_color_light&lt;/item>"
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="242"
column="38"/>
</issue>
<issue <issue
id="HardCodedColor" id="HardCodedColor"
severity="Error" severity="Error"
@@ -2749,7 +2845,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="279" line="280"
column="47"/> column="47"/>
</issue> </issue>
@@ -2765,7 +2861,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="347" line="348"
column="45"/> column="45"/>
</issue> </issue>
@@ -2781,7 +2877,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="348" line="349"
column="49"/> column="49"/>
</issue> </issue>
@@ -2797,7 +2893,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="356" line="357"
column="45"/> column="45"/>
</issue> </issue>
@@ -2813,7 +2909,7 @@
errorLine2=" ^"> errorLine2=" ^">
<location <location
file="res/values/themes.xml" file="res/values/themes.xml"
line="357" line="358"
column="49"/> column="49"/>
</issue> </issue>

View File

@@ -18,9 +18,6 @@
--> -->
<resources> <resources>
<item type="id" name="preference_highlighted" /> <item type="id" name="preference_highlighted" />
<item type="id" name="job_anomaly_clean_up" />
<item type="id" name="job_anomaly_config_update"/>
<item type="id" name="job_anomaly_detection" />
<item type="id" name="lock_none" /> <item type="id" name="lock_none" />
<item type="id" name="lock_pin" /> <item type="id" name="lock_pin" />

22
res/values/integers.xml Normal file
View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Reserve all the job ids in settings -->
<integer name="job_anomaly_clean_up">100</integer>
<integer name="job_anomaly_config_update">101</integer>
<integer name="job_anomaly_detection">102</integer>
</resources>

View File

@@ -5711,9 +5711,6 @@
<string name="admin_disabled_other_options">Other options are disabled by your admin</string> <string name="admin_disabled_other_options">Other options are disabled by your admin</string>
<string name="admin_more_details">More details</string> <string name="admin_more_details">More details</string>
<!-- Name to assign to a Network Access Point that was saved without a name -->
<string name="untitled_apn">Untitled</string>
<string name="sound_category_sound_title">General</string> <string name="sound_category_sound_title">General</string>
<string name="notification_log_title">Notification log</string> <string name="notification_log_title">Notification log</string>

View File

@@ -14,14 +14,17 @@
limitations under the License. limitations under the License.
--> -->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="magnification_preference_screen_title" android:key="magnification_preference_screen_title"
android:title="@string/accessibility_screen_magnification_title"> android:title="@string/accessibility_screen_magnification_title">
<Preference <Preference
android:fragment="com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment" android:fragment="com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment"
android:key="screen_magnification_gestures_preference_screen" android:key="screen_magnification_gestures_preference_screen"
android:title="@string/accessibility_screen_magnification_gestures_title"/> android:title="@string/accessibility_screen_magnification_gestures_title"
settings:controller="com.android.settings.accessibility.MagnificationGesturesPreferenceController"/>
<Preference <Preference
android:fragment="com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment" android:fragment="com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment"
android:key="screen_magnification_navbar_preference_screen" android:key="screen_magnification_navbar_preference_screen"
android:title="@string/accessibility_screen_magnification_navbar_title"/> android:title="@string/accessibility_screen_magnification_navbar_title"
settings:controller="com.android.settings.accessibility.MagnificationNavbarPreferenceController"/>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -18,7 +18,8 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto" xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="network_and_internet_screen" android:key="network_and_internet_screen"
android:title="@string/network_dashboard_title"> android:title="@string/network_dashboard_title"
settings:initialExpandedChildrenCount="5">
<com.android.settings.widget.MasterSwitchPreference <com.android.settings.widget.MasterSwitchPreference
android:fragment="com.android.settings.wifi.WifiSettings" android:fragment="com.android.settings.wifi.WifiSettings"
@@ -58,20 +59,11 @@
settings:userRestriction="no_config_tethering" settings:userRestriction="no_config_tethering"
settings:useAdminDisabledSummary="true" /> settings:useAdminDisabledSummary="true" />
<com.android.settingslib.RestrictedPreference
android:fragment="com.android.settings.vpn2.VpnSettings"
android:key="vpn_settings"
android:title="@string/vpn_settings_title"
android:icon="@drawable/ic_vpn_key"
android:order="0"
android:summary="@string/summary_placeholder"
settings:userRestriction="no_config_vpn"
settings:useAdminDisabledSummary="true" />
<com.android.settingslib.RestrictedPreference <com.android.settingslib.RestrictedPreference
android:key="manage_mobile_plan" android:key="manage_mobile_plan"
android:title="@string/manage_mobile_plan_title" android:title="@string/manage_mobile_plan_title"
android:persistent="false" android:persistent="false"
android:order="0"
settings:userRestriction="no_config_mobile_networks" settings:userRestriction="no_config_mobile_networks"
settings:useAdminDisabledSummary="true" /> settings:useAdminDisabledSummary="true" />
@@ -88,4 +80,22 @@
android:key="proxy_settings" android:key="proxy_settings"
android:title="@string/proxy_settings_title" /> android:title="@string/proxy_settings_title" />
</PreferenceScreen> <com.android.settingslib.RestrictedPreference
android:fragment="com.android.settings.vpn2.VpnSettings"
android:key="vpn_settings"
android:title="@string/vpn_settings_title"
android:icon="@drawable/ic_vpn_key"
android:order="10"
android:summary="@string/summary_placeholder"
settings:userRestriction="no_config_vpn"
settings:useAdminDisabledSummary="true" />
<com.android.settings.network.PrivateDnsModeDialogPreference
android:key="private_dns_settings"
android:title="@string/select_private_dns_configuration_title"
android:order="15"
android:dialogTitle="@string/select_private_dns_configuration_dialog_title"
android:dialogLayout="@layout/private_dns_mode_dialog"
android:positiveButtonText="@string/save" />
</PreferenceScreen>

View File

@@ -18,11 +18,9 @@ package com.android.settings;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.ContentUris;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@@ -52,17 +50,17 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
import com.android.settingslib.utils.ThreadUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static android.app.Activity.RESULT_OK;
import static android.content.Context.TELEPHONY_SERVICE; import static android.content.Context.TELEPHONY_SERVICE;
/** /**
* TODO: After loading all changes, please move this to network package. * TODO(b/77339683): After loading all changes, please move this to network package.
*/ */
public class ApnEditor extends SettingsPreferenceFragment public class ApnEditor extends SettingsPreferenceFragment
implements OnPreferenceChangeListener, OnKeyListener { implements OnPreferenceChangeListener, OnKeyListener {
@@ -70,7 +68,6 @@ public class ApnEditor extends SettingsPreferenceFragment
private final static String TAG = ApnEditor.class.getSimpleName(); private final static String TAG = ApnEditor.class.getSimpleName();
private final static boolean VDBG = false; // STOPSHIP if true private final static boolean VDBG = false; // STOPSHIP if true
private final static String SAVED_POS = "pos";
private final static String KEY_AUTH_TYPE = "auth_type"; private final static String KEY_AUTH_TYPE = "auth_type";
private final static String KEY_PROTOCOL = "apn_protocol"; private final static String KEY_PROTOCOL = "apn_protocol";
private final static String KEY_ROAMING_PROTOCOL = "apn_roaming_protocol"; private final static String KEY_ROAMING_PROTOCOL = "apn_roaming_protocol";
@@ -83,37 +80,57 @@ public class ApnEditor extends SettingsPreferenceFragment
private static final int MENU_SAVE = Menu.FIRST + 1; private static final int MENU_SAVE = Menu.FIRST + 1;
private static final int MENU_CANCEL = Menu.FIRST + 2; private static final int MENU_CANCEL = Menu.FIRST + 2;
private static String sNotSet; @VisibleForTesting
private EditTextPreference mName; static String sNotSet;
private EditTextPreference mApn; @VisibleForTesting
private EditTextPreference mProxy; EditTextPreference mName;
private EditTextPreference mPort; @VisibleForTesting
private EditTextPreference mUser; EditTextPreference mApn;
private EditTextPreference mServer; @VisibleForTesting
private EditTextPreference mPassword; EditTextPreference mProxy;
private EditTextPreference mMmsc; @VisibleForTesting
private EditTextPreference mMcc; EditTextPreference mPort;
private EditTextPreference mMnc; @VisibleForTesting
private EditTextPreference mMmsProxy; EditTextPreference mUser;
private EditTextPreference mMmsPort; @VisibleForTesting
private ListPreference mAuthType; EditTextPreference mServer;
private EditTextPreference mApnType; @VisibleForTesting
private ListPreference mProtocol; EditTextPreference mPassword;
private ListPreference mRoamingProtocol; @VisibleForTesting
private SwitchPreference mCarrierEnabled; EditTextPreference mMmsc;
private MultiSelectListPreference mBearerMulti; @VisibleForTesting
private ListPreference mMvnoType; EditTextPreference mMcc;
private EditTextPreference mMvnoMatchData; @VisibleForTesting
EditTextPreference mMnc;
@VisibleForTesting
EditTextPreference mMmsProxy;
@VisibleForTesting
EditTextPreference mMmsPort;
@VisibleForTesting
ListPreference mAuthType;
@VisibleForTesting
EditTextPreference mApnType;
@VisibleForTesting
ListPreference mProtocol;
@VisibleForTesting
ListPreference mRoamingProtocol;
@VisibleForTesting
SwitchPreference mCarrierEnabled;
@VisibleForTesting
MultiSelectListPreference mBearerMulti;
@VisibleForTesting
ListPreference mMvnoType;
@VisibleForTesting
EditTextPreference mMvnoMatchData;
@VisibleForTesting
ApnData mApnData;
private String mCurMnc; private String mCurMnc;
private String mCurMcc; private String mCurMcc;
private Uri mUri;
private Cursor mCursor;
private boolean mNewApn; private boolean mNewApn;
private boolean mFirstTime;
private int mSubId; private int mSubId;
private Resources mRes;
private TelephonyManager mTelephonyManager; private TelephonyManager mTelephonyManager;
private int mBearerInitialVal = 0; private int mBearerInitialVal = 0;
private String mMvnoTypeStr; private String mMvnoTypeStr;
@@ -121,6 +138,7 @@ public class ApnEditor extends SettingsPreferenceFragment
private String[] mReadOnlyApnTypes; private String[] mReadOnlyApnTypes;
private String[] mReadOnlyApnFields; private String[] mReadOnlyApnFields;
private boolean mReadOnlyApn; private boolean mReadOnlyApn;
private Uri mCarrierUri;
/** /**
* Standard projection for the interesting columns of a normal note. * Standard projection for the interesting columns of a normal note.
@@ -154,22 +172,27 @@ public class ApnEditor extends SettingsPreferenceFragment
}; };
private static final int ID_INDEX = 0; private static final int ID_INDEX = 0;
private static final int NAME_INDEX = 1; @VisibleForTesting
private static final int APN_INDEX = 2; static final int NAME_INDEX = 1;
@VisibleForTesting
static final int APN_INDEX = 2;
private static final int PROXY_INDEX = 3; private static final int PROXY_INDEX = 3;
private static final int PORT_INDEX = 4; private static final int PORT_INDEX = 4;
private static final int USER_INDEX = 5; private static final int USER_INDEX = 5;
private static final int SERVER_INDEX = 6; private static final int SERVER_INDEX = 6;
private static final int PASSWORD_INDEX = 7; private static final int PASSWORD_INDEX = 7;
private static final int MMSC_INDEX = 8; private static final int MMSC_INDEX = 8;
private static final int MCC_INDEX = 9; @VisibleForTesting
private static final int MNC_INDEX = 10; static final int MCC_INDEX = 9;
@VisibleForTesting
static final int MNC_INDEX = 10;
private static final int MMSPROXY_INDEX = 12; private static final int MMSPROXY_INDEX = 12;
private static final int MMSPORT_INDEX = 13; private static final int MMSPORT_INDEX = 13;
private static final int AUTH_TYPE_INDEX = 14; private static final int AUTH_TYPE_INDEX = 14;
private static final int TYPE_INDEX = 15; private static final int TYPE_INDEX = 15;
private static final int PROTOCOL_INDEX = 16; private static final int PROTOCOL_INDEX = 16;
private static final int CARRIER_ENABLED_INDEX = 17; @VisibleForTesting
static final int CARRIER_ENABLED_INDEX = 17;
private static final int BEARER_INDEX = 18; private static final int BEARER_INDEX = 18;
private static final int BEARER_BITMASK_INDEX = 19; private static final int BEARER_BITMASK_INDEX = 19;
private static final int ROAMING_PROTOCOL_INDEX = 20; private static final int ROAMING_PROTOCOL_INDEX = 20;
@@ -178,7 +201,6 @@ public class ApnEditor extends SettingsPreferenceFragment
private static final int EDITED_INDEX = 23; private static final int EDITED_INDEX = 23;
private static final int USER_EDITABLE_INDEX = 24; private static final int USER_EDITABLE_INDEX = 24;
@Override @Override
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
@@ -207,14 +229,11 @@ public class ApnEditor extends SettingsPreferenceFragment
mMvnoType = (ListPreference) findPreference(KEY_MVNO_TYPE); mMvnoType = (ListPreference) findPreference(KEY_MVNO_TYPE);
mMvnoMatchData = (EditTextPreference) findPreference("mvno_match_data"); mMvnoMatchData = (EditTextPreference) findPreference("mvno_match_data");
mRes = getResources();
final Intent intent = getIntent(); final Intent intent = getIntent();
final String action = intent.getAction(); final String action = intent.getAction();
mSubId = intent.getIntExtra(ApnSettings.SUB_ID, mSubId = intent.getIntExtra(ApnSettings.SUB_ID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID); SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mFirstTime = icicle == null;
mReadOnlyApn = false; mReadOnlyApn = false;
mReadOnlyApnTypes = null; mReadOnlyApnTypes = null;
mReadOnlyApnFields = null; mReadOnlyApnFields = null;
@@ -236,61 +255,47 @@ public class ApnEditor extends SettingsPreferenceFragment
} }
} }
Uri uri = null;
if (action.equals(Intent.ACTION_EDIT)) { if (action.equals(Intent.ACTION_EDIT)) {
Uri uri = intent.getData(); uri = intent.getData();
if (!uri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) { if (!uri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
Log.e(TAG, "Edit request not for carrier table. Uri: " + uri); Log.e(TAG, "Edit request not for carrier table. Uri: " + uri);
finish(); finish();
return; return;
} }
mUri = uri;
} else if (action.equals(Intent.ACTION_INSERT)) { } else if (action.equals(Intent.ACTION_INSERT)) {
if (mFirstTime || icicle.getInt(SAVED_POS) == 0) { mCarrierUri = intent.getData();
Uri uri = intent.getData(); if (!mCarrierUri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
if (!uri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) { Log.e(TAG, "Insert request not for carrier table. Uri: " + mCarrierUri);
Log.e(TAG, "Insert request not for carrier table. Uri: " + uri); finish();
finish(); return;
return;
}
ContentValues contentValues = new ContentValues();
contentValues.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED);
mUri = getContentResolver().insert(uri, contentValues);
} else {
mUri = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI,
icicle.getInt(SAVED_POS));
} }
mNewApn = true; mNewApn = true;
mMvnoTypeStr = intent.getStringExtra(ApnSettings.MVNO_TYPE); mMvnoTypeStr = intent.getStringExtra(ApnSettings.MVNO_TYPE);
mMvnoMatchDataStr = intent.getStringExtra(ApnSettings.MVNO_MATCH_DATA); mMvnoMatchDataStr = intent.getStringExtra(ApnSettings.MVNO_MATCH_DATA);
// If we were unable to create a new note, then just finish
// this activity. A RESULT_CANCELED will be sent back to the
// original activity if they requested a result.
if (mUri == null) {
Log.w(TAG, "Failed to insert new telephony provider into "
+ getIntent().getData());
finish();
return;
}
// The new entry was created, so assume all will end well and
// set the result to be returned.
setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
} else { } else {
finish(); finish();
return; return;
} }
mCursor = getActivity().managedQuery(mUri, sProjection, null, null); // Creates an ApnData to store the apn data temporary, so that we don't need the cursor to
mCursor.moveToFirst(); // get the apn data. The uri is null if the action is ACTION_INSERT, that mean there is no
// record in the database, so create a empty ApnData to represent a empty row of database.
if (uri != null) {
mApnData = getApnDataFromUri(uri);
} else {
mApnData = new ApnData(sProjection.length);
}
mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
Log.d(TAG, "onCreate: EDITED " + mCursor.getInt(EDITED_INDEX)); boolean isUserEdited = mApnData.getInteger(EDITED_INDEX, Telephony.Carriers.USER_EDITED)
== Telephony.Carriers.USER_EDITED;
Log.d(TAG, "onCreate: EDITED " + isUserEdited);
// if it's not a USER_EDITED apn, check if it's read-only // if it's not a USER_EDITED apn, check if it's read-only
if (mCursor.getInt(EDITED_INDEX) != Telephony.Carriers.USER_EDITED && if (!isUserEdited && (mApnData.getInteger(USER_EDITABLE_INDEX, 1) == 0
(mCursor.getInt(USER_EDITABLE_INDEX) == 0 || || apnTypesMatch(mReadOnlyApnTypes, mApnData.getString(TYPE_INDEX)))) {
apnTypesMatch(mReadOnlyApnTypes, mCursor.getString(TYPE_INDEX)))) {
Log.d(TAG, "onCreate: apnTypesMatch; read-only APN"); Log.d(TAG, "onCreate: apnTypesMatch; read-only APN");
mReadOnlyApn = true; mReadOnlyApn = true;
disableAllFields(); disableAllFields();
@@ -302,12 +307,7 @@ public class ApnEditor extends SettingsPreferenceFragment
getPreferenceScreen().getPreference(i).setOnPreferenceChangeListener(this); getPreferenceScreen().getPreference(i).setOnPreferenceChangeListener(this);
} }
} fillUI(icicle == null);
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
fillUi();
} }
/** /**
@@ -462,50 +462,23 @@ public class ApnEditor extends SettingsPreferenceFragment
return MetricsEvent.APN_EDITOR; return MetricsEvent.APN_EDITOR;
} }
@Override @VisibleForTesting
public void onResume() { void fillUI(boolean firstTime) {
super.onResume(); if (firstTime) {
if (mUri == null && mNewApn) {
// The URI could have been deleted when activity is paused,
// therefore, it needs to be restored.
ContentValues contentValues = new ContentValues();
contentValues.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED);
mUri = getContentResolver().insert(getIntent().getData(), contentValues);
if (mUri == null) {
Log.w(TAG, "Failed to insert new telephony provider into "
+ getIntent().getData());
finish();
return;
}
mCursor = getActivity().managedQuery(mUri, sProjection, null, null);
mCursor.moveToFirst();
}
}
@Override
public void onPause() {
super.onPause();
}
private void fillUi() {
if (mFirstTime) {
mFirstTime = false;
// Fill in all the values from the db in both text editor and summary // Fill in all the values from the db in both text editor and summary
mName.setText(mCursor.getString(NAME_INDEX)); mName.setText(mApnData.getString(NAME_INDEX));
mApn.setText(mCursor.getString(APN_INDEX)); mApn.setText(mApnData.getString(APN_INDEX));
mProxy.setText(mCursor.getString(PROXY_INDEX)); mProxy.setText(mApnData.getString(PROXY_INDEX));
mPort.setText(mCursor.getString(PORT_INDEX)); mPort.setText(mApnData.getString(PORT_INDEX));
mUser.setText(mCursor.getString(USER_INDEX)); mUser.setText(mApnData.getString(USER_INDEX));
mServer.setText(mCursor.getString(SERVER_INDEX)); mServer.setText(mApnData.getString(SERVER_INDEX));
mPassword.setText(mCursor.getString(PASSWORD_INDEX)); mPassword.setText(mApnData.getString(PASSWORD_INDEX));
mMmsProxy.setText(mCursor.getString(MMSPROXY_INDEX)); mMmsProxy.setText(mApnData.getString(MMSPROXY_INDEX));
mMmsPort.setText(mCursor.getString(MMSPORT_INDEX)); mMmsPort.setText(mApnData.getString(MMSPORT_INDEX));
mMmsc.setText(mCursor.getString(MMSC_INDEX)); mMmsc.setText(mApnData.getString(MMSC_INDEX));
mMcc.setText(mCursor.getString(MCC_INDEX)); mMcc.setText(mApnData.getString(MCC_INDEX));
mMnc.setText(mCursor.getString(MNC_INDEX)); mMnc.setText(mApnData.getString(MNC_INDEX));
mApnType.setText(mCursor.getString(TYPE_INDEX)); mApnType.setText(mApnData.getString(TYPE_INDEX));
if (mNewApn) { if (mNewApn) {
String numeric = mTelephonyManager.getSimOperator(mSubId); String numeric = mTelephonyManager.getSimOperator(mSubId);
// MCC is first 3 chars and then in 2 - 3 chars of MNC // MCC is first 3 chars and then in 2 - 3 chars of MNC
@@ -521,20 +494,20 @@ public class ApnEditor extends SettingsPreferenceFragment
mCurMcc = mcc; mCurMcc = mcc;
} }
} }
int authVal = mCursor.getInt(AUTH_TYPE_INDEX); int authVal = mApnData.getInteger(AUTH_TYPE_INDEX, -1);
if (authVal != -1) { if (authVal != -1) {
mAuthType.setValueIndex(authVal); mAuthType.setValueIndex(authVal);
} else { } else {
mAuthType.setValue(null); mAuthType.setValue(null);
} }
mProtocol.setValue(mCursor.getString(PROTOCOL_INDEX)); mProtocol.setValue(mApnData.getString(PROTOCOL_INDEX));
mRoamingProtocol.setValue(mCursor.getString(ROAMING_PROTOCOL_INDEX)); mRoamingProtocol.setValue(mApnData.getString(ROAMING_PROTOCOL_INDEX));
mCarrierEnabled.setChecked(mCursor.getInt(CARRIER_ENABLED_INDEX)==1); mCarrierEnabled.setChecked(mApnData.getInteger(CARRIER_ENABLED_INDEX, 1) == 1);
mBearerInitialVal = mCursor.getInt(BEARER_INDEX); mBearerInitialVal = mApnData.getInteger(BEARER_INDEX, 0);
HashSet<String> bearers = new HashSet<String>(); HashSet<String> bearers = new HashSet<String>();
int bearerBitmask = mCursor.getInt(BEARER_BITMASK_INDEX); int bearerBitmask = mApnData.getInteger(BEARER_BITMASK_INDEX, 0);
if (bearerBitmask == 0) { if (bearerBitmask == 0) {
if (mBearerInitialVal == 0) { if (mBearerInitialVal == 0) {
bearers.add("" + 0); bearers.add("" + 0);
@@ -556,9 +529,9 @@ public class ApnEditor extends SettingsPreferenceFragment
} }
mBearerMulti.setValues(bearers); mBearerMulti.setValues(bearers);
mMvnoType.setValue(mCursor.getString(MVNO_TYPE_INDEX)); mMvnoType.setValue(mApnData.getString(MVNO_TYPE_INDEX));
mMvnoMatchData.setEnabled(false); mMvnoMatchData.setEnabled(false);
mMvnoMatchData.setText(mCursor.getString(MVNO_MATCH_DATA_INDEX)); mMvnoMatchData.setText(mApnData.getString(MVNO_MATCH_DATA_INDEX));
if (mNewApn && mMvnoTypeStr != null && mMvnoMatchDataStr != null) { if (mNewApn && mMvnoTypeStr != null && mMvnoMatchDataStr != null) {
mMvnoType.setValue(mMvnoTypeStr); mMvnoType.setValue(mMvnoTypeStr);
mMvnoMatchData.setText(mMvnoMatchDataStr); mMvnoMatchData.setText(mMvnoMatchDataStr);
@@ -584,7 +557,7 @@ public class ApnEditor extends SettingsPreferenceFragment
int authValIndex = Integer.parseInt(authVal); int authValIndex = Integer.parseInt(authVal);
mAuthType.setValueIndex(authValIndex); mAuthType.setValueIndex(authValIndex);
String []values = mRes.getStringArray(R.array.apn_auth_entries); String[] values = getResources().getStringArray(R.array.apn_auth_entries);
mAuthType.setSummary(values[authValIndex]); mAuthType.setSummary(values[authValIndex]);
} else { } else {
mAuthType.setSummary(sNotSet); mAuthType.setSummary(sNotSet);
@@ -617,7 +590,7 @@ public class ApnEditor extends SettingsPreferenceFragment
if (protocolIndex == -1) { if (protocolIndex == -1) {
return null; return null;
} else { } else {
String[] values = mRes.getStringArray(R.array.apn_protocol_entries); String[] values = getResources().getStringArray(R.array.apn_protocol_entries);
try { try {
return values[protocolIndex]; return values[protocolIndex];
} catch (ArrayIndexOutOfBoundsException e) { } catch (ArrayIndexOutOfBoundsException e) {
@@ -631,7 +604,7 @@ public class ApnEditor extends SettingsPreferenceFragment
if (mBearerIndex == -1) { if (mBearerIndex == -1) {
return null; return null;
} else { } else {
String[] values = mRes.getStringArray(R.array.bearer_entries); String[] values = getResources().getStringArray(R.array.bearer_entries);
try { try {
return values[mBearerIndex]; return values[mBearerIndex];
} catch (ArrayIndexOutOfBoundsException e) { } catch (ArrayIndexOutOfBoundsException e) {
@@ -641,7 +614,7 @@ public class ApnEditor extends SettingsPreferenceFragment
} }
private String bearerMultiDescription(Set<String> raw) { private String bearerMultiDescription(Set<String> raw) {
String[] values = mRes.getStringArray(R.array.bearer_entries); String[] values = getResources().getStringArray(R.array.bearer_entries);
StringBuilder retVal = new StringBuilder(); StringBuilder retVal = new StringBuilder();
boolean first = true; boolean first = true;
for (String bearer : raw) { for (String bearer : raw) {
@@ -671,7 +644,7 @@ public class ApnEditor extends SettingsPreferenceFragment
if (mvnoIndex == -1) { if (mvnoIndex == -1) {
return null; return null;
} else { } else {
String[] values = mRes.getStringArray(R.array.mvno_type_entries); String[] values = getResources().getStringArray(R.array.mvno_type_entries);
boolean mvnoMatchDataUneditable = boolean mvnoMatchDataUneditable =
mReadOnlyApn || (mReadOnlyApnFields != null mReadOnlyApn || (mReadOnlyApnFields != null
&& Arrays.asList(mReadOnlyApnFields) && Arrays.asList(mReadOnlyApnFields)
@@ -703,7 +676,7 @@ public class ApnEditor extends SettingsPreferenceFragment
int index = Integer.parseInt((String) newValue); int index = Integer.parseInt((String) newValue);
mAuthType.setValueIndex(index); mAuthType.setValueIndex(index);
String[] values = mRes.getStringArray(R.array.apn_auth_entries); String[] values = getResources().getStringArray(R.array.apn_auth_entries);
mAuthType.setSummary(values[index]); mAuthType.setSummary(values[index]);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
return false; return false;
@@ -764,22 +737,21 @@ public class ApnEditor extends SettingsPreferenceFragment
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case MENU_DELETE: case MENU_DELETE:
deleteApn(); deleteApn();
return true;
case MENU_SAVE:
if (validateAndSave(false)) {
finish(); finish();
} return true;
return true; case MENU_SAVE:
case MENU_CANCEL: if (validateAndSaveApnData()) {
if (mNewApn) { finish();
getContentResolver().delete(mUri, null, null); }
} return true;
finish(); case MENU_CANCEL:
return true; finish();
return true;
default:
return super.onOptionsItemSelected(item);
} }
return super.onOptionsItemSelected(item);
} }
@Override @Override
@@ -790,11 +762,20 @@ public class ApnEditor extends SettingsPreferenceFragment
view.requestFocus(); view.requestFocus();
} }
/**
* Try to save the apn data when pressed the back button. An error message will be displayed if
* the apn data is invalid.
*
* TODO(b/77339593): Try to keep the same behavior between back button and up navigate button.
* We will save the valid apn data to the database when pressed the back button, but discard all
* user changed when pressed the up navigate button.
*/
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) { public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() != KeyEvent.ACTION_DOWN) return false; if (event.getAction() != KeyEvent.ACTION_DOWN) return false;
switch (keyCode) { switch (keyCode) {
case KeyEvent.KEYCODE_BACK: { case KeyEvent.KEYCODE_BACK: {
if (validateAndSave(false)) { if (validateAndSaveApnData()) {
finish(); finish();
} }
return true; return true;
@@ -803,62 +784,70 @@ public class ApnEditor extends SettingsPreferenceFragment
return false; return false;
} }
@Override
public void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
if (validateAndSave(true)) {
icicle.putInt(SAVED_POS, mCursor.getInt(ID_INDEX));
}
}
/** /**
* Add key, value to cv and compare the value against the value at index in mCursor. Return true * Add key, value to {@code cv} and compare the value against the value at index in
* if values are different. assumeDiff indicates if values can be assumed different in which * {@link #mApnData}.
* case no comparison is needed. *
* @return true if value is different from the value at index in mCursor * <p>
* The key, value will not add to {@code cv} if value is null.
*
* @return true if values are different. {@code assumeDiff} indicates if values can be assumed
* different in which case no comparison is needed.
*/ */
boolean setStringValueAndCheckIfDiff(ContentValues cv, String key, String value, boolean setStringValueAndCheckIfDiff(
boolean assumeDiff, int index) { ContentValues cv, String key, String value, boolean assumeDiff, int index) {
cv.put(key, value); String valueFromLocalCache = mApnData.getString(index);
String valueFromCursor = mCursor.getString(index);
if (VDBG) { if (VDBG) {
Log.d(TAG, "setStringValueAndCheckIfDiff: assumeDiff: " + assumeDiff Log.d(TAG, "setStringValueAndCheckIfDiff: assumeDiff: " + assumeDiff
+ " key: " + key + " key: " + key
+ " value: '" + value + " value: '" + value
+ "' valueFromCursor: '" + valueFromCursor + "'"); + "' valueFromDb: '" + valueFromLocalCache + "'");
} }
return assumeDiff boolean isDiff = assumeDiff
|| !((TextUtils.isEmpty(value) && TextUtils.isEmpty(valueFromCursor)) || !((TextUtils.isEmpty(value) && TextUtils.isEmpty(valueFromLocalCache))
|| (value != null && value.equals(valueFromCursor))); || (value != null && value.equals(valueFromLocalCache)));
if (isDiff && value != null) {
cv.put(key, value);
}
return isDiff;
} }
/** /**
* Add key, value to cv and compare the value against the value at index in mCursor. Return true * Add key, value to {@code cv} and compare the value against the value at index in
* if values are different. assumeDiff indicates if values can be assumed different in which * {@link #mApnData}.
* case no comparison is needed. *
* @return true if value is different from the value at index in mCursor * @return true if values are different. {@code assumeDiff} indicates if values can be assumed
* different in which case no comparison is needed.
*/ */
boolean setIntValueAndCheckIfDiff(ContentValues cv, String key, int value, boolean setIntValueAndCheckIfDiff(
boolean assumeDiff, int index) { ContentValues cv, String key, int value, boolean assumeDiff, int index) {
cv.put(key, value); Integer valueFromLocalCache = mApnData.getInteger(index);
int valueFromCursor = mCursor.getInt(index);
if (VDBG) { if (VDBG) {
Log.d(TAG, "setIntValueAndCheckIfDiff: assumeDiff: " + assumeDiff Log.d(TAG, "setIntValueAndCheckIfDiff: assumeDiff: " + assumeDiff
+ " key: " + key + " key: " + key
+ " value: '" + value + " value: '" + value
+ "' valueFromCursor: '" + valueFromCursor + "'"); + "' valueFromDb: '" + valueFromLocalCache + "'");
} }
return assumeDiff || value != valueFromCursor;
boolean isDiff = assumeDiff || value != valueFromLocalCache;
if (isDiff) {
cv.put(key, value);
}
return isDiff;
} }
/** /**
* Check the key fields' validity and save if valid. * Validates the apn data and save it to the database if it's valid.
* @param force save even if the fields are not valid, if the app is *
* being suspended * <p>
* @return true if there's no error * A dialog with error message will be displayed if the APN data is invalid.
*
* @return true if there is no error
*/ */
private boolean validateAndSave(boolean force) { @VisibleForTesting
// nothing to do if it's a read only APN boolean validateAndSaveApnData() {
// Nothing to do if it's a read only APN
if (mReadOnlyApn) { if (mReadOnlyApn) {
return true; return true;
} }
@@ -868,21 +857,9 @@ public class ApnEditor extends SettingsPreferenceFragment
String mcc = checkNotSet(mMcc.getText()); String mcc = checkNotSet(mMcc.getText());
String mnc = checkNotSet(mMnc.getText()); String mnc = checkNotSet(mMnc.getText());
if (getErrorMsg() != null && !force) { String errorMsg = validateApnData();
ErrorDialog.showError(this); if (errorMsg != null) {
return false; showError();
}
if (!mCursor.moveToFirst()) {
Log.w(TAG,
"Could not go to the first row in the Cursor when saving data.");
return false;
}
// If it's a new APN and a name or apn haven't been entered, then erase the entry
if (force && mNewApn && name.length() < 1 && apn.length() < 1) {
getContentResolver().delete(mUri, null, null);
mUri = null;
return false; return false;
} }
@@ -890,12 +867,9 @@ public class ApnEditor extends SettingsPreferenceFragment
// call update() if it's a new APN. If not, check if any field differs from the db value; // call update() if it's a new APN. If not, check if any field differs from the db value;
// if any diff is found update() should be called // if any diff is found update() should be called
boolean callUpdate = mNewApn; boolean callUpdate = mNewApn;
// Add a dummy name "Untitled", if the user exits the screen without adding a name but
// entered other information worth keeping.
callUpdate = setStringValueAndCheckIfDiff(values, callUpdate = setStringValueAndCheckIfDiff(values,
Telephony.Carriers.NAME, Telephony.Carriers.NAME,
name.length() < 1 ? getResources().getString(R.string.untitled_apn) : name, name,
callUpdate, callUpdate,
NAME_INDEX); NAME_INDEX);
@@ -1054,15 +1028,38 @@ public class ApnEditor extends SettingsPreferenceFragment
values.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED); values.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED);
if (callUpdate) { if (callUpdate) {
getContentResolver().update(mUri, values, null, null); final Uri uri = mApnData.getUri() == null ? mCarrierUri : mApnData.getUri();
updateApnDataToDatabase(uri, values);
} else { } else {
if (VDBG) Log.d(TAG, "validateAndSave: not calling update()"); if (VDBG) Log.d(TAG, "validateAndSaveApnData: not calling update()");
} }
return true; return true;
} }
private String getErrorMsg() { private void updateApnDataToDatabase(Uri uri, ContentValues values) {
ThreadUtils.postOnBackgroundThread(() -> {
if (uri.equals(mCarrierUri)) {
// Add a new apn to the database
final Uri newUri = getContentResolver().insert(mCarrierUri, values);
if (newUri == null) {
Log.e(TAG, "Can't add a new apn to database " + mCarrierUri);
}
} else {
// Update the existing apn
getContentResolver().update(
uri, values, null /* where */, null /* selection Args */);
}
});
}
/**
* Validates whether the apn data is valid.
*
* @return An error message if the apn data is invalid, otherwise return null.
*/
@VisibleForTesting
String validateApnData() {
String errorMsg = null; String errorMsg = null;
String name = checkNotSet(mName.getText()); String name = checkNotSet(mName.getText());
@@ -1070,14 +1067,14 @@ public class ApnEditor extends SettingsPreferenceFragment
String mcc = checkNotSet(mMcc.getText()); String mcc = checkNotSet(mMcc.getText());
String mnc = checkNotSet(mMnc.getText()); String mnc = checkNotSet(mMnc.getText());
if (name.length() < 1) { if (TextUtils.isEmpty(name)) {
errorMsg = mRes.getString(R.string.error_name_empty); errorMsg = getResources().getString(R.string.error_name_empty);
} else if (apn.length() < 1) { } else if (TextUtils.isEmpty(apn)) {
errorMsg = mRes.getString(R.string.error_apn_empty); errorMsg = getResources().getString(R.string.error_apn_empty);
} else if (mcc.length() != 3) { } else if (mcc == null || mcc.length() != 3) {
errorMsg = mRes.getString(R.string.error_mcc_not3); errorMsg = getResources().getString(R.string.error_mcc_not3);
} else if ((mnc.length() & 0xFFFE) != 2) { } else if ((mnc == null || (mnc.length() & 0xFFFE) != 2)) {
errorMsg = mRes.getString(R.string.error_mnc_not23); errorMsg = getResources().getString(R.string.error_mnc_not23);
} }
if (errorMsg == null) { if (errorMsg == null) {
@@ -1088,13 +1085,13 @@ public class ApnEditor extends SettingsPreferenceFragment
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
for (String type : mReadOnlyApnTypes) { for (String type : mReadOnlyApnTypes) {
stringBuilder.append(type).append(", "); stringBuilder.append(type).append(", ");
Log.d(TAG, "getErrorMsg: appending type: " + type); Log.d(TAG, "validateApnData: appending type: " + type);
} }
// remove last ", " // remove last ", "
if (stringBuilder.length() >= 2) { if (stringBuilder.length() >= 2) {
stringBuilder.delete(stringBuilder.length() - 2, stringBuilder.length()); stringBuilder.delete(stringBuilder.length() - 2, stringBuilder.length());
} }
errorMsg = String.format(mRes.getString(R.string.error_adding_apn_type), errorMsg = String.format(getResources().getString(R.string.error_adding_apn_type),
stringBuilder); stringBuilder);
} }
} }
@@ -1102,9 +1099,16 @@ public class ApnEditor extends SettingsPreferenceFragment
return errorMsg; return errorMsg;
} }
@VisibleForTesting
void showError() {
ErrorDialog.showError(this);
}
private void deleteApn() { private void deleteApn() {
getContentResolver().delete(mUri, null, null); if (mApnData.getUri() != null) {
finish(); getContentResolver().delete(mApnData.getUri(), null, null);
mApnData = new ApnData(sProjection.length);
}
} }
private String starify(String value) { private String starify(String value) {
@@ -1119,20 +1123,21 @@ public class ApnEditor extends SettingsPreferenceFragment
} }
} }
/**
* Returns {@link #sNotSet} if the given string {@code value} is null or empty. The string
* {@link #sNotSet} typically used as the default display when an entry in the preference is
* null or empty.
*/
private String checkNull(String value) { private String checkNull(String value) {
if (value == null || value.length() == 0) { return TextUtils.isEmpty(value) ? sNotSet : value;
return sNotSet;
} else {
return value;
}
} }
/**
* Returns null if the given string {@code value} equals to {@link #sNotSet}. This method
* should be used when convert a string value from preference to database.
*/
private String checkNotSet(String value) { private String checkNotSet(String value) {
if (value == null || value.equals(sNotSet)) { return sNotSet.equals(value) ? null : value;
return "";
} else {
return value;
}
} }
private String getUserEnteredApnType() { private String getUserEnteredApnType() {
@@ -1176,7 +1181,7 @@ public class ApnEditor extends SettingsPreferenceFragment
@Override @Override
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
String msg = ((ApnEditor) getTargetFragment()).getErrorMsg(); String msg = ((ApnEditor) getTargetFragment()).validateApnData();
return new AlertDialog.Builder(getContext()) return new AlertDialog.Builder(getContext())
.setTitle(R.string.error_title) .setTitle(R.string.error_title)
@@ -1191,10 +1196,19 @@ public class ApnEditor extends SettingsPreferenceFragment
} }
} }
public static class InvalidTypeException extends RuntimeException { private ApnData getApnDataFromUri(Uri uri) {
InvalidTypeException(String msg) { ApnData apnData;
super(msg); try (Cursor cursor = getActivity().managedQuery(
uri, sProjection, null /* selection */, null /* sortOrder */)) {
cursor.moveToFirst();
apnData = new ApnData(uri, cursor);
} }
if (apnData == null) {
Log.d(TAG, "Can't get apnData from Uri " + uri);
}
return apnData;
} }
@VisibleForTesting @VisibleForTesting
@@ -1243,34 +1257,17 @@ public class ApnEditor extends SettingsPreferenceFragment
mUri = uri; mUri = uri;
} }
Integer getInteger(int index) throws InvalidTypeException { Integer getInteger(int index) {
if (!isValidTypeOrNull(mData[index], Integer.class)) {
throwInvalidTypeException(Integer.class, mData[index].getClass());
}
return (Integer) mData[index]; return (Integer) mData[index];
} }
Integer getInteger(int index, Integer defaultValue) throws InvalidTypeException { Integer getInteger(int index, Integer defaultValue) {
Integer val = getInteger(index); Integer val = getInteger(index);
return val == null ? defaultValue : val; return val == null ? defaultValue : val;
} }
String getString(int index) throws InvalidTypeException { String getString(int index) {
if (!isValidTypeOrNull(mData[index], String.class)) {
throwInvalidTypeException(String.class, mData[index].getClass());
}
return (String) mData[index]; return (String) mData[index];
} }
private boolean isValidTypeOrNull(Object obj, Class expectedClass) {
return obj == null || expectedClass.isInstance(obj);
}
private void throwInvalidTypeException(Class<?> expectedClass, Class<?> actualClass) {
throw new InvalidTypeException(
String.format(
"Type mismatched, want %s, but is %s", expectedClass, actualClass));
}
} }
} }

View File

@@ -94,7 +94,6 @@ import com.android.internal.app.UnlaunchableAppActivity;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Iterator; import java.util.Iterator;
@@ -874,7 +873,7 @@ public final class Utils extends com.android.settingslib.Utils {
* @param packageName package to check about * @param packageName package to check about
*/ */
public static boolean isProfileOrDeviceOwner(UserManager userManager, public static boolean isProfileOrDeviceOwner(UserManager userManager,
DevicePolicyManagerWrapper devicePolicyManager, String packageName) { DevicePolicyManager devicePolicyManager, String packageName) {
List<UserInfo> userInfos = userManager.getUsers(); List<UserInfo> userInfos = userManager.getUsers();
if (devicePolicyManager.isDeviceOwnerAppOnAnyUser(packageName)) { if (devicePolicyManager.isDeviceOwnerAppOnAnyUser(packageName)) {
return true; return true;

View File

@@ -813,8 +813,8 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
if (!MagnificationPreferenceFragment.isApplicable(context.getResources())) { if (!MagnificationPreferenceFragment.isApplicable(context.getResources())) {
preference.setFragment(ToggleScreenMagnificationPreferenceFragment.class.getName()); preference.setFragment(ToggleScreenMagnificationPreferenceFragment.class.getName());
final Bundle extras = preference.getExtras(); final Bundle extras = preference.getExtras();
MagnificationPreferenceFragment.populateMagnificationGesturesPreferenceExtras(extras, MagnificationGesturesPreferenceController
context); .populateMagnificationGesturesPreferenceExtras(extras, context);
} }
} }

View File

@@ -156,8 +156,8 @@ public class AccessibilitySettingsForSetupWizard extends SettingsPreferenceFragm
preference.setFragment( preference.setFragment(
ToggleScreenMagnificationPreferenceFragmentForSetupWizard.class.getName()); ToggleScreenMagnificationPreferenceFragmentForSetupWizard.class.getName());
final Bundle extras = preference.getExtras(); final Bundle extras = preference.getExtras();
MagnificationPreferenceFragment.populateMagnificationGesturesPreferenceExtras(extras, MagnificationGesturesPreferenceController
context); .populateMagnificationGesturesPreferenceExtras(extras, context);
} }
} }
} }

View File

@@ -0,0 +1,80 @@
/*
* 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.accessibility;
import android.content.Context;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
public class MagnificationGesturesPreferenceController extends BasePreferenceController {
private boolean mIsFromSUW = false;
public MagnificationGesturesPreferenceController(Context context, String key) {
super(context, key);
}
public void setIsFromSUW(boolean fromSUW) {
mIsFromSUW = fromSUW;
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (getPreferenceKey().equals(preference.getKey())) {
Bundle extras = preference.getExtras();
populateMagnificationGesturesPreferenceExtras(extras, mContext);
extras.putBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW, mIsFromSUW);
}
return false;
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public CharSequence getSummary() {
int resId = 0;
if (mIsFromSUW) {
resId = R.string.accessibility_screen_magnification_short_summary;
} else {
final boolean enabled = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1;
resId = (enabled ? R.string.accessibility_feature_state_on :
R.string.accessibility_feature_state_off);
}
return mContext.getString(resId);
}
static void populateMagnificationGesturesPreferenceExtras(Bundle extras, Context context) {
extras.putString(AccessibilitySettings.EXTRA_PREFERENCE_KEY,
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
extras.putString(AccessibilitySettings.EXTRA_TITLE, context.getString(
R.string.accessibility_screen_magnification_gestures_title));
extras.putInt(AccessibilitySettings.EXTRA_TITLE_RES,
R.string.accessibility_screen_magnification_gestures_title);
extras.putCharSequence(AccessibilitySettings.EXTRA_SUMMARY, context.getResources().getText(
R.string.accessibility_screen_magnification_summary));
extras.putBoolean(AccessibilitySettings.EXTRA_CHECKED,
Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1);
extras.putInt(AccessibilitySettings.EXTRA_VIDEO_RAW_RESOURCE_ID,
R.raw.accessibility_screen_magnification);
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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.accessibility;
import android.content.Context;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
public class MagnificationNavbarPreferenceController extends BasePreferenceController {
private boolean mIsFromSUW = false;
public MagnificationNavbarPreferenceController(Context context, String key) {
super(context, key);
}
public void setIsFromSUW(boolean fromSUW) {
mIsFromSUW = fromSUW;
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (getPreferenceKey().equals(preference.getKey())) {
Bundle extras = preference.getExtras();
extras.putString(AccessibilitySettings.EXTRA_PREFERENCE_KEY,
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
extras.putString(AccessibilitySettings.EXTRA_TITLE, mContext.getString(
R.string.accessibility_screen_magnification_navbar_title));
extras.putInt(AccessibilitySettings.EXTRA_TITLE_RES,
R.string.accessibility_screen_magnification_navbar_title);
extras.putCharSequence(AccessibilitySettings.EXTRA_SUMMARY,
mContext.getResources().getText(
R.string.accessibility_screen_magnification_navbar_summary));
extras.putBoolean(AccessibilitySettings.EXTRA_CHECKED,
Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0)
== 1);
extras.putBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW, mIsFromSUW);
}
return false;
}
@Override
public int getAvailabilityStatus() {
return MagnificationPreferenceFragment.isApplicable(mContext.getResources())
? AVAILABLE
: DISABLED_UNSUPPORTED;
}
@Override
public CharSequence getSummary() {
int resId = 0;
if (mIsFromSUW) {
resId = R.string.accessibility_screen_magnification_navbar_short_summary;
} else {
final boolean enabled = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0) == 1;
resId = (enabled ? R.string.accessibility_feature_state_on :
R.string.accessibility_feature_state_off);
}
return mContext.getText(resId);
}
}

View File

@@ -29,40 +29,39 @@ import android.view.View;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable; import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
public final class MagnificationPreferenceFragment extends SettingsPreferenceFragment implements public final class MagnificationPreferenceFragment extends DashboardFragment {
Indexable {
private static final String TAG = "MagnificationPreferenceFragment";
// Settings App preference keys // Settings App preference keys
private static final String PREFERENCE_TITLE_KEY = "magnification_preference_screen_title"; private static final String PREFERENCE_TITLE_KEY = "magnification_preference_screen_title";
private static final String MAGNIFICATION_GESTURES_PREFERENCE_SCREEN_KEY =
"screen_magnification_gestures_preference_screen";
private static final String MAGNIFICATION_NAVBAR_PREFERENCE_SCREEN_KEY =
"screen_magnification_navbar_preference_screen";
// Pseudo ComponentName used to represent navbar magnification in Settings.Secure. // Pseudo ComponentName used to represent navbar magnification in Settings.Secure.
private static final String MAGNIFICATION_COMPONENT_ID = private static final String MAGNIFICATION_COMPONENT_ID =
"com.android.server.accessibility.MagnificationController"; "com.android.server.accessibility.MagnificationController";
private Preference mMagnificationGesturesPreference;
private Preference mMagnificationNavbarPreference;
private boolean mLaunchedFromSuw = false; private boolean mLaunchedFromSuw = false;
@Override @Override
public void onCreatePreferences(Bundle bundle, String s) { public int getMetricsCategory() {
addPreferencesFromResource(R.xml.accessibility_magnification_settings); return MetricsEvent.ACCESSIBILITY_SCREEN_MAGNIFICATION_SETTINGS;
mMagnificationGesturesPreference = findPreference( }
MAGNIFICATION_GESTURES_PREFERENCE_SCREEN_KEY);
mMagnificationNavbarPreference = findPreference(MAGNIFICATION_NAVBAR_PREFERENCE_SCREEN_KEY); @Override
protected String getLogTag() {
return TAG;
} }
@Override @Override
@@ -71,28 +70,21 @@ public final class MagnificationPreferenceFragment extends SettingsPreferenceFra
} }
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { protected int getPreferenceScreenResId() {
super.onViewCreated(view, savedInstanceState); return R.xml.accessibility_magnification_settings;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
final Bundle args = getArguments(); final Bundle args = getArguments();
if ((args != null) && args.containsKey(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW)) { if ((args != null) && args.containsKey(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW)) {
mLaunchedFromSuw = args.getBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW); mLaunchedFromSuw = args.getBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW);
} }
} use(MagnificationGesturesPreferenceController.class)
.setIsFromSUW(mLaunchedFromSuw);
@Override use(MagnificationNavbarPreferenceController.class)
public void onResume() { .setIsFromSUW(mLaunchedFromSuw);
super.onResume();
getActivity().setTitle(R.string.accessibility_screen_magnification_title);
updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
mMagnificationGesturesPreference);
updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
mMagnificationNavbarPreference);
}
@Override
public int getMetricsCategory() {
return MetricsEvent.ACCESSIBILITY_SCREEN_MAGNIFICATION_SETTINGS;
} }
@Override @Override
@@ -102,57 +94,9 @@ public final class MagnificationPreferenceFragment extends SettingsPreferenceFra
preference.setFragment( preference.setFragment(
ToggleScreenMagnificationPreferenceFragmentForSetupWizard.class.getName()); ToggleScreenMagnificationPreferenceFragmentForSetupWizard.class.getName());
} }
if (mMagnificationGesturesPreference == preference) {
handleMagnificationGesturesPreferenceScreenClick();
super.onPreferenceTreeClick(mMagnificationGesturesPreference);
return true;
} else if (mMagnificationNavbarPreference == preference) {
handleMagnificationNavbarPreferenceScreenClick();
super.onPreferenceTreeClick(mMagnificationNavbarPreference);
return true;
}
return super.onPreferenceTreeClick(preference); return super.onPreferenceTreeClick(preference);
} }
private void updateFeatureSummary(String prefKey, Preference pref) {
if (!mLaunchedFromSuw) {
final boolean enabled = Settings.Secure.getInt(getContentResolver(), prefKey, 0) == 1;
pref.setSummary(enabled ? R.string.accessibility_feature_state_on
: R.string.accessibility_feature_state_off);
} else {
if (Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED.equals(prefKey)) {
pref.setSummary(R.string.accessibility_screen_magnification_short_summary);
} else if (Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(
prefKey)) {
pref.setSummary(R.string.accessibility_screen_magnification_navbar_short_summary);
}
}
}
private void handleMagnificationGesturesPreferenceScreenClick() {
Bundle extras = mMagnificationGesturesPreference.getExtras();
populateMagnificationGesturesPreferenceExtras(extras, getContext());
extras.putBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW, mLaunchedFromSuw);
}
private void handleMagnificationNavbarPreferenceScreenClick() {
Bundle extras = mMagnificationNavbarPreference.getExtras();
extras.putString(AccessibilitySettings.EXTRA_PREFERENCE_KEY,
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
extras.putString(AccessibilitySettings.EXTRA_TITLE, getString(
R.string.accessibility_screen_magnification_navbar_title));
extras.putInt(AccessibilitySettings.EXTRA_TITLE_RES,
R.string.accessibility_screen_magnification_navbar_title);
extras.putCharSequence(AccessibilitySettings.EXTRA_SUMMARY,
getActivity().getResources().getText(
R.string.accessibility_screen_magnification_navbar_summary));
extras.putBoolean(AccessibilitySettings.EXTRA_CHECKED,
Settings.Secure.getInt(getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0)
== 1);
extras.putBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW, mLaunchedFromSuw);
}
static CharSequence getConfigurationWarningStringForSecureSettingsKey(String key, static CharSequence getConfigurationWarningStringForSecureSettingsKey(String key,
Context context) { Context context) {
if (!Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(key)) { if (!Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(key)) {
@@ -187,22 +131,6 @@ public final class MagnificationPreferenceFragment extends SettingsPreferenceFra
return null; return null;
} }
static void populateMagnificationGesturesPreferenceExtras(Bundle extras, Context context) {
extras.putString(AccessibilitySettings.EXTRA_PREFERENCE_KEY,
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
extras.putString(AccessibilitySettings.EXTRA_TITLE, context.getString(
R.string.accessibility_screen_magnification_gestures_title));
extras.putInt(AccessibilitySettings.EXTRA_TITLE_RES,
R.string.accessibility_screen_magnification_gestures_title);
extras.putCharSequence(AccessibilitySettings.EXTRA_SUMMARY, context.getResources().getText(
R.string.accessibility_screen_magnification_summary));
extras.putBoolean(AccessibilitySettings.EXTRA_CHECKED,
Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1);
extras.putInt(AccessibilitySettings.EXTRA_VIDEO_RAW_RESOURCE_ID,
R.raw.accessibility_screen_magnification);
}
/** /**
* @return {@code true} if this fragment should be shown, {@code false} otherwise. This * @return {@code true} if this fragment should be shown, {@code false} otherwise. This
* fragment is shown in the case that more than one magnification mode is available. * fragment is shown in the case that more than one magnification mode is available.

View File

@@ -25,7 +25,6 @@ import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.Fragment; import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
@@ -37,13 +36,11 @@ import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.Button;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.applications.LayoutPreference; import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
@@ -58,26 +55,17 @@ public class RemoveAccountPreferenceController extends AbstractPreferenceControl
private Account mAccount; private Account mAccount;
private Fragment mParentFragment; private Fragment mParentFragment;
private UserHandle mUserHandle; private UserHandle mUserHandle;
private DevicePolicyManagerWrapper mDpm;
public RemoveAccountPreferenceController(Context context, Fragment parent) { public RemoveAccountPreferenceController(Context context, Fragment parent) {
this(context, parent, new DevicePolicyManagerWrapper(
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE)));
}
@VisibleForTesting
RemoveAccountPreferenceController(Context context, Fragment parent,
DevicePolicyManagerWrapper dpm) {
super(context); super(context);
mParentFragment = parent; mParentFragment = parent;
mDpm = dpm;
} }
@Override @Override
public void displayPreference(PreferenceScreen screen) { public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen); super.displayPreference(screen);
final LayoutPreference removeAccountPreference = final LayoutPreference removeAccountPreference =
(LayoutPreference) screen.findPreference(KEY_REMOVE_ACCOUNT); (LayoutPreference) screen.findPreference(KEY_REMOVE_ACCOUNT);
Button removeAccountButton = (Button) removeAccountPreference.findViewById(R.id.button); Button removeAccountButton = (Button) removeAccountPreference.findViewById(R.id.button);
removeAccountButton.setOnClickListener(this); removeAccountButton.setOnClickListener(this);
} }
@@ -96,7 +84,7 @@ public class RemoveAccountPreferenceController extends AbstractPreferenceControl
public void onClick(View v) { public void onClick(View v) {
if (mUserHandle != null) { if (mUserHandle != null) {
final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext, final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle.getIdentifier()); UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle.getIdentifier());
if (admin != null) { if (admin != null) {
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, admin); RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, admin);
return; return;
@@ -148,11 +136,11 @@ public class RemoveAccountPreferenceController extends AbstractPreferenceControl
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context = getActivity(); final Context context = getActivity();
return new AlertDialog.Builder(context) return new AlertDialog.Builder(context)
.setTitle(R.string.really_remove_account_title) .setTitle(R.string.really_remove_account_title)
.setMessage(R.string.really_remove_account_message) .setMessage(R.string.really_remove_account_message)
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.remove_account_label, this) .setPositiveButton(R.string.remove_account_label, this)
.create(); .create();
} }
@Override @Override
@@ -174,7 +162,7 @@ public class RemoveAccountPreferenceController extends AbstractPreferenceControl
boolean failed = true; boolean failed = true;
try { try {
if (future.getResult() if (future.getResult()
.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) { .getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) {
failed = false; failed = false;
} }
} catch (OperationCanceledException e) { } catch (OperationCanceledException e) {
@@ -216,10 +204,10 @@ public class RemoveAccountPreferenceController extends AbstractPreferenceControl
final Context context = getActivity(); final Context context = getActivity();
return new AlertDialog.Builder(context) return new AlertDialog.Builder(context)
.setTitle(R.string.really_remove_account_title) .setTitle(R.string.really_remove_account_title)
.setMessage(R.string.remove_account_failed) .setMessage(R.string.remove_account_failed)
.setPositiveButton(android.R.string.ok, null) .setPositiveButton(android.R.string.ok, null)
.create(); .create();
} }
@Override @Override

View File

@@ -47,7 +47,6 @@ import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.AppEntry;
@@ -75,7 +74,7 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
protected String mPackageName; protected String mPackageName;
protected IUsbManager mUsbManager; protected IUsbManager mUsbManager;
protected DevicePolicyManagerWrapper mDpm; protected DevicePolicyManager mDpm;
protected UserManager mUserManager; protected UserManager mUserManager;
protected PackageManager mPm; protected PackageManager mPm;
@@ -94,8 +93,7 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
.getApplicationFeatureProvider(activity); .getApplicationFeatureProvider(activity);
mState = ApplicationsState.getInstance(activity.getApplication()); mState = ApplicationsState.getInstance(activity.getApplication());
mSession = mState.newSession(this, getLifecycle()); mSession = mState.newSession(this, getLifecycle());
mDpm = new DevicePolicyManagerWrapper( mDpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
(DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE));
mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE); mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
mPm = activity.getPackageManager(); mPm = activity.getPackageManager();
IBinder b = ServiceManager.getService(Context.USB_SERVICE); IBinder b = ServiceManager.getService(Context.USB_SERVICE);
@@ -161,10 +159,10 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
} }
protected void setIntentAndFinish(boolean finish, boolean appChanged) { protected void setIntentAndFinish(boolean finish, boolean appChanged) {
if (localLOGV) Log.i(TAG, "appChanged="+appChanged); if (localLOGV) Log.i(TAG, "appChanged=" + appChanged);
Intent intent = new Intent(); Intent intent = new Intent();
intent.putExtra(ManageApplications.APP_CHG, appChanged); intent.putExtra(ManageApplications.APP_CHG, appChanged);
SettingsActivity sa = (SettingsActivity)getActivity(); SettingsActivity sa = (SettingsActivity) getActivity();
sa.finishPreferencePanel(Activity.RESULT_OK, intent); sa.finishPreferencePanel(Activity.RESULT_OK, intent);
mFinishing = true; mFinishing = true;
} }
@@ -176,6 +174,7 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
} }
protected abstract boolean refreshUi(); protected abstract boolean refreshUi();
protected abstract AlertDialog createDialog(int id, int errorCode); protected abstract AlertDialog createDialog(int id, int errorCode);
@Override @Override

View File

@@ -22,7 +22,6 @@ import android.os.Build;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settings.wrapper.IPackageManagerWrapper; import com.android.settings.wrapper.IPackageManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
@@ -34,11 +33,11 @@ public abstract class AppWithAdminGrantedPermissionsCounter extends AppCounter {
private final String[] mPermissions; private final String[] mPermissions;
private final IPackageManagerWrapper mPackageManagerService; private final IPackageManagerWrapper mPackageManagerService;
private final DevicePolicyManagerWrapper mDevicePolicyManager; private final DevicePolicyManager mDevicePolicyManager;
public AppWithAdminGrantedPermissionsCounter(Context context, String[] permissions, public AppWithAdminGrantedPermissionsCounter(Context context, String[] permissions,
PackageManagerWrapper packageManager, IPackageManagerWrapper packageManagerService, PackageManagerWrapper packageManager, IPackageManagerWrapper packageManagerService,
DevicePolicyManagerWrapper devicePolicyManager) { DevicePolicyManager devicePolicyManager) {
super(context, packageManager); super(context, packageManager);
mPermissions = permissions; mPermissions = permissions;
mPackageManagerService = packageManagerService; mPackageManagerService = packageManagerService;
@@ -52,7 +51,7 @@ public abstract class AppWithAdminGrantedPermissionsCounter extends AppCounter {
} }
public static boolean includeInCount(String[] permissions, public static boolean includeInCount(String[] permissions,
DevicePolicyManagerWrapper devicePolicyManager, PackageManagerWrapper packageManager, DevicePolicyManager devicePolicyManager, PackageManagerWrapper packageManager,
IPackageManagerWrapper packageManagerService, ApplicationInfo info) { IPackageManagerWrapper packageManagerService, ApplicationInfo info) {
if (info.targetSdkVersion >= Build.VERSION_CODES.M) { if (info.targetSdkVersion >= Build.VERSION_CODES.M) {
// The app uses run-time permissions. Check whether one or more of the permissions were // The app uses run-time permissions. Check whether one or more of the permissions were
@@ -70,7 +69,7 @@ public abstract class AppWithAdminGrantedPermissionsCounter extends AppCounter {
// permissions and was installed by enterprise policy, implicitly granting permissions. // permissions and was installed by enterprise policy, implicitly granting permissions.
if (packageManager.getInstallReason(info.packageName, if (packageManager.getInstallReason(info.packageName,
new UserHandle(UserHandle.getUserId(info.uid))) new UserHandle(UserHandle.getUserId(info.uid)))
!= PackageManager.INSTALL_REASON_POLICY) { != PackageManager.INSTALL_REASON_POLICY) {
return false; return false;
} }
try { try {

View File

@@ -16,9 +16,10 @@
package com.android.settings.applications; package com.android.settings.applications;
import android.app.admin.DevicePolicyManager;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.os.UserManager; import android.os.UserManager;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settings.wrapper.IPackageManagerWrapper; import com.android.settings.wrapper.IPackageManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
@@ -29,11 +30,11 @@ import com.android.settingslib.wrapper.PackageManagerWrapper;
public abstract class AppWithAdminGrantedPermissionsLister extends AppLister { public abstract class AppWithAdminGrantedPermissionsLister extends AppLister {
private final String[] mPermissions; private final String[] mPermissions;
private final IPackageManagerWrapper mPackageManagerService; private final IPackageManagerWrapper mPackageManagerService;
private final DevicePolicyManagerWrapper mDevicePolicyManager; private final DevicePolicyManager mDevicePolicyManager;
public AppWithAdminGrantedPermissionsLister(String[] permissions, public AppWithAdminGrantedPermissionsLister(String[] permissions,
PackageManagerWrapper packageManager, IPackageManagerWrapper packageManagerService, PackageManagerWrapper packageManager, IPackageManagerWrapper packageManagerService,
DevicePolicyManagerWrapper devicePolicyManager, UserManager userManager) { DevicePolicyManager devicePolicyManager, UserManager userManager) {
super(packageManager, userManager); super(packageManager, userManager);
mPermissions = permissions; mPermissions = permissions;
mPackageManagerService = packageManagerService; mPackageManagerService = packageManagerService;

View File

@@ -16,6 +16,7 @@
package com.android.settings.applications; package com.android.settings.applications;
import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ComponentInfo; import android.content.pm.ComponentInfo;
@@ -26,7 +27,6 @@ import android.os.RemoteException;
import android.os.UserManager; import android.os.UserManager;
import android.util.ArraySet; import android.util.ArraySet;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settings.wrapper.IPackageManagerWrapper; import com.android.settings.wrapper.IPackageManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
@@ -39,11 +39,11 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide
private final Context mContext; private final Context mContext;
private final PackageManagerWrapper mPm; private final PackageManagerWrapper mPm;
private final IPackageManagerWrapper mPms; private final IPackageManagerWrapper mPms;
private final DevicePolicyManagerWrapper mDpm; private final DevicePolicyManager mDpm;
private final UserManager mUm; private final UserManager mUm;
public ApplicationFeatureProviderImpl(Context context, PackageManagerWrapper pm, public ApplicationFeatureProviderImpl(Context context, PackageManagerWrapper pm,
IPackageManagerWrapper pms, DevicePolicyManagerWrapper dpm) { IPackageManagerWrapper pms, DevicePolicyManager dpm) {
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
mPm = pm; mPm = pm;
mPms = pms; mPms = pms;
@@ -150,7 +150,7 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide
CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(Context context, CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(Context context,
String[] permissions, PackageManagerWrapper packageManager, String[] permissions, PackageManagerWrapper packageManager,
IPackageManagerWrapper packageManagerService, IPackageManagerWrapper packageManagerService,
DevicePolicyManagerWrapper devicePolicyManager, NumberOfAppsCallback callback) { DevicePolicyManager devicePolicyManager, NumberOfAppsCallback callback) {
super(context, permissions, packageManager, packageManagerService, devicePolicyManager); super(context, permissions, packageManager, packageManagerService, devicePolicyManager);
mCallback = callback; mCallback = callback;
} }
@@ -182,7 +182,7 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide
CurrentUserAppWithAdminGrantedPermissionsLister(String[] permissions, CurrentUserAppWithAdminGrantedPermissionsLister(String[] permissions,
PackageManagerWrapper packageManager, IPackageManagerWrapper packageManagerService, PackageManagerWrapper packageManager, IPackageManagerWrapper packageManagerService,
DevicePolicyManagerWrapper devicePolicyManager, UserManager userManager, DevicePolicyManager devicePolicyManager, UserManager userManager,
ListOfAppsCallback callback) { ListOfAppsCallback callback) {
super(permissions, packageManager, packageManagerService, devicePolicyManager, super(permissions, packageManager, packageManagerService, devicePolicyManager,
userManager); userManager);

View File

@@ -44,7 +44,6 @@ import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.ActionButtonPreference; import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.AppEntry;
@@ -67,7 +66,7 @@ public class AppActionButtonPreferenceController extends BasePreferenceControlle
private final ApplicationFeatureProvider mApplicationFeatureProvider; private final ApplicationFeatureProvider mApplicationFeatureProvider;
private int mUserId; private int mUserId;
private DevicePolicyManagerWrapper mDpm; private DevicePolicyManager mDpm;
private UserManager mUserManager; private UserManager mUserManager;
private PackageManager mPm; private PackageManager mPm;
@@ -94,7 +93,7 @@ public class AppActionButtonPreferenceController extends BasePreferenceControlle
@Override @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
return AppUtils.isInstant(mParent.getPackageInfo().applicationInfo) return AppUtils.isInstant(mParent.getPackageInfo().applicationInfo)
? DISABLED_FOR_USER : AVAILABLE; ? DISABLED_FOR_USER : AVAILABLE;
} }
@Override @Override
@@ -112,8 +111,7 @@ public class AppActionButtonPreferenceController extends BasePreferenceControlle
mPm = mContext.getPackageManager(); mPm = mContext.getPackageManager();
} }
if (mDpm == null) { if (mDpm == null) {
mDpm = new DevicePolicyManagerWrapper( mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE));
} }
if (mUserManager == null) { if (mUserManager == null) {
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
@@ -125,7 +123,7 @@ public class AppActionButtonPreferenceController extends BasePreferenceControlle
final List<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>(); final List<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
mPm.getHomeActivities(homeActivities); mPm.getHomeActivities(homeActivities);
mHomePackages.clear(); mHomePackages.clear();
for (int i = 0; i< homeActivities.size(); i++) { for (int i = 0; i < homeActivities.size(); i++) {
final ResolveInfo ri = homeActivities.get(i); final ResolveInfo ri = homeActivities.get(i);
final String activityPkg = ri.activityInfo.packageName; final String activityPkg = ri.activityInfo.packageName;
mHomePackages.add(activityPkg); mHomePackages.add(activityPkg);
@@ -187,7 +185,7 @@ public class AppActionButtonPreferenceController extends BasePreferenceControlle
enabled = false; enabled = false;
} else { } else {
ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>(); ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities); ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities);
if (currentDefaultHome == null) { if (currentDefaultHome == null) {
// No preferred default, so permit uninstall only when // No preferred default, so permit uninstall only when
// there is more than one candidate // there is more than one candidate
@@ -284,7 +282,7 @@ public class AppActionButtonPreferenceController extends BasePreferenceControlle
Log.w(TAG, "User can't force stop device admin"); Log.w(TAG, "User can't force stop device admin");
updateForceStopButton(false); updateForceStopButton(false);
} else if (mPm.isPackageStateProtected(packageInfo.packageName, } else if (mPm.isPackageStateProtected(packageInfo.packageName,
UserHandle.getUserId(appEntry.info.uid))) { UserHandle.getUserId(appEntry.info.uid))) {
Log.w(TAG, "User can't force stop protected packages"); Log.w(TAG, "User can't force stop protected packages");
updateForceStopButton(false); updateForceStopButton(false);
} else if (AppUtils.isInstant(packageInfo.applicationInfo)) { } else if (AppUtils.isInstant(packageInfo.applicationInfo)) {
@@ -298,7 +296,7 @@ public class AppActionButtonPreferenceController extends BasePreferenceControlle
} else { } else {
final Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART, final Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
Uri.fromParts("package", appEntry.info.packageName, null)); Uri.fromParts("package", appEntry.info.packageName, null));
intent.putExtra(Intent.EXTRA_PACKAGES, new String[] { appEntry.info.packageName }); intent.putExtra(Intent.EXTRA_PACKAGES, new String[] {appEntry.info.packageName});
intent.putExtra(Intent.EXTRA_UID, appEntry.info.uid); intent.putExtra(Intent.EXTRA_UID, appEntry.info.uid);
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(appEntry.info.uid)); intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(appEntry.info.uid));
Log.d(TAG, "Sending broadcast to query restart status for " Log.d(TAG, "Sending broadcast to query restart status for "

View File

@@ -55,7 +55,6 @@ import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
@@ -122,7 +121,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
private int mUserId; private int mUserId;
private String mPackageName; private String mPackageName;
private DevicePolicyManagerWrapper mDpm; private DevicePolicyManager mDpm;
private UserManager mUserManager; private UserManager mUserManager;
private PackageManager mPm; private PackageManager mPm;
@@ -198,8 +197,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
super.onCreate(icicle); super.onCreate(icicle);
mFinishing = false; mFinishing = false;
final Activity activity = getActivity(); final Activity activity = getActivity();
mDpm = new DevicePolicyManagerWrapper( mDpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
(DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE));
mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE); mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
mPm = activity.getPackageManager(); mPm = activity.getPackageManager();

View File

@@ -109,7 +109,7 @@ public class AppMemoryPreferenceController extends BasePreferenceController
} }
return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext) return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)
? AVAILABLE : DISABLED_DEPENDENT_SETTING; ? AVAILABLE : DISABLED_UNSUPPORTED;
} }
@Override @Override

View File

@@ -40,7 +40,6 @@ import com.android.settings.R;
import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppInfoBase;
import com.android.settings.notification.EmptyTextSettings; import com.android.settings.notification.EmptyTextSettings;
import com.android.settings.widget.AppPreference; import com.android.settings.widget.AppPreference;
import com.android.settings.wrapper.UserManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
import java.text.Collator; import java.text.Collator;
@@ -88,7 +87,7 @@ public class PictureInPictureSettings extends EmptyTextSettings {
private Context mContext; private Context mContext;
private PackageManagerWrapper mPackageManager; private PackageManagerWrapper mPackageManager;
private UserManagerWrapper mUserManager; private UserManager mUserManager;
private IconDrawableFactory mIconDrawableFactory; private IconDrawableFactory mIconDrawableFactory;
/** /**
@@ -119,7 +118,7 @@ public class PictureInPictureSettings extends EmptyTextSettings {
// Do nothing // Do nothing
} }
public PictureInPictureSettings(PackageManagerWrapper pm, UserManagerWrapper um) { public PictureInPictureSettings(PackageManagerWrapper pm, UserManager um) {
mPackageManager = pm; mPackageManager = pm;
mUserManager = um; mUserManager = um;
} }
@@ -130,7 +129,7 @@ public class PictureInPictureSettings extends EmptyTextSettings {
mContext = getActivity(); mContext = getActivity();
mPackageManager = new PackageManagerWrapper(mContext.getPackageManager()); mPackageManager = new PackageManagerWrapper(mContext.getPackageManager());
mUserManager = new UserManagerWrapper(mContext.getSystemService(UserManager.class)); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mIconDrawableFactory = IconDrawableFactory.newInstance(mContext); mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
} }

View File

@@ -22,11 +22,10 @@ import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus; import android.hardware.usb.UsbPortStatus;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import com.android.settings.wrapper.UserManagerWrapper;
/** /**
* Provides access to underlying system USB functionality. * Provides access to underlying system USB functionality.
*/ */
@@ -50,17 +49,17 @@ public class UsbBackend {
private UsbPortStatus mPortStatus; private UsbPortStatus mPortStatus;
public UsbBackend(Context context) { public UsbBackend(Context context) {
this(context, new UserManagerWrapper(UserManager.get(context))); this(context, (UserManager) context.getSystemService(Context.USER_SERVICE));
} }
@VisibleForTesting @VisibleForTesting
public UsbBackend(Context context, UserManagerWrapper userManagerWrapper) { public UsbBackend(Context context, UserManager userManager) {
mUsbManager = context.getSystemService(UsbManager.class); mUsbManager = context.getSystemService(UsbManager.class);
mFileTransferRestricted = userManagerWrapper.isUsbFileTransferRestricted(); mFileTransferRestricted = isUsbFileTransferRestricted(userManager);
mFileTransferRestrictedBySystem = userManagerWrapper.isUsbFileTransferRestrictedBySystem(); mFileTransferRestrictedBySystem = isUsbFileTransferRestrictedBySystem(userManager);
mTetheringRestricted = userManagerWrapper.isUsbTetheringRestricted(); mTetheringRestricted = isUsbTetheringRestricted(userManager);
mTetheringRestrictedBySystem = userManagerWrapper.isUsbTetheringRestrictedBySystem(); mTetheringRestrictedBySystem = isUsbTetheringRestrictedBySystem(userManager);
mMidiSupported = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI); mMidiSupported = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
ConnectivityManager cm = ConnectivityManager cm =
@@ -172,6 +171,24 @@ public class UsbBackend {
return Integer.parseInt(role); return Integer.parseInt(role);
} }
private static boolean isUsbFileTransferRestricted(UserManager userManager) {
return userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER);
}
private static boolean isUsbTetheringRestricted(UserManager userManager) {
return userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
}
private static boolean isUsbFileTransferRestrictedBySystem(UserManager userManager) {
return userManager.hasBaseUserRestriction(
UserManager.DISALLOW_USB_FILE_TRANSFER, UserHandle.of(UserHandle.myUserId()));
}
private static boolean isUsbTetheringRestrictedBySystem(UserManager userManager) {
return userManager.hasBaseUserRestriction(
UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(UserHandle.myUserId()));
}
private boolean areFunctionDisallowed(long functions) { private boolean areFunctionDisallowed(long functions) {
return (mFileTransferRestricted && ((functions & UsbManager.FUNCTION_MTP) != 0 return (mFileTransferRestricted && ((functions & UsbManager.FUNCTION_MTP) != 0
|| (functions & UsbManager.FUNCTION_PTP) != 0)) || (functions & UsbManager.FUNCTION_PTP) != 0))

View File

@@ -22,7 +22,6 @@ import com.android.settings.search.ResultPayload;
import com.android.settings.search.SearchIndexableRaw; import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.slices.SliceData; import com.android.settings.slices.SliceData;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@@ -30,6 +29,10 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.List; import java.util.List;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
/** /**
* Abstract class to consolidate utility between preference controllers and act as an interface * Abstract class to consolidate utility between preference controllers and act as an interface
* for Slices. The abstract classes that inherit from this class will act as the direct interfaces * for Slices. The abstract classes that inherit from this class will act as the direct interfaces
@@ -39,6 +42,12 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
private static final String TAG = "SettingsPrefController"; private static final String TAG = "SettingsPrefController";
/**
* Denotes the availability of the Setting.
* <p>
* Used both explicitly and by the convenience methods {@link #isAvailable()} and
* {@link #isSupported()}.
*/
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({AVAILABLE, DISABLED_UNSUPPORTED, DISABLED_FOR_USER, DISABLED_DEPENDENT_SETTING, @IntDef({AVAILABLE, DISABLED_UNSUPPORTED, DISABLED_FOR_USER, DISABLED_DEPENDENT_SETTING,
UNAVAILABLE_UNKNOWN}) UNAVAILABLE_UNKNOWN})
@@ -52,21 +61,42 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
/** /**
* The setting is not supported by the device. * The setting is not supported by the device.
* <p>
* There is no guarantee that the setting page exists, and any links to the Setting should take
* you to the home page of Settings.
*/ */
public static final int DISABLED_UNSUPPORTED = 1; public static final int DISABLED_UNSUPPORTED = 1;
/** /**
* The setting cannot be changed by the current user. * The setting cannot be changed by the current user.
* <p>
* Links to the Setting should take you to the page of the Setting, even if it cannot be
* changed.
*/ */
public static final int DISABLED_FOR_USER = 2; public static final int DISABLED_FOR_USER = 2;
/** /**
* The setting has a dependency in the Settings App which is currently blocking access. * The setting has a dependency in the Settings App which is currently blocking access.
* <p>
* It must be possible for the Setting to be enabled by changing the configuration of the device
* settings. That is, a setting that cannot be changed because of the state of another setting.
* This should not be used for a setting that would be hidden from the UI entirely.
* <p>
* Correct use: Intensity of night display should be {@link #DISABLED_DEPENDENT_SETTING} when
* night display is off.
* Incorrect use: Mobile Data is {@link #DISABLED_DEPENDENT_SETTING} when there is no
* data-enabled sim.
* <p>
* Links to the Setting should take you to the page of the Setting, even if it cannot be
* changed.
*/ */
public static final int DISABLED_DEPENDENT_SETTING = 3; public static final int DISABLED_DEPENDENT_SETTING = 3;
/** /**
* A catch-all case for internal errors and inexplicable unavailability. * A catch-all case for internal errors and inexplicable unavailability.
* <p>
* There is no guarantee that the setting page exists, and any links to the Setting should take
* you to the home page of Settings.
*/ */
public static final int UNAVAILABLE_UNKNOWN = 4; public static final int UNAVAILABLE_UNKNOWN = 4;
@@ -134,9 +164,25 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
return mPreferenceKey; return mPreferenceKey;
} }
/**
* @return {@code true} when the controller can be changed on the device.
*
* <p>
* Will return true for {@link #AVAILABLE} and {@link #DISABLED_DEPENDENT_SETTING}.
* <p>
* When the availability status returned by {@link #getAvailabilityStatus()} is
* {@link #DISABLED_DEPENDENT_SETTING}, then the setting will be disabled by default in the
* DashboardFragment, and it is up to the {@link BasePreferenceController} to enable the
* preference at the right time.
*
* TODO (mfritze) Build a dependency mechanism to allow a controller to easily define the
* dependent setting.
*/
@Override @Override
public final boolean isAvailable() { public final boolean isAvailable() {
return getAvailabilityStatus() == AVAILABLE; final int availabilityStatus = getAvailabilityStatus();
return (availabilityStatus == AVAILABLE) ||
(availabilityStatus == DISABLED_DEPENDENT_SETTING);
} }
/** /**
@@ -150,6 +196,21 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
return getAvailabilityStatus() != DISABLED_UNSUPPORTED; return getAvailabilityStatus() != DISABLED_UNSUPPORTED;
} }
/**
* Displays preference in this controller.
*/
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
if (getAvailabilityStatus() == DISABLED_DEPENDENT_SETTING) {
// Disable preference if it depends on another setting.
final Preference preference = screen.findPreference(getPreferenceKey());
if (preference != null) {
preference.setEnabled(false);
}
}
}
/** /**
* @return the UI type supported by the controller. * @return the UI type supported by the controller.
*/ */

View File

@@ -47,7 +47,6 @@ import com.android.settings.deviceinfo.storage.VolumeSizesLoader;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable; import com.android.settings.search.Indexable;
import com.android.settings.widget.EntityHeaderController; import com.android.settings.widget.EntityHeaderController;
import com.android.settings.wrapper.UserManagerWrapper;
import com.android.settingslib.applications.StorageStatsSource; import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.deviceinfo.PrivateStorageInfo; import com.android.settingslib.deviceinfo.PrivateStorageInfo;
@@ -185,8 +184,7 @@ public class StorageDashboardFragment extends DashboardFragment
mVolume, new StorageManagerVolumeProvider(sm)); mVolume, new StorageManagerVolumeProvider(sm));
controllers.add(mPreferenceController); controllers.add(mPreferenceController);
UserManagerWrapper userManager = final UserManager userManager = context.getSystemService(UserManager.class);
new UserManagerWrapper(context.getSystemService(UserManager.class));
mSecondaryUsers = SecondaryUserController.getSecondaryUserControllers(context, userManager); mSecondaryUsers = SecondaryUserController.getSecondaryUserControllers(context, userManager);
controllers.addAll(mSecondaryUsers); controllers.addAll(mSecondaryUsers);
@@ -235,8 +233,7 @@ public class StorageDashboardFragment extends DashboardFragment
public List<AbstractPreferenceController> createPreferenceControllers( public List<AbstractPreferenceController> createPreferenceControllers(
Context context) { Context context) {
final StorageManager sm = context.getSystemService(StorageManager.class); final StorageManager sm = context.getSystemService(StorageManager.class);
final UserManagerWrapper userManager = final UserManager userManager = context.getSystemService(UserManager.class);
new UserManagerWrapper(context.getSystemService(UserManager.class));
final List<AbstractPreferenceController> controllers = new ArrayList<>(); final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new StorageSummaryDonutPreferenceController(context)); controllers.add(new StorageSummaryDonutPreferenceController(context));
controllers.add(new StorageItemPreferenceController(context, null /* host */, controllers.add(new StorageItemPreferenceController(context, null /* host */,
@@ -251,9 +248,8 @@ public class StorageDashboardFragment extends DashboardFragment
@Override @Override
public Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> onCreateLoader(int id, public Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> onCreateLoader(int id,
Bundle args) { Bundle args) {
Context context = getContext(); final Context context = getContext();
return new StorageAsyncLoader(context, return new StorageAsyncLoader(context, context.getSystemService(UserManager.class),
new UserManagerWrapper(context.getSystemService(UserManager.class)),
mVolume.fsUuid, mVolume.fsUuid,
new StorageStatsSource(context), new StorageStatsSource(context),
new PackageManagerWrapper(context.getPackageManager())); new PackageManagerWrapper(context.getPackageManager()));

View File

@@ -34,7 +34,6 @@ import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.deviceinfo.storage.StorageAsyncLoader; import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
import com.android.settings.deviceinfo.storage.StorageAsyncLoader.AppsStorageResult; import com.android.settings.deviceinfo.storage.StorageAsyncLoader.AppsStorageResult;
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController; import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
import com.android.settings.wrapper.UserManagerWrapper;
import com.android.settingslib.applications.StorageStatsSource; import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider; import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
@@ -114,9 +113,9 @@ public class StorageProfileFragment extends DashboardFragment
@Override @Override
public Loader<SparseArray<AppsStorageResult>> onCreateLoader(int id, Bundle args) { public Loader<SparseArray<AppsStorageResult>> onCreateLoader(int id, Bundle args) {
Context context = getContext(); final Context context = getContext();
return new StorageAsyncLoader(context, return new StorageAsyncLoader(context,
new UserManagerWrapper(context.getSystemService(UserManager.class)), context.getSystemService(UserManager.class),
mVolume.fsUuid, mVolume.fsUuid,
new StorageStatsSource(context), new StorageStatsSource(context),
new PackageManagerWrapper(context.getPackageManager())); new PackageManagerWrapper(context.getPackageManager()));

View File

@@ -19,6 +19,7 @@ package com.android.settings.deviceinfo.storage;
import android.content.Context; import android.content.Context;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.UserManager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
@@ -29,7 +30,6 @@ import android.util.SparseArray;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.deviceinfo.StorageItemPreference; import com.android.settings.deviceinfo.StorageItemPreference;
import com.android.settings.wrapper.UserManagerWrapper;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import java.util.ArrayList; import java.util.ArrayList;
@@ -61,7 +61,7 @@ public class SecondaryUserController extends AbstractPreferenceController implem
* @param userManager UserManagerWrapper for figuring out which controllers to add. * @param userManager UserManagerWrapper for figuring out which controllers to add.
*/ */
public static List<AbstractPreferenceController> getSecondaryUserControllers( public static List<AbstractPreferenceController> getSecondaryUserControllers(
Context context, UserManagerWrapper userManager) { Context context, UserManager userManager) {
List<AbstractPreferenceController> controllers = new ArrayList<>(); List<AbstractPreferenceController> controllers = new ArrayList<>();
UserInfo primaryUser = userManager.getPrimaryUser(); UserInfo primaryUser = userManager.getPrimaryUser();
boolean addedUser = false; boolean addedUser = false;
@@ -74,8 +74,7 @@ public class SecondaryUserController extends AbstractPreferenceController implem
if (info == null || Utils.isProfileOf(primaryUser, info)) { if (info == null || Utils.isProfileOf(primaryUser, info)) {
controllers.add( controllers.add(
new UserProfileController( new UserProfileController(context, info, USER_PROFILE_INSERTION_LOCATION));
context, info, userManager, USER_PROFILE_INSERTION_LOCATION));
continue; continue;
} }

View File

@@ -26,11 +26,11 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Log; import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
import com.android.settings.wrapper.UserManagerWrapper;
import com.android.settingslib.applications.StorageStatsSource; import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.utils.AsyncLoader; import com.android.settingslib.utils.AsyncLoader;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
@@ -46,7 +46,7 @@ import java.util.List;
*/ */
public class StorageAsyncLoader public class StorageAsyncLoader
extends AsyncLoader<SparseArray<StorageAsyncLoader.AppsStorageResult>> { extends AsyncLoader<SparseArray<StorageAsyncLoader.AppsStorageResult>> {
private UserManagerWrapper mUserManager; private UserManager mUserManager;
private static final String TAG = "StorageAsyncLoader"; private static final String TAG = "StorageAsyncLoader";
private String mUuid; private String mUuid;
@@ -54,7 +54,7 @@ public class StorageAsyncLoader
private PackageManagerWrapper mPackageManager; private PackageManagerWrapper mPackageManager;
private ArraySet<String> mSeenPackages; private ArraySet<String> mSeenPackages;
public StorageAsyncLoader(Context context, UserManagerWrapper userManager, public StorageAsyncLoader(Context context, UserManager userManager,
String uuid, StorageStatsSource source, PackageManagerWrapper pm) { String uuid, StorageStatsSource source, PackageManagerWrapper pm) {
super(context); super(context);
mUserManager = userManager; mUserManager = userManager;

View File

@@ -32,7 +32,6 @@ import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.deviceinfo.StorageItemPreference; import com.android.settings.deviceinfo.StorageItemPreference;
import com.android.settings.deviceinfo.StorageProfileFragment; import com.android.settings.deviceinfo.StorageProfileFragment;
import com.android.settings.wrapper.UserManagerWrapper;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
/** /**
@@ -44,16 +43,13 @@ public class UserProfileController extends AbstractPreferenceController implemen
UserIconLoader.UserIconHandler { UserIconLoader.UserIconHandler {
private static final String PREFERENCE_KEY_BASE = "pref_profile_"; private static final String PREFERENCE_KEY_BASE = "pref_profile_";
private StorageItemPreference mStoragePreference; private StorageItemPreference mStoragePreference;
private UserManagerWrapper mUserManager;
private UserInfo mUser; private UserInfo mUser;
private long mTotalSizeBytes; private long mTotalSizeBytes;
private final int mPreferenceOrder; private final int mPreferenceOrder;
public UserProfileController( public UserProfileController(Context context, UserInfo info, int preferenceOrder) {
Context context, UserInfo info, UserManagerWrapper userManager, int preferenceOrder) {
super(context); super(context);
mUser = Preconditions.checkNotNull(info); mUser = Preconditions.checkNotNull(info);
mUserManager = userManager;
mPreferenceOrder = preferenceOrder; mPreferenceOrder = preferenceOrder;
} }

View File

@@ -15,6 +15,7 @@ package com.android.settings.display;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
@@ -25,7 +26,6 @@ import android.util.Log;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.TimeoutListPreference; import com.android.settings.TimeoutListPreference;
import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
@@ -61,7 +61,8 @@ public class TimeoutPreferenceController extends AbstractPreferenceController im
final long currentTimeout = Settings.System.getLong(mContext.getContentResolver(), final long currentTimeout = Settings.System.getLong(mContext.getContentResolver(),
SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE); SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE);
timeoutListPreference.setValue(String.valueOf(currentTimeout)); timeoutListPreference.setValue(String.valueOf(currentTimeout));
final DevicePolicyManagerWrapper dpm = DevicePolicyManagerWrapper.from(mContext); final DevicePolicyManager dpm =
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
if (dpm != null) { if (dpm != null) {
final RestrictedLockUtils.EnforcedAdmin admin = final RestrictedLockUtils.EnforcedAdmin admin =
RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(mContext); RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(mContext);

View File

@@ -16,6 +16,7 @@
package com.android.settings.enterprise; package com.android.settings.enterprise;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -32,7 +33,6 @@ import android.view.View;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.vpn2.VpnUtils; import com.android.settings.vpn2.VpnUtils;
import com.android.settings.wrapper.ConnectivityManagerWrapper; import com.android.settings.wrapper.ConnectivityManagerWrapper;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
import java.util.Date; import java.util.Date;
@@ -41,7 +41,7 @@ import java.util.List;
public class EnterprisePrivacyFeatureProviderImpl implements EnterprisePrivacyFeatureProvider { public class EnterprisePrivacyFeatureProviderImpl implements EnterprisePrivacyFeatureProvider {
private final Context mContext; private final Context mContext;
private final DevicePolicyManagerWrapper mDpm; private final DevicePolicyManager mDpm;
private final PackageManagerWrapper mPm; private final PackageManagerWrapper mPm;
private final UserManager mUm; private final UserManager mUm;
private final ConnectivityManagerWrapper mCm; private final ConnectivityManagerWrapper mCm;
@@ -49,7 +49,7 @@ public class EnterprisePrivacyFeatureProviderImpl implements EnterprisePrivacyFe
private static final int MY_USER_ID = UserHandle.myUserId(); private static final int MY_USER_ID = UserHandle.myUserId();
public EnterprisePrivacyFeatureProviderImpl(Context context, DevicePolicyManagerWrapper dpm, public EnterprisePrivacyFeatureProviderImpl(Context context, DevicePolicyManager dpm,
PackageManagerWrapper pm, UserManager um, ConnectivityManagerWrapper cm, PackageManagerWrapper pm, UserManager um, ConnectivityManagerWrapper cm,
Resources resources) { Resources resources) {
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();

View File

@@ -54,7 +54,6 @@ import com.android.settings.fuelgauge.anomaly.AnomalyUtils;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController; import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.widget.EntityHeaderController; import com.android.settings.widget.EntityHeaderController;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
@@ -116,7 +115,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
private AppButtonsPreferenceController mAppButtonsPreferenceController; private AppButtonsPreferenceController mAppButtonsPreferenceController;
private BackgroundActivityPreferenceController mBackgroundActivityPreferenceController; private BackgroundActivityPreferenceController mBackgroundActivityPreferenceController;
private DevicePolicyManagerWrapper mDpm; private DevicePolicyManager mDpm;
private UserManager mUserManager; private UserManager mUserManager;
private PackageManager mPackageManager; private PackageManager mPackageManager;
private List<Anomaly> mAnomalies; private List<Anomaly> mAnomalies;
@@ -167,7 +166,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
.launch(); .launch();
} }
private static @UserIdInt int getUserIdToLaunchAdvancePowerUsageDetail(BatterySipper bs) { private static @UserIdInt
int getUserIdToLaunchAdvancePowerUsageDetail(BatterySipper bs) {
if (bs.drainType == BatterySipper.DrainType.USER) { if (bs.drainType == BatterySipper.DrainType.USER) {
return ActivityManager.getCurrentUser(); return ActivityManager.getCurrentUser();
} }
@@ -206,8 +206,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
super.onAttach(activity); super.onAttach(activity);
mState = ApplicationsState.getInstance(getActivity().getApplication()); mState = ApplicationsState.getInstance(getActivity().getApplication());
mDpm = new DevicePolicyManagerWrapper( mDpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
(DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE));
mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE); mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
mPackageManager = activity.getPackageManager(); mPackageManager = activity.getPackageManager();
mBatteryUtils = BatteryUtils.getInstance(getContext()); mBatteryUtils = BatteryUtils.getInstance(getContext());

View File

@@ -19,6 +19,7 @@ package com.android.settings.fuelgauge;
import android.app.Activity; import android.app.Activity;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.Fragment; import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
@@ -50,7 +51,6 @@ import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.ActionButtonPreference; import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
@@ -102,7 +102,7 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
private final int mRequestRemoveDeviceAdmin; private final int mRequestRemoveDeviceAdmin;
private ApplicationsState.Session mSession; private ApplicationsState.Session mSession;
private DevicePolicyManagerWrapper mDpm; private DevicePolicyManager mDpm;
private UserManager mUserManager; private UserManager mUserManager;
private PackageManager mPm; private PackageManager mPm;
private SettingsActivity mActivity; private SettingsActivity mActivity;
@@ -118,7 +118,7 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
public AppButtonsPreferenceController(SettingsActivity activity, Fragment fragment, public AppButtonsPreferenceController(SettingsActivity activity, Fragment fragment,
Lifecycle lifecycle, String packageName, ApplicationsState state, Lifecycle lifecycle, String packageName, ApplicationsState state,
DevicePolicyManagerWrapper dpm, UserManager userManager, DevicePolicyManager dpm, UserManager userManager,
PackageManager packageManager, int requestUninstall, int requestRemoveDeviceAdmin) { PackageManager packageManager, int requestUninstall, int requestRemoveDeviceAdmin) {
super(activity); super(activity);
@@ -477,7 +477,7 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
} else { } else {
Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART, Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
Uri.fromParts("package", mAppEntry.info.packageName, null)); Uri.fromParts("package", mAppEntry.info.packageName, null));
intent.putExtra(Intent.EXTRA_PACKAGES, new String[]{mAppEntry.info.packageName}); intent.putExtra(Intent.EXTRA_PACKAGES, new String[] {mAppEntry.info.packageName});
intent.putExtra(Intent.EXTRA_UID, mAppEntry.info.uid); intent.putExtra(Intent.EXTRA_UID, mAppEntry.info.uid);
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mAppEntry.info.uid)); intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mAppEntry.info.uid));
Log.d(TAG, "Sending broadcast to query restart status for " Log.d(TAG, "Sending broadcast to query restart status for "

View File

@@ -30,7 +30,6 @@ import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip; import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip; import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend; import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
@@ -48,7 +47,7 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
private final UserManager mUserManager; private final UserManager mUserManager;
private final int mUid; private final int mUid;
@VisibleForTesting @VisibleForTesting
DevicePolicyManagerWrapper mDpm; DevicePolicyManager mDpm;
@VisibleForTesting @VisibleForTesting
BatteryUtils mBatteryUtils; BatteryUtils mBatteryUtils;
private InstrumentedPreferenceFragment mFragment; private InstrumentedPreferenceFragment mFragment;
@@ -66,8 +65,7 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
super(context); super(context);
mPowerWhitelistBackend = backend; mPowerWhitelistBackend = backend;
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mDpm = new DevicePolicyManagerWrapper( mDpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE));
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mUid = uid; mUid = uid;
mFragment = fragment; mFragment = fragment;

View File

@@ -42,12 +42,17 @@ public class AnomalyCleanupJobService extends JobService {
final ComponentName component = new ComponentName(context, AnomalyCleanupJobService.class); final ComponentName component = new ComponentName(context, AnomalyCleanupJobService.class);
final JobInfo.Builder jobBuilder = final JobInfo.Builder jobBuilder =
new JobInfo.Builder(R.id.job_anomaly_clean_up, component) new JobInfo.Builder(R.integer.job_anomaly_clean_up, component)
.setPeriodic(CLEAN_UP_FREQUENCY_MS) .setPeriodic(CLEAN_UP_FREQUENCY_MS)
.setRequiresDeviceIdle(true) .setRequiresDeviceIdle(true)
.setRequiresCharging(true); .setRequiresCharging(true)
.setPersisted(true);
final JobInfo pending = jobScheduler.getPendingJob(R.integer.job_anomaly_clean_up);
if (jobScheduler.schedule(jobBuilder.build()) != JobScheduler.RESULT_SUCCESS) { // Don't schedule it if it already exists, to make sure it runs periodically even after
// reboot
if (pending == null && jobScheduler.schedule(jobBuilder.build())
!= JobScheduler.RESULT_SUCCESS) {
Log.i(TAG, "Anomaly clean up job service schedule failed."); Log.i(TAG, "Anomaly clean up job service schedule failed.");
} }
} }

View File

@@ -52,12 +52,17 @@ public class AnomalyConfigJobService extends JobService {
final ComponentName component = new ComponentName(context, AnomalyConfigJobService.class); final ComponentName component = new ComponentName(context, AnomalyConfigJobService.class);
final JobInfo.Builder jobBuilder = final JobInfo.Builder jobBuilder =
new JobInfo.Builder(R.id.job_anomaly_config_update, component) new JobInfo.Builder(R.integer.job_anomaly_config_update, component)
.setPeriodic(CONFIG_UPDATE_FREQUENCY_MS) .setPeriodic(CONFIG_UPDATE_FREQUENCY_MS)
.setRequiresDeviceIdle(true) .setRequiresDeviceIdle(true)
.setRequiresCharging(true); .setRequiresCharging(true)
.setPersisted(true);
final JobInfo pending = jobScheduler.getPendingJob(R.integer.job_anomaly_config_update);
if (jobScheduler.schedule(jobBuilder.build()) != JobScheduler.RESULT_SUCCESS) { // Don't schedule it if it already exists, to make sure it runs periodically even after
// reboot
if (pending == null && jobScheduler.schedule(jobBuilder.build())
!= JobScheduler.RESULT_SUCCESS) {
Log.i(TAG, "Anomaly config update job service schedule failed."); Log.i(TAG, "Anomaly config update job service schedule failed.");
} }
} }

View File

@@ -70,7 +70,7 @@ public class AnomalyDetectionJobService extends JobService {
final ComponentName component = new ComponentName(context, final ComponentName component = new ComponentName(context,
AnomalyDetectionJobService.class); AnomalyDetectionJobService.class);
final JobInfo.Builder jobBuilder = final JobInfo.Builder jobBuilder =
new JobInfo.Builder(R.id.job_anomaly_detection, component) new JobInfo.Builder(R.integer.job_anomaly_detection, component)
.setOverrideDeadline(MAX_DELAY_MS); .setOverrideDeadline(MAX_DELAY_MS);
if (jobScheduler.enqueue(jobBuilder.build(), new JobWorkItem(intent)) if (jobScheduler.enqueue(jobBuilder.build(), new JobWorkItem(intent))

View File

@@ -49,10 +49,8 @@ public class NetworkDashboardFragment extends DashboardFragment implements
private static final String TAG = "NetworkDashboardFrag"; private static final String TAG = "NetworkDashboardFrag";
private static final int MENU_NETWORK_RESET = Menu.FIRST; private static final int MENU_NETWORK_RESET = Menu.FIRST;
private static final int MENU_PRIVATE_DNS = Menu.FIRST + 1;
private NetworkResetActionMenuController mNetworkResetController; private NetworkResetActionMenuController mNetworkResetController;
private PrivateDnsMenuController mPrivateDnsMenuController;
@Override @Override
public int getMetricsCategory() { public int getMetricsCategory() {
@@ -73,8 +71,6 @@ public class NetworkDashboardFragment extends DashboardFragment implements
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
mNetworkResetController = new NetworkResetActionMenuController(context, MENU_NETWORK_RESET); mNetworkResetController = new NetworkResetActionMenuController(context, MENU_NETWORK_RESET);
mPrivateDnsMenuController = new PrivateDnsMenuController(getFragmentManager(),
MENU_PRIVATE_DNS);
} }
@Override @Override
@@ -86,7 +82,6 @@ public class NetworkDashboardFragment extends DashboardFragment implements
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
mNetworkResetController.buildMenuItem(menu); mNetworkResetController.buildMenuItem(menu);
mPrivateDnsMenuController.buildMenuItem(menu);
} }
@Override @Override
@@ -109,6 +104,8 @@ public class NetworkDashboardFragment extends DashboardFragment implements
new MobileNetworkPreferenceController(context); new MobileNetworkPreferenceController(context);
final VpnPreferenceController vpnPreferenceController = final VpnPreferenceController vpnPreferenceController =
new VpnPreferenceController(context); new VpnPreferenceController(context);
final PrivateDnsPreferenceController privateDnsPreferenceController =
new PrivateDnsPreferenceController(context);
if (lifecycle != null) { if (lifecycle != null) {
lifecycle.addObserver(airplaneModePreferenceController); lifecycle.addObserver(airplaneModePreferenceController);
@@ -116,6 +113,7 @@ public class NetworkDashboardFragment extends DashboardFragment implements
lifecycle.addObserver(wifiPreferenceController); lifecycle.addObserver(wifiPreferenceController);
lifecycle.addObserver(mobileNetworkPreferenceController); lifecycle.addObserver(mobileNetworkPreferenceController);
lifecycle.addObserver(vpnPreferenceController); lifecycle.addObserver(vpnPreferenceController);
lifecycle.addObserver(privateDnsPreferenceController);
} }
final List<AbstractPreferenceController> controllers = new ArrayList<>(); final List<AbstractPreferenceController> controllers = new ArrayList<>();
@@ -126,6 +124,7 @@ public class NetworkDashboardFragment extends DashboardFragment implements
controllers.add(new ProxyPreferenceController(context)); controllers.add(new ProxyPreferenceController(context));
controllers.add(mobilePlanPreferenceController); controllers.add(mobilePlanPreferenceController);
controllers.add(wifiPreferenceController); controllers.add(wifiPreferenceController);
controllers.add(privateDnsPreferenceController);
return controllers; return controllers;
} }

View File

@@ -20,19 +20,18 @@ import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.content.ActivityNotFoundException;
import android.app.FragmentManager;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.util.AttributeSet;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
@@ -41,8 +40,9 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.utils.AnnotationSpan; import com.android.settings.utils.AnnotationSpan;
import com.android.settingslib.CustomDialogPreference;
import com.android.settingslib.HelpUtils; import com.android.settingslib.HelpUtils;
import java.util.HashMap; import java.util.HashMap;
@@ -51,7 +51,7 @@ import java.util.Map;
/** /**
* Dialog to set the private dns * Dialog to set the private dns
*/ */
public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment implements public class PrivateDnsModeDialogPreference extends CustomDialogPreference implements
DialogInterface.OnClickListener, RadioGroup.OnCheckedChangeListener, TextWatcher { DialogInterface.OnClickListener, RadioGroup.OnCheckedChangeListener, TextWatcher {
public static final String ANNOTATION_URL = "url"; public static final String ANNOTATION_URL = "url";
@@ -77,41 +77,44 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp
@VisibleForTesting @VisibleForTesting
RadioGroup mRadioGroup; RadioGroup mRadioGroup;
@VisibleForTesting @VisibleForTesting
Button mSaveButton;
@VisibleForTesting
String mMode; String mMode;
public static void show(FragmentManager fragmentManager) { public PrivateDnsModeDialogPreference(Context context) {
if (fragmentManager.findFragmentByTag(TAG) == null) { super(context);
final PrivateDnsModeDialogFragment fragment = new PrivateDnsModeDialogFragment();
fragment.show(fragmentManager, TAG);
}
} }
public PrivateDnsModeDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PrivateDnsModeDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public PrivateDnsModeDialogPreference(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private final AnnotationSpan.LinkInfo mUrlLinkInfo = new AnnotationSpan.LinkInfo(
ANNOTATION_URL, (widget) -> {
final Context context = widget.getContext();
final Intent intent = HelpUtils.getHelpIntent(context,
context.getString(R.string.help_uri_private_dns),
context.getClass().getName());
if (intent != null) {
try {
widget.startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
Log.w(TAG, "Activity was not found for intent, " + intent.toString());
}
}
});
@Override @Override
public Dialog onCreateDialog(Bundle savedInstanceState) { protected void onBindDialogView(View view) {
final Context context = getContext(); final Context context = getContext();
final AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(R.string.select_private_dns_configuration_title)
.setView(buildPrivateDnsView(context))
.setPositiveButton(R.string.save, this)
.setNegativeButton(R.string.dlg_cancel, null)
.create();
dialog.setOnShowListener(dialogInterface -> {
mSaveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
updateDialogInfo();
});
return dialog;
}
private View buildPrivateDnsView(final Context context) {
final ContentResolver contentResolver = context.getContentResolver(); final ContentResolver contentResolver = context.getContentResolver();
mMode = Settings.Global.getString(contentResolver, MODE_KEY);
final View view = LayoutInflater.from(context).inflate(R.layout.private_dns_mode_dialog,
null);
mEditText = view.findViewById(R.id.private_dns_mode_provider_hostname); mEditText = view.findViewById(R.id.private_dns_mode_provider_hostname);
mEditText.addTextChangedListener(this); mEditText.addTextChangedListener(this);
mEditText.setText(Settings.Global.getString(contentResolver, HOSTNAME_KEY)); mEditText.setText(Settings.Global.getString(contentResolver, HOSTNAME_KEY));
@@ -131,26 +134,20 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp
helpTextView.setText(AnnotationSpan.linkify( helpTextView.setText(AnnotationSpan.linkify(
context.getText(R.string.private_dns_help_message), linkInfo)); context.getText(R.string.private_dns_help_message), linkInfo));
} }
return view;
} }
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
final Context context = getContext();
if (mMode.equals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) { if (mMode.equals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) {
// Only clickable if hostname is valid, so we could save it safely // Only clickable if hostname is valid, so we could save it safely
Settings.Global.putString(getContext().getContentResolver(), HOSTNAME_KEY, Settings.Global.putString(context.getContentResolver(), HOSTNAME_KEY,
mEditText.getText().toString()); mEditText.getText().toString());
} }
mMetricsFeatureProvider.action(getContext(), FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context,
MetricsProto.MetricsEvent.ACTION_PRIVATE_DNS_MODE, mMode); MetricsProto.MetricsEvent.ACTION_PRIVATE_DNS_MODE, mMode);
Settings.Global.putString(getContext().getContentResolver(), MODE_KEY, mMode); Settings.Global.putString(context.getContentResolver(), MODE_KEY, mMode);
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DIALOG_PRIVATE_DNS;
} }
@Override @Override
@@ -179,9 +176,7 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
if (mSaveButton != null) { updateDialogInfo();
mSaveButton.setEnabled(isWeaklyValidatedHostname(mEditText.getText().toString()));
}
} }
private boolean isWeaklyValidatedHostname(String hostname) { private boolean isWeaklyValidatedHostname(String hostname) {
@@ -193,17 +188,24 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp
return hostname.matches(WEAK_HOSTNAME_REGEX); return hostname.matches(WEAK_HOSTNAME_REGEX);
} }
private Button getSaveButton() {
final AlertDialog dialog = (AlertDialog) getDialog();
if (dialog == null) {
return null;
}
return dialog.getButton(DialogInterface.BUTTON_POSITIVE);
}
private void updateDialogInfo() { private void updateDialogInfo() {
final boolean modeProvider = PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(mMode); final boolean modeProvider = PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(mMode);
if (mEditText != null) { if (mEditText != null) {
mEditText.setEnabled(modeProvider); mEditText.setEnabled(modeProvider);
} }
if (mSaveButton != null) { final Button saveButton = getSaveButton();
mSaveButton.setEnabled( if (saveButton != null) {
modeProvider saveButton.setEnabled(modeProvider
? isWeaklyValidatedHostname(mEditText.getText().toString()) ? isWeaklyValidatedHostname(mEditText.getText().toString())
: true); : true);
} }
} }
} }

View File

@@ -16,29 +16,28 @@
package com.android.settings.network; package com.android.settings.network;
import android.app.FragmentManager; import android.content.Context;
import android.view.Menu;
import android.view.MenuItem;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
public class PrivateDnsMenuController { public class PrivateDnsPreferenceController extends BasePreferenceController
private final FragmentManager mFragmentManager; implements PreferenceControllerMixin, LifecycleObserver {
private final int mMenuId; private static final String KEY_PRIVATE_DNS_SETTINGS = "private_dns_settings";
public PrivateDnsMenuController(FragmentManager fragmentManager, int menuId) { public PrivateDnsPreferenceController(Context context) {
mFragmentManager = fragmentManager; super(context, KEY_PRIVATE_DNS_SETTINGS);
mMenuId = menuId;
} }
public void buildMenuItem(Menu menu) { @Override
if (menu != null) { public String getPreferenceKey() {
MenuItem item = menu.add(0 /* groupId */, mMenuId, 0 /* order */, return KEY_PRIVATE_DNS_SETTINGS;
R.string.select_private_dns_configuration_title); }
item.setOnMenuItemClickListener(target -> {
PrivateDnsModeDialogFragment.show(mFragmentManager); @Override
return true; public int getAvailabilityStatus() {
}); return AVAILABLE;
}
} }
} }

View File

@@ -180,13 +180,11 @@ public class VpnPreferenceController extends AbstractPreferenceController
mNetworkCallback = new ConnectivityManager.NetworkCallback() { mNetworkCallback = new ConnectivityManager.NetworkCallback() {
@Override @Override
public void onAvailable(Network network) { public void onAvailable(Network network) {
Log.d(TAG, "onAvailable " + network.netId);
updateSummary(); updateSummary();
} }
@Override @Override
public void onLost(Network network) { public void onLost(Network network) {
Log.d(TAG, "onLost " + network.netId);
updateSummary(); updateSummary();
} }
}; };

View File

@@ -52,7 +52,6 @@ import com.android.settings.slices.SlicesFeatureProviderImpl;
import com.android.settings.users.UserFeatureProvider; import com.android.settings.users.UserFeatureProvider;
import com.android.settings.users.UserFeatureProviderImpl; import com.android.settings.users.UserFeatureProviderImpl;
import com.android.settings.wrapper.ConnectivityManagerWrapper; import com.android.settings.wrapper.ConnectivityManagerWrapper;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settings.wrapper.IPackageManagerWrapper; import com.android.settings.wrapper.IPackageManagerWrapper;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
@@ -114,8 +113,8 @@ public class FeatureFactoryImpl extends FeatureFactory {
mApplicationFeatureProvider = new ApplicationFeatureProviderImpl(context, mApplicationFeatureProvider = new ApplicationFeatureProviderImpl(context,
new PackageManagerWrapper(context.getPackageManager()), new PackageManagerWrapper(context.getPackageManager()),
new IPackageManagerWrapper(AppGlobals.getPackageManager()), new IPackageManagerWrapper(AppGlobals.getPackageManager()),
new DevicePolicyManagerWrapper((DevicePolicyManager) context (DevicePolicyManager) context
.getSystemService(Context.DEVICE_POLICY_SERVICE))); .getSystemService(Context.DEVICE_POLICY_SERVICE));
} }
return mApplicationFeatureProvider; return mApplicationFeatureProvider;
} }
@@ -132,8 +131,7 @@ public class FeatureFactoryImpl extends FeatureFactory {
public EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(Context context) { public EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(Context context) {
if (mEnterprisePrivacyFeatureProvider == null) { if (mEnterprisePrivacyFeatureProvider == null) {
mEnterprisePrivacyFeatureProvider = new EnterprisePrivacyFeatureProviderImpl(context, mEnterprisePrivacyFeatureProvider = new EnterprisePrivacyFeatureProviderImpl(context,
new DevicePolicyManagerWrapper((DevicePolicyManager) context (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE),
.getSystemService(Context.DEVICE_POLICY_SERVICE)),
new PackageManagerWrapper(context.getPackageManager()), new PackageManagerWrapper(context.getPackageManager()),
UserManager.get(context), UserManager.get(context),
new ConnectivityManagerWrapper((ConnectivityManager) context new ConnectivityManagerWrapper((ConnectivityManager) context

View File

@@ -32,7 +32,6 @@ import com.android.settings.TimeoutListPreference;
import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.security.trustagent.TrustAgentManager; import com.android.settings.security.trustagent.TrustAgentManager;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
@@ -44,14 +43,14 @@ public class LockAfterTimeoutPreferenceController extends AbstractPreferenceCont
private final int mUserId; private final int mUserId;
private final LockPatternUtils mLockPatternUtils; private final LockPatternUtils mLockPatternUtils;
private final TrustAgentManager mTrustAgentManager; private final TrustAgentManager mTrustAgentManager;
private final DevicePolicyManagerWrapper mDPM; private final DevicePolicyManager mDPM;
public LockAfterTimeoutPreferenceController(Context context, int userId, public LockAfterTimeoutPreferenceController(Context context, int userId,
LockPatternUtils lockPatternUtils) { LockPatternUtils lockPatternUtils) {
super(context); super(context);
mUserId = userId; mUserId = userId;
mLockPatternUtils = lockPatternUtils; mLockPatternUtils = lockPatternUtils;
mDPM = DevicePolicyManagerWrapper.from(context); mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
mTrustAgentManager = FeatureFactory.getFactory(context) mTrustAgentManager = FeatureFactory.getFactory(context)
.getSecurityFeatureProvider().getTrustAgentManager(); .getSecurityFeatureProvider().getTrustAgentManager();
} }

View File

@@ -27,7 +27,6 @@ import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.wrapper.WallpaperManagerWrapper;
public class WallpaperSuggestionActivity extends Activity { public class WallpaperSuggestionActivity extends Activity {
@@ -61,9 +60,16 @@ public class WallpaperSuggestionActivity extends Activity {
@VisibleForTesting @VisibleForTesting
public static boolean isSuggestionComplete(Context context) { public static boolean isSuggestionComplete(Context context) {
final WallpaperManagerWrapper manager = new WallpaperManagerWrapper(context); if (!isWallpaperServiceEnabled(context)) {
return manager.isWallpaperServiceEnabled() ? manager.getWallpaperId( return true;
WallpaperManager.FLAG_SYSTEM) > 0 : false; }
final WallpaperManager manager = (WallpaperManager) context.getSystemService(
WALLPAPER_SERVICE);
return manager.getWallpaperId(WallpaperManager.FLAG_SYSTEM) > 0;
} }
private static boolean isWallpaperServiceEnabled(Context context) {
return context.getResources().getBoolean(
com.android.internal.R.bool.config_enableWallpaperService);
}
} }

View File

@@ -43,7 +43,7 @@ public class PreferenceCategoryController extends BasePreferenceController {
@Override @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
if (mChildren == null || mChildren.isEmpty()) { if (mChildren == null || mChildren.isEmpty()) {
return DISABLED_DEPENDENT_SETTING; return DISABLED_UNSUPPORTED;
} }
// Category is available if any child is available // Category is available if any child is available
for (AbstractPreferenceController controller : mChildren) { for (AbstractPreferenceController controller : mChildren) {
@@ -51,7 +51,7 @@ public class PreferenceCategoryController extends BasePreferenceController {
return AVAILABLE; return AVAILABLE;
} }
} }
return DISABLED_DEPENDENT_SETTING; return DISABLED_UNSUPPORTED;
} }
@Override @Override

View File

@@ -16,6 +16,7 @@
package com.android.settings.wifi; package com.android.settings.wifi;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
@@ -25,7 +26,6 @@ import android.net.wifi.WifiConfiguration;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
public class WifiUtils { public class WifiUtils {
@@ -69,7 +69,8 @@ public class WifiUtils {
return false; return false;
} }
final DevicePolicyManagerWrapper dpm = DevicePolicyManagerWrapper.from(context); final DevicePolicyManager dpm =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
final PackageManagerWrapper pm = new PackageManagerWrapper(context.getPackageManager()); final PackageManagerWrapper pm = new PackageManagerWrapper(context.getPackageManager());
// Check if device has DPM capability. If it has and dpm is still null, then we // Check if device has DPM capability. If it has and dpm is still null, then we

View File

@@ -1,229 +0,0 @@
/*
* Copyright (C) 2016 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.wrapper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import java.util.List;
/**
* This class replicates a subset of the android.app.admin.DevicePolicyManager (DPM). The
* class exists so that we can use a thin wrapper around the DPM in production code and a mock
* in tests. We cannot directly mock or shadow the DPM, because some of the methods we rely on are
* newer than the API version supported by Robolectric.
*/
public class DevicePolicyManagerWrapper {
private final DevicePolicyManager mDpm;
public DevicePolicyManagerWrapper(DevicePolicyManager dpm) {
mDpm = dpm;
}
public static @Nullable DevicePolicyManagerWrapper from(Context context) {
DevicePolicyManager dpm =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
return dpm == null ? null : new DevicePolicyManagerWrapper(dpm);
}
/**
* Calls {@code DevicePolicyManager.getActiveAdminsAsUser()}.
*
* @see DevicePolicyManager#getActiveAdminsAsUser
*/
public @Nullable List<ComponentName> getActiveAdminsAsUser(int userId) {
return mDpm.getActiveAdminsAsUser(userId);
}
/**
* Calls {@code DevicePolicyManager.getMaximumFailedPasswordsForWipe()}.
*
* @see DevicePolicyManager#getMaximumFailedPasswordsForWipe
*/
public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin, int userHandle) {
return mDpm.getMaximumFailedPasswordsForWipe(admin, userHandle);
}
/**
* Calls {@code DevicePolicyManager.getDeviceOwnerComponentOnCallingUser()}.
*
* @see DevicePolicyManager#getDeviceOwnerComponentOnCallingUser
*/
public ComponentName getDeviceOwnerComponentOnCallingUser() {
return mDpm.getDeviceOwnerComponentOnCallingUser();
}
/**
* Calls {@code DevicePolicyManager.getDeviceOwnerComponentOnAnyUser()}.
*
* @see DevicePolicyManager#getDeviceOwnerComponentOnAnyUser
*/
public ComponentName getDeviceOwnerComponentOnAnyUser() {
return mDpm.getDeviceOwnerComponentOnAnyUser();
}
/**
* Calls {@code DevicePolicyManager.getProfileOwnerAsUser()}.
*
* @see DevicePolicyManager#getProfileOwnerAsUser
*/
public @Nullable ComponentName getProfileOwnerAsUser(final int userId) {
return mDpm.getProfileOwnerAsUser(userId);
}
/**
* Calls {@code DevicePolicyManager.getDeviceOwnerNameOnAnyUser()}.
*
* @see DevicePolicyManager#getDeviceOwnerNameOnAnyUser
*/
public CharSequence getDeviceOwnerOrganizationName() {
return mDpm.getDeviceOwnerOrganizationName();
}
/**
* Calls {@code DevicePolicyManager.getPermissionGrantState()}.
*
* @see DevicePolicyManager#getPermissionGrantState
*/
public int getPermissionGrantState(@Nullable ComponentName admin, String packageName,
String permission) {
return mDpm.getPermissionGrantState(admin, packageName, permission);
}
/**
* Calls {@code DevicePolicyManager.isSecurityLoggingEnabled()}.
*
* @see DevicePolicyManager#isSecurityLoggingEnabled
*/
public boolean isSecurityLoggingEnabled(@Nullable ComponentName admin) {
return mDpm.isSecurityLoggingEnabled(admin);
}
/**
* Calls {@code DevicePolicyManager.isNetworkLoggingEnabled()}.
*
* @see DevicePolicyManager#isNetworkLoggingEnabled
*/
public boolean isNetworkLoggingEnabled(@Nullable ComponentName admin) {
return mDpm.isNetworkLoggingEnabled(admin);
}
/**
* Calls {@code DevicePolicyManager.getLastSecurityLogRetrievalTime()}.
*
* @see DevicePolicyManager#getLastSecurityLogRetrievalTime
*/
public long getLastSecurityLogRetrievalTime() {
return mDpm.getLastSecurityLogRetrievalTime();
}
/**
* Calls {@code DevicePolicyManager.getLastBugReportRequestTime()}.
*
* @see DevicePolicyManager#getLastBugReportRequestTime
*/
public long getLastBugReportRequestTime() {
return mDpm.getLastBugReportRequestTime();
}
/**
* Calls {@code DevicePolicyManager.getLastNetworkLogRetrievalTime()}.
*
* @see DevicePolicyManager#getLastNetworkLogRetrievalTime
*/
public long getLastNetworkLogRetrievalTime() {
return mDpm.getLastNetworkLogRetrievalTime();
}
/**
* Calls {@code DevicePolicyManager.isCurrentInputMethodSetByOwner()}.
*
* @see DevicePolicyManager#isCurrentInputMethodSetByOwner
*/
public boolean isCurrentInputMethodSetByOwner() {
return mDpm.isCurrentInputMethodSetByOwner();
}
/**
* Calls {@code DevicePolicyManager.getOwnerInstalledCaCerts()}.
*
* @see DevicePolicyManager#getOwnerInstalledCaCerts
*/
public List<String> getOwnerInstalledCaCerts(@NonNull UserHandle user) {
return mDpm.getOwnerInstalledCaCerts(user);
}
/**
* Calls {@code DevicePolicyManager.isDeviceOwnerAppOnAnyUser()}.
*
* @see DevicePolicyManager#isDeviceOwnerAppOnAnyUser
*/
public boolean isDeviceOwnerAppOnAnyUser(String packageName) {
return mDpm.isDeviceOwnerAppOnAnyUser(packageName);
}
/**
* Calls {@code DevicePolicyManager.packageHasActiveAdmins()}.
*
* @see DevicePolicyManager#packageHasActiveAdmins
*/
public boolean packageHasActiveAdmins(String packageName) {
return mDpm.packageHasActiveAdmins(packageName);
}
/**
* Calls {@code DevicePolicyManager.isUninstallInQueue()}.
*
* @see DevicePolicyManager#isUninstallInQueue
*/
public boolean isUninstallInQueue(String packageName) {
return mDpm.isUninstallInQueue(packageName);
}
/**
* Calls {@code DevicePolicyManager.createAdminSupportIntent()}.
*
* @see DevicePolicyManager#createAdminSupportIntent(String)
*/
public Intent createAdminSupportIntent(@NonNull String restriction) {
return mDpm.createAdminSupportIntent(restriction);
}
/**
* Calls {@code DevicePolicyManager#getDeviceOwnerUserId()}.
*
* @see DevicePolicyManager#getDeviceOwnerUserId()
*/
public int getDeviceOwnerUserId() {
return mDpm.getDeviceOwnerUserId();
}
/**
* Calls {@code DevicePolicyManager#getMaximumTimeToLock()}.
*
* @see DevicePolicyManager#getMaximumTimeToLock(ComponentName, int)
*/
public long getMaximumTimeToLock(@Nullable ComponentName admin, @UserIdInt int userHandle) {
return mDpm.getMaximumTimeToLock(admin, userHandle);
}
}

View File

@@ -1,67 +0,0 @@
/*
* Copyright (C) 2017 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.wrapper;
import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
import java.util.List;
/**
* This class replicates a subset of the android.os.UserManager. The class
* exists so that we can use a thin wrapper around the UserManager in production code and a mock in
* tests. We cannot directly mock or shadow the UserManager, because some of the methods we rely on
* are newer than the API version supported by Robolectric or are hidden.
*/
public class UserManagerWrapper {
private UserManager mUserManager;
public UserManagerWrapper(UserManager userManager) {
mUserManager = userManager;
}
public UserInfo getPrimaryUser() {
return mUserManager.getPrimaryUser();
}
public List<UserInfo> getUsers() {
return mUserManager.getUsers();
}
public List<UserInfo> getProfiles(int userHandle) {
return mUserManager.getProfiles(userHandle);
}
public boolean isUsbFileTransferRestricted() {
return mUserManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER);
}
public boolean isUsbTetheringRestricted() {
return mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
}
public boolean isUsbFileTransferRestrictedBySystem() {
return mUserManager.hasBaseUserRestriction(
UserManager.DISALLOW_USB_FILE_TRANSFER, UserHandle.of(UserHandle.myUserId()));
}
public boolean isUsbTetheringRestrictedBySystem() {
return mUserManager.hasBaseUserRestriction(
UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(UserHandle.myUserId()));
}
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright (C) 2017 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.wrapper;
import android.app.WallpaperManager;
import android.content.Context;
public class WallpaperManagerWrapper {
private final WallpaperManager mWallpaperManager;
private final boolean mWallpaperServiceEnabled;
public WallpaperManagerWrapper(Context context) {
mWallpaperServiceEnabled = context.getResources().getBoolean(
com.android.internal.R.bool.config_enableWallpaperService);
mWallpaperManager = mWallpaperServiceEnabled ? (WallpaperManager) context.getSystemService(
Context.WALLPAPER_SERVICE) : null;
}
public boolean isWallpaperServiceEnabled() {
return mWallpaperServiceEnabled;
}
public int getWallpaperId(int which) {
if (!mWallpaperServiceEnabled) {
throw new RuntimeException("This device does not have wallpaper service enabled.");
}
return mWallpaperManager.getWallpaperId(which);
}
}

View File

@@ -16,27 +16,73 @@
package com.android.settings; package com.android.settings;
import static junit.framework.Assert.assertEquals; import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.support.v14.preference.MultiSelectListPreference;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.EditTextPreference;
import android.support.v7.preference.ListPreference;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.android.settings.ApnEditor.ApnData; import com.android.settings.ApnEditor.ApnData;
import com.android.settings.ApnEditor.InvalidTypeException;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
public class ApnEditorTest { public class ApnEditorTest {
private static final Object[] APN_DATA = new Object[] {
0, /* ID */
"apn_name" /* apn name */,
"apn.com" /* apn */,
"" /* proxy */,
"" /* port */,
"" /* username */,
"" /* server */,
"" /* password */,
"" /* MMSC */,
"123" /* MCC */,
"456" /* MNC */,
"123456" /* operator numeric */,
"" /* MMS proxy */,
"" /* MMS port */,
0 /* Authentication type */,
"default,supl,ia" /* APN type */,
"IPv6" /* APN protocol */,
1 /* APN enable/disable */,
0 /* Bearer */,
0 /* Bearer BITMASK*/,
"IPv4" /* APN roaming protocol */,
"None" /* MVNO type */,
"", /* MVNO value */
};
private static final int CURSOR_INTEGER_INDEX = 0; private static final int CURSOR_INTEGER_INDEX = 0;
private static final int CURSOR_STRING_INDEX = 1; private static final int CURSOR_STRING_INDEX = 1;
@@ -45,10 +91,331 @@ public class ApnEditorTest {
@Mock @Mock
private Cursor mCursor; private Cursor mCursor;
@Captor
private ArgumentCaptor<Uri> mUriCaptor;
private ApnEditor mApnEditorUT;
private Activity mActivity;
private Resources mResources;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mActivity = spy(Robolectric.setupActivity(Activity.class));
mResources = mActivity.getResources();
mApnEditorUT = spy(new ApnEditor());
doReturn(mActivity).when(mApnEditorUT).getActivity();
doReturn(mResources).when(mApnEditorUT).getResources();
doNothing().when(mApnEditorUT).finish();
doNothing().when(mApnEditorUT).showError();
setMockPreference(mActivity);
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
mApnEditorUT.sNotSet = "Not Set";
}
@Test
public void testSetStringValue_valueChanged_shouldSetValue() {
// GIVEN an APN value which is different than the APN value in database
final String apnKey = "apn";
final String apnValue = "testing.com";
final ContentValues cv = new ContentValues();
// WHEN try to check and set the apn value
final boolean isDiff = mApnEditorUT.setStringValueAndCheckIfDiff(
cv, apnKey, apnValue, false /* assumeDiff */, ApnEditor.APN_INDEX);
// THEN the APN value is different than the one in database, and it has been stored in the
// given ContentValues
assertThat(isDiff).isTrue();
assertThat(apnValue).isEqualTo(cv.getAsString(apnKey));
}
@Test
public void testSetStringValue_valueNotChanged_shouldNotSetValue() {
// GIVEN an APN value which is same as the APN value in database
final String apnKey = "apn";
final String apnValue = (String) APN_DATA[ApnEditor.APN_INDEX];
final ContentValues cv = new ContentValues();
// WHEN try to check and set the apn value
final boolean isDiff = mApnEditorUT.setStringValueAndCheckIfDiff(
cv, apnKey, apnValue, false /* assumeDiff */, ApnEditor.APN_INDEX);
// THEN the APN value is same as the one in database, and the new APN value is not stored
// in the given ContentValues
assertThat(isDiff).isFalse();
assertThat(cv.get(apnKey)).isNull();
}
@Test
public void testSetStringValue_nullValue_shouldNotSetValue_shouldNotSetValue() {
// GIVEN a null APN value
final String apnKey = "apn";
final String apnValue = null;
final ContentValues cv = new ContentValues();
// WHEN try to check and set the apn value
final boolean isDiff = mApnEditorUT.setStringValueAndCheckIfDiff(
cv, apnKey, apnValue, false /* assumeDiff */, ApnEditor.APN_INDEX);
// THEN the APN value is different than the one in database, but the null value is not
// stored in the given ContentValues
assertThat(isDiff).isTrue();
assertThat(cv.get(apnKey)).isNull();
}
@Test
public void testSetIntValue_valueChanged_shouldSetValue() {
// GIVEN a value indicated whether the apn is enabled, and it's different than the value in
// the database
final String apnEnabledKey = "apn_enabled";
final int apnEnabledValue = 0;
final ContentValues cv = new ContentValues();
// WHEN try to check and set the apn enabled
final boolean isDiff = mApnEditorUT.setIntValueAndCheckIfDiff(
cv,
apnEnabledKey,
apnEnabledValue,
false /* assumeDiff */,
ApnEditor.CARRIER_ENABLED_INDEX);
// THEN the apn enabled field is different than the one in database, and it has been stored
// in the given ContentValues
assertThat(isDiff).isTrue();
assertThat(cv.getAsInteger(apnEnabledKey)).isEqualTo(apnEnabledValue);
}
@Test
public void testSetIntValue_valueNotChanged_shouldNotSetValue() {
// GIVEN a value indicated whether the apn is enabled, and it's same as the one in the
// database
final String apnEnabledKey = "apn_enabled";
final int apnEnabledValue = (int) APN_DATA[ApnEditor.CARRIER_ENABLED_INDEX];
final ContentValues cv = new ContentValues();
// WHEN try to check and set the apn enabled
final boolean isDiff = mApnEditorUT.setIntValueAndCheckIfDiff(
cv,
apnEnabledKey,
apnEnabledValue,
false /* assumeDiff */,
ApnEditor.CARRIER_ENABLED_INDEX);
// THEN the apn enabled field is same as the one in the database, and the filed is not
// stored in the given ContentValues
assertThat(isDiff).isFalse();
assertThat(cv.get(apnEnabledKey)).isNull();
}
@Test
public void testValidateApnData_validData_shouldReturnNull() {
// GIVEN a valid apn data
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
mApnEditorUT.fillUI(true /* firstTime */);
// WHEN validate the apn data
final String errMsg = mApnEditorUT.validateApnData();
// THEN the error message should be null
assertThat(errMsg).isNull();
}
@Test
public void testValidateApn_apnNameNotSet_shouldReturnErrorMessage() {
// GIVEN a apn data without the apn name
final FakeApnData apnData = new FakeApnData(APN_DATA);
apnData.mData[ApnEditor.NAME_INDEX] = "";
mApnEditorUT.mApnData = apnData;
mApnEditorUT.fillUI(true /* firstTime */);
// THEN validate the apn data
final String errMsg = mApnEditorUT.validateApnData();
// THEN the error message indicated the apn name not set is returned
assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_name_empty));
}
@Test
public void testValidateApnData_apnNotSet_shouldReturnErrorMessage() {
// GIVEN a apn data without the apn
final FakeApnData apnData = new FakeApnData(APN_DATA);
apnData.mData[ApnEditor.APN_INDEX] = "";
mApnEditorUT.mApnData = apnData;
mApnEditorUT.fillUI(true /* firstTime */);
// THEN validate the apn data
final String errMsg = mApnEditorUT.validateApnData();
// THEN the error message indicated the apn not set is returned
assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_apn_empty));
}
@Test
public void testValidateApnData_mccInvalid_shouldReturnErrorMessage() {
// GIVEN a apn data with invalid mcc
final FakeApnData apnData = new FakeApnData(APN_DATA);
// The length of the mcc should be 3
apnData.mData[ApnEditor.MCC_INDEX] = "1324";
mApnEditorUT.mApnData = apnData;
mApnEditorUT.fillUI(true /* firstTime */);
// WHEN validate the apn data
final String errMsg = mApnEditorUT.validateApnData();
// THEN the error message indicated the mcc invalid is returned
assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_mcc_not3));
}
@Test
public void testValidateApnData_mncInvalid_shouldReturnErrorMessage() {
// GIVEN an apn data with invalid mnc
final FakeApnData apnData = new FakeApnData(APN_DATA);
// The length of the mnc should be 2 or 3
apnData.mData[ApnEditor.MNC_INDEX] = "1324";
mApnEditorUT.mApnData = apnData;
mApnEditorUT.fillUI(true /* firstTime */);
// WHEN validate the apn data
final String errMsg = mApnEditorUT.validateApnData();
// THEN the error message indicated the mnc invalid is returned
assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_mnc_not23));
}
@Test
public void testSaveApnData_pressBackButtonWithValidApnData_shouldSaveApnData() {
// GIVEN a valid apn data
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
mApnEditorUT.fillUI(true /* firstTime */);
// WHEN press the back button
final KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
mApnEditorUT.onKey(new View(mActivity), KeyEvent.KEYCODE_BACK, event);
// THEN the apn data is saved and the apn editor is closed
verify(mApnEditorUT).validateAndSaveApnData();
verify(mApnEditorUT).finish();
}
@Test
public void testSaveApnData_pressSaveButtonWithValidApnData_shouldSaveApnData() {
// GIVEN a valid apn data
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
mApnEditorUT.fillUI(true /* firstTime */);
// WHEN press the save button
MenuItem item = Mockito.mock(MenuItem.class);
// Menu.FIRST + 1 indicated the SAVE option in ApnEditor
doReturn(Menu.FIRST + 1).when(item).getItemId();
mApnEditorUT.onOptionsItemSelected(item);
// THEN the apn data is saved and the apn editor is closed
verify(mApnEditorUT).validateAndSaveApnData();
verify(mApnEditorUT).finish();
}
@Test
public void testSaveApnData_apnDataInvalid_shouldNotSaveApnData() {
// GIVEN an invalid apn data
final FakeApnData apnData = new FakeApnData(APN_DATA);
// The valid apn data should contains a non-empty apn name
apnData.mData[ApnEditor.NAME_INDEX] = "";
mApnEditorUT.mApnData = apnData;
mApnEditorUT.fillUI(true /* firstTime */);
// WHEN press the save button
final MenuItem item = Mockito.mock(MenuItem.class);
// Menu.FIRST + 1 indicated the SAVE option in ApnEditor
doReturn(Menu.FIRST + 1).when(item).getItemId();
mApnEditorUT.onOptionsItemSelected(item);
// THEN the error dialog is shown
verify(mApnEditorUT).validateAndSaveApnData();
verify(mApnEditorUT).showError();
}
@Test
public void testDeleteApnData_shouldDeleteData() {
// GIVEN a valid apn data correspond a row in database
final Uri apnUri = Uri.parse("content://telephony/carriers/1");
mApnEditorUT.mApnData = new FakeApnData(APN_DATA, apnUri);
mApnEditorUT.fillUI(true /* firstTime */);
ContentResolver mockContentResolver = Mockito.mock(ContentResolver.class);
doReturn(mockContentResolver).when(mActivity).getContentResolver();
// WHEN press the save button
final MenuItem item = Mockito.mock(MenuItem.class);
// Menu.FIRST indicated the DELETE option in ApnEditor
doReturn(Menu.FIRST).when(item).getItemId();
mApnEditorUT.onOptionsItemSelected(item);
// THEN the apn data is deleted and the apn editor is closed
verify(mockContentResolver).delete(mUriCaptor.capture(), any(), any());
assertThat(apnUri).isEqualTo(mUriCaptor.getValue());
verify(mApnEditorUT).finish();
}
@Test(expected = ClassCastException.class)
public void testApnData_invalidIntegerType_throwsInvalidTypeException() {
// GIVEN a ApnData constructed from cursor
initCursor(); initCursor();
final ApnData data = new ApnData(mApnUri, mCursor);
// WHEN get a string from an integer column
// THEN the InvalidTypeException is threw
data.getString(CURSOR_INTEGER_INDEX);
}
@Test(expected = ClassCastException.class)
public void testApnData_invalidStringType_throwsInvalidTypeException() {
// GIVEN a ApnData constructed from cursor
initCursor();
final ApnData data = new ApnData(mApnUri, mCursor);
// WHEN get a integer from a string column
// THEN the InvalidTypeException is threw
data.getInteger(CURSOR_STRING_INDEX);
}
@Test
public void testApnData_validIntegerType_returnCorrectValue() {
// GIVEN a ApnData constructed from cursor
initCursor();
final ApnData data = new ApnData(mApnUri, mCursor);
// WHEN get integer from an integer column
final int val = data.getInteger(CURSOR_INTEGER_INDEX);
// THEN the integer is returned correctly
assertThat(val).isEqualTo(mCursor.getInt(CURSOR_INTEGER_INDEX));
}
@Test
public void testApnData_validStringType_returnCorrectValue() {
// GIVEN a ApnData constructed from cursor
initCursor();
final ApnData data = new ApnData(mApnUri, mCursor);
// WHEN get string from a string column
final String str = data.getString(CURSOR_STRING_INDEX);
// THEN the integer is returned correctly
assertThat(str).isEqualTo(mCursor.getString(CURSOR_STRING_INDEX));
}
@Test
public void testApnData_nullValueColumn_returnNull() {
// GIVEN a empty ApnData
final ApnData data = new ApnData(3);
// WHEN get string value from a null column
final String str = data.getString(0);
// THEN the null value is returned
assertThat(str).isNull();
} }
private void initCursor() { private void initCursor() {
@@ -59,59 +426,38 @@ public class ApnEditorTest {
doReturn(Cursor.FIELD_TYPE_STRING).when(mCursor).getType(CURSOR_STRING_INDEX); doReturn(Cursor.FIELD_TYPE_STRING).when(mCursor).getType(CURSOR_STRING_INDEX);
} }
@Test(expected = InvalidTypeException.class) private void setMockPreference(Context context) {
public void testApnData_invalidIntegerType_throwsInvalidTypeException() { mApnEditorUT.mName = new EditTextPreference(context);
// GIVEN a ApnData constructed from cursor mApnEditorUT.mApn = new EditTextPreference(context);
ApnData data = new ApnData(mApnUri, mCursor); mApnEditorUT.mProxy = new EditTextPreference(context);
mApnEditorUT.mPort = new EditTextPreference(context);
// WHEN get a string from an integer column mApnEditorUT.mUser = new EditTextPreference(context);
// THEN the InvalidTypeException is threw mApnEditorUT.mServer = new EditTextPreference(context);
data.getString(CURSOR_INTEGER_INDEX); mApnEditorUT.mPassword = new EditTextPreference(context);
mApnEditorUT.mMmsc = new EditTextPreference(context);
mApnEditorUT.mMcc = new EditTextPreference(context);
mApnEditorUT.mMnc = new EditTextPreference(context);
mApnEditorUT.mMmsProxy = new EditTextPreference(context);
mApnEditorUT.mMmsPort = new EditTextPreference(context);
mApnEditorUT.mAuthType = new ListPreference(context);
mApnEditorUT.mApnType = new EditTextPreference(context);
mApnEditorUT.mProtocol = new ListPreference(context);
mApnEditorUT.mRoamingProtocol = new ListPreference(context);
mApnEditorUT.mCarrierEnabled = new SwitchPreference(context);
mApnEditorUT.mBearerMulti = new MultiSelectListPreference(context);
mApnEditorUT.mMvnoType = new ListPreference(context);
mApnEditorUT.mMvnoMatchData = new EditTextPreference(context);
} }
@Test(expected = InvalidTypeException.class) private final class FakeApnData extends ApnData {
public void testApnData_invalidStringType_throwsInvalidTypeException() { FakeApnData(Object[] data) {
// GIVEN a ApnData constructed from cursor super(data.length);
ApnData data = new ApnData(mApnUri, mCursor); System.arraycopy(data, 0, mData, 0, data.length);
}
// WHEN get a integer from a string column FakeApnData(Object[] data, Uri uri) {
// THEN the InvalidTypeException is threw this(data);
data.getInteger(CURSOR_STRING_INDEX); mUri = uri;
}
} }
}
@Test
public void testApnData_validIntegerType_returnCorrectValue() {
// GIVEN a ApnData constructed from cursor
ApnData data = new ApnData(mApnUri, mCursor);
// WHEN get integer from an integer column
int val = data.getInteger(CURSOR_INTEGER_INDEX);
// THEN the integer is returned correctly
assertEquals(mCursor.getInt(CURSOR_INTEGER_INDEX), val);
}
@Test
public void testApnData_validStringType_returnCorrectValue() {
// GIVEN a ApnData constructed from cursor
ApnData data = new ApnData(mApnUri, mCursor);
// WHEN get string from a string column
String str = data.getString(CURSOR_STRING_INDEX);
// THEN the integer is returned correctly
assertEquals(mCursor.getString(CURSOR_STRING_INDEX), str);
}
@Test
public void testApnData_nullValueColumn_returnNull() {
// GIVEN a empty ApnData
ApnData data = new ApnData(3);
// WHEN get string value from a null column
String str = data.getString(0);
// THEN the null value is returned
assertNull(str);
}
}

View File

@@ -17,7 +17,6 @@
package com.android.settings; package com.android.settings;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
@@ -28,6 +27,7 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@@ -48,7 +48,6 @@ import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -74,7 +73,7 @@ public class UtilsTest {
@Mock @Mock
private ConnectivityManager connectivityManager; private ConnectivityManager connectivityManager;
@Mock @Mock
private DevicePolicyManagerWrapper mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
@Mock @Mock
private UserManager mUserManager; private UserManager mUserManager;
@Mock @Mock

View File

@@ -0,0 +1,80 @@
/*
* 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.accessibility;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
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;
@RunWith(SettingsRobolectricTestRunner.class)
public class MagnificationGesturesPreferenceControllerTest {
private Context mContext;
private MagnificationGesturesPreferenceController mController;
private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new MagnificationGesturesPreferenceController(mContext, "pref_key");
mPreference = new Preference(mContext);
mController.updateState(mPreference);
}
@Test
public void isAlwaysAvailable() {
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
}
@Test
public void updateState_shouldRefreshSummary() {
Settings.System.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 1);
mController.updateState(mPreference);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.accessibility_feature_state_on));
Settings.System.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0);
mController.updateState(mPreference);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.accessibility_feature_state_off));
}
@Test
public void updateState_shouldRefreshSummarySuw() {
mController.setIsFromSUW(true);
mController.updateState(mPreference);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.
accessibility_screen_magnification_short_summary));
}
}

View File

@@ -0,0 +1,123 @@
/*
* 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.accessibility;
import static com.android.settings.search.ResultPayload.Availability.AVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.content.res.Resources;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.After;
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.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
@RunWith(SettingsRobolectricTestRunner.class)
public class MagnificationNavbarPreferenceControllerTest {
private Context mContext;
private MagnificationNavbarPreferenceController mController;
private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mController = new MagnificationNavbarPreferenceController(mContext, "test_key");
mPreference = new Preference(mContext);
mController.updateState(mPreference);
}
@After
public void tearDown() {
ShadowMagnificationPreferenceFragment.reset();
}
@Test
@Config(shadows = ShadowMagnificationPreferenceFragment.class)
public void isAvailable_unsupported_shouldNotBeAvailable() {
ShadowMagnificationPreferenceFragment.setApplicable(false);
assertThat(mController.getAvailabilityStatus())
.isNotEqualTo(AVAILABLE);
}
@Test
@Config(shadows = ShadowMagnificationPreferenceFragment.class)
public void isAvailable_supported_shouldBeAvailable() {
ShadowMagnificationPreferenceFragment.setApplicable(true);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(AVAILABLE);
}
@Test
public void updateState_shouldRefreshSummary() {
Settings.System.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 1);
mController.updateState(mPreference);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getText(R.string.accessibility_feature_state_on));
Settings.System.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0);
mController.updateState(mPreference);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getText(R.string.accessibility_feature_state_off));
}
@Test
public void updateState_shouldRefreshSummarySuw() {
mController.setIsFromSUW(true);
mController.updateState(mPreference);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.
accessibility_screen_magnification_navbar_short_summary));
}
@Implements(MagnificationPreferenceFragment.class)
public static class ShadowMagnificationPreferenceFragment {
private static boolean sIsApplicable;
@Resetter
static void reset() {
sIsApplicable = false;
}
@Implementation
static boolean isApplicable(Resources res) {
return sIsApplicable;
}
static void setApplicable(boolean applicable) {
sIsApplicable = applicable;
}
}
}

View File

@@ -50,10 +50,6 @@ import com.android.settings.testutils.shadow.ShadowAccountManager;
import com.android.settings.testutils.shadow.ShadowContentResolver; import com.android.settings.testutils.shadow.ShadowContentResolver;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -64,12 +60,14 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.ShadowApplication;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@Config( @Config(shadows = {
shadows = {
ShadowUserManager.class, ShadowUserManager.class,
ShadowDevicePolicyManager.class ShadowDevicePolicyManager.class
}) })
public class RemoveAccountPreferenceControllerTest { public class RemoveAccountPreferenceControllerTest {
private static final String KEY_REMOVE_ACCOUNT = "remove_account"; private static final String KEY_REMOVE_ACCOUNT = "remove_account";
@@ -78,8 +76,6 @@ public class RemoveAccountPreferenceControllerTest {
@Mock(answer = RETURNS_DEEP_STUBS) @Mock(answer = RETURNS_DEEP_STUBS)
private AccountManager mAccountManager; private AccountManager mAccountManager;
@Mock @Mock
private DevicePolicyManagerWrapper mDevicePolicyManager;
@Mock
private PreferenceFragment mFragment; private PreferenceFragment mFragment;
@Mock @Mock
private PreferenceManager mPreferenceManager; private PreferenceManager mPreferenceManager;
@@ -105,10 +101,10 @@ public class RemoveAccountPreferenceControllerTest {
when(mFragment.getFragmentManager()).thenReturn(mFragmentManager); when(mFragment.getFragmentManager()).thenReturn(mFragmentManager);
when(mFragmentManager.beginTransaction()).thenReturn(mFragmentTransaction); when(mFragmentManager.beginTransaction()).thenReturn(mFragmentTransaction);
when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())) when(mAccountManager.getAuthenticatorTypesAsUser(anyInt()))
.thenReturn(new AuthenticatorDescription[0]); .thenReturn(new AuthenticatorDescription[0]);
when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]); when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
mController = new RemoveAccountPreferenceController(RuntimeEnvironment.application, mController = new RemoveAccountPreferenceController(RuntimeEnvironment.application,
mFragment, mDevicePolicyManager); mFragment);
} }
@Test @Test
@@ -128,8 +124,8 @@ public class RemoveAccountPreferenceControllerTest {
mController.onClick(null); mController.onClick(null);
verify(mFragmentTransaction).add( verify(mFragmentTransaction).add(
any(RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.class), any(RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.class),
eq(TAG_REMOVE_ACCOUNT_DIALOG)); eq(TAG_REMOVE_ACCOUNT_DIALOG));
} }
@Test @Test
@@ -141,20 +137,20 @@ public class RemoveAccountPreferenceControllerTest {
List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>(); List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
enforcingUsers.add(new UserManager.EnforcingUser(userId, enforcingUsers.add(new UserManager.EnforcingUser(userId,
UserManager.RESTRICTION_SOURCE_DEVICE_OWNER)); UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
ComponentName componentName = new ComponentName("test", "test"); ComponentName componentName = new ComponentName("test", "test");
// Ensure that RestrictedLockUtils.checkIfRestrictionEnforced doesn't return null. // Ensure that RestrictedLockUtils.checkIfRestrictionEnforced doesn't return null.
ShadowUserManager.getShadow().setUserRestrictionSources( ShadowUserManager.getShadow().setUserRestrictionSources(
UserManager.DISALLOW_MODIFY_ACCOUNTS, UserManager.DISALLOW_MODIFY_ACCOUNTS,
UserHandle.of(userId), UserHandle.of(userId),
enforcingUsers); enforcingUsers);
ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(componentName); ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(componentName);
mController.onClick(null); mController.onClick(null);
verify(mFragmentTransaction, never()).add( verify(mFragmentTransaction, never()).add(
any(RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.class), any(RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.class),
eq(TAG_REMOVE_ACCOUNT_DIALOG)); eq(TAG_REMOVE_ACCOUNT_DIALOG));
} }
@Test @Test
@@ -168,11 +164,11 @@ public class RemoveAccountPreferenceControllerTest {
Account account = new Account("Account11", "com.acct1"); Account account = new Account("Account11", "com.acct1");
UserHandle userHandle = new UserHandle(10); UserHandle userHandle = new UserHandle(10);
RemoveAccountPreferenceController.ConfirmRemoveAccountDialog dialog = RemoveAccountPreferenceController.ConfirmRemoveAccountDialog dialog =
RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.show( RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.show(
mFragment, account, userHandle); mFragment, account, userHandle);
dialog.onCreate(new Bundle()); dialog.onCreate(new Bundle());
dialog.onClick(null, 0); dialog.onClick(null, 0);
verify(mAccountManager).removeAccountAsUser(eq(account), nullable(Activity.class), verify(mAccountManager).removeAccountAsUser(eq(account), nullable(Activity.class),
nullable(AccountManagerCallback.class), nullable(Handler.class), eq(userHandle)); nullable(AccountManagerCallback.class), nullable(Handler.class), eq(userHandle));
} }
} }

View File

@@ -37,7 +37,6 @@ import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settings.wrapper.IPackageManagerWrapper; import com.android.settings.wrapper.IPackageManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
@@ -84,7 +83,7 @@ public final class AppWithAdminGrantedPermissionsCounterTest {
@Mock @Mock
private IPackageManagerWrapper mPackageManagerService; private IPackageManagerWrapper mPackageManagerService;
@Mock @Mock
private DevicePolicyManagerWrapper mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
private int mAppCount = -1; private int mAppCount = -1;
private ApplicationInfo mApp1; private ApplicationInfo mApp1;
@@ -214,13 +213,13 @@ public final class AppWithAdminGrantedPermissionsCounterTest {
// * app5 uses install-time permissions. It was installed by the admin but did not request // * app5 uses install-time permissions. It was installed by the admin but did not request
// any of the permissions. It should not be counted. // any of the permissions. It should not be counted.
when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
| PackageManager.MATCH_ANY_USER, | PackageManager.MATCH_ANY_USER,
MAIN_USER_ID)).thenReturn(Arrays.asList(mApp1, mApp2, mApp3, mApp4, mApp5)); MAIN_USER_ID)).thenReturn(Arrays.asList(mApp1, mApp2, mApp3, mApp4, mApp5));
// The second user has one app installed. This app uses run-time permissions. It has been // The second user has one app installed. This app uses run-time permissions. It has been
// granted both permissions by the admin. It should be counted. // granted both permissions by the admin. It should be counted.
when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
MANAGED_PROFILE_ID)).thenReturn(Arrays.asList(mApp6)); MANAGED_PROFILE_ID)).thenReturn(Arrays.asList(mApp6));
// app3 and app5 were installed by enterprise policy. // app3 and app5 were installed by enterprise policy.
@@ -250,7 +249,7 @@ public final class AppWithAdminGrantedPermissionsCounterTest {
} }
private class AppWithAdminGrantedPermissionsCounterTestable private class AppWithAdminGrantedPermissionsCounterTestable
extends AppWithAdminGrantedPermissionsCounter { extends AppWithAdminGrantedPermissionsCounter {
private AppWithAdminGrantedPermissionsCounterTestable(String[] permissions) { private AppWithAdminGrantedPermissionsCounterTestable(String[] permissions) {
super(mContext, permissions, mPackageManager, mPackageManagerService, super(mContext, permissions, mPackageManager, mPackageManagerService,
mDevicePolicyManager); mDevicePolicyManager);

View File

@@ -34,7 +34,6 @@ import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settings.wrapper.IPackageManagerWrapper; import com.android.settings.wrapper.IPackageManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
@@ -81,7 +80,7 @@ public final class AppWithAdminGrantedPermissionsListerTest {
@Mock @Mock
private IPackageManagerWrapper mPackageManagerService; private IPackageManagerWrapper mPackageManagerService;
@Mock @Mock
private DevicePolicyManagerWrapper mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
private List<UserAppInfo> mAppList = Collections.emptyList(); private List<UserAppInfo> mAppList = Collections.emptyList();
@@ -109,14 +108,14 @@ public final class AppWithAdminGrantedPermissionsListerTest {
// * app5 uses install-time permissions. It was installed by the admin but did not request // * app5 uses install-time permissions. It was installed by the admin but did not request
// any of the permissions. It should not be listed. // any of the permissions. It should not be listed.
when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
| PackageManager.MATCH_ANY_USER, | PackageManager.MATCH_ANY_USER,
MAIN_USER_ID)).thenReturn(Arrays.asList( MAIN_USER_ID)).thenReturn(Arrays.asList(
buildInfo(APP_1_UID, APP_1, 0 /* flags */, Build.VERSION_CODES.M), buildInfo(APP_1_UID, APP_1, 0 /* flags */, Build.VERSION_CODES.M),
buildInfo(APP_2_UID, APP_2, 0 /* flags */, Build.VERSION_CODES.M), buildInfo(APP_2_UID, APP_2, 0 /* flags */, Build.VERSION_CODES.M),
buildInfo(APP_3_UID, APP_3, 0 /* flags */, Build.VERSION_CODES.LOLLIPOP), buildInfo(APP_3_UID, APP_3, 0 /* flags */, Build.VERSION_CODES.LOLLIPOP),
buildInfo(APP_4_UID, APP_4, 0 /* flags */, Build.VERSION_CODES.LOLLIPOP), buildInfo(APP_4_UID, APP_4, 0 /* flags */, Build.VERSION_CODES.LOLLIPOP),
buildInfo(APP_5_UID, APP_5, 0 /* flags */, Build.VERSION_CODES.LOLLIPOP))); buildInfo(APP_5_UID, APP_5, 0 /* flags */, Build.VERSION_CODES.LOLLIPOP)));
// Grant run-time permissions as appropriate. // Grant run-time permissions as appropriate.
when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION_1)) when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION_1))
@@ -164,9 +163,9 @@ public final class AppWithAdminGrantedPermissionsListerTest {
// The second user has one app installed. This app uses run-time permissions. It has been // The second user has one app installed. This app uses run-time permissions. It has been
// granted both permissions by the admin. It should be listed. // granted both permissions by the admin. It should be listed.
when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
MANAGED_PROFILE_ID)).thenReturn(Arrays.asList( MANAGED_PROFILE_ID)).thenReturn(Arrays.asList(
buildInfo(APP_6_UID, APP_6, 0 /* flags */, Build.VERSION_CODES.M))); buildInfo(APP_6_UID, APP_6, 0 /* flags */, Build.VERSION_CODES.M)));
// Grant run-time permissions as appropriate. // Grant run-time permissions as appropriate.
when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_6), anyObject())) when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_6), anyObject()))

View File

@@ -33,7 +33,6 @@ import android.os.UserManager;
import com.android.settings.testutils.ApplicationTestUtils; import com.android.settings.testutils.ApplicationTestUtils;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settings.wrapper.IPackageManagerWrapper; import com.android.settings.wrapper.IPackageManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
@@ -75,7 +74,7 @@ public final class ApplicationFeatureProviderImplTest {
@Mock @Mock
private IPackageManagerWrapper mPackageManagerService; private IPackageManagerWrapper mPackageManagerService;
@Mock @Mock
private DevicePolicyManagerWrapper mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
private ApplicationFeatureProvider mProvider; private ApplicationFeatureProvider mProvider;
@@ -258,16 +257,16 @@ public final class ApplicationFeatureProviderImplTest {
new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0))); new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0)));
when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
| PackageManager.MATCH_ANY_USER, | PackageManager.MATCH_ANY_USER,
MAIN_USER_ID)).thenReturn(Arrays.asList( MAIN_USER_ID)).thenReturn(Arrays.asList(
ApplicationTestUtils.buildInfo(APP_1_UID, APP_1, 0 /* flags */, ApplicationTestUtils.buildInfo(APP_1_UID, APP_1, 0 /* flags */,
Build.VERSION_CODES.M))); Build.VERSION_CODES.M)));
when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
MANAGED_PROFILE_ID)).thenReturn(Arrays.asList( MANAGED_PROFILE_ID)).thenReturn(Arrays.asList(
ApplicationTestUtils.buildInfo(APP_2_UID, APP_2, 0 /* flags */, ApplicationTestUtils.buildInfo(APP_2_UID, APP_2, 0 /* flags */,
Build.VERSION_CODES.LOLLIPOP))); Build.VERSION_CODES.LOLLIPOP)));
} }
private ResolveInfo createResolveInfo(String packageName) { private ResolveInfo createResolveInfo(String packageName) {

View File

@@ -17,7 +17,6 @@
package com.android.settings.applications.appinfo; package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.argThat;
@@ -28,6 +27,7 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -47,7 +47,6 @@ import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.widget.ActionButtonPreference; import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.ActionButtonPreferenceTest; import com.android.settings.widget.ActionButtonPreferenceTest;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.Utils; import com.android.settingslib.Utils;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
@@ -74,7 +73,7 @@ public class AppActionButtonPreferenceControllerTest {
@Mock @Mock
private UserManager mUserManager; private UserManager mUserManager;
@Mock @Mock
private DevicePolicyManagerWrapper mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
@Mock @Mock
private AppInfoDashboardFragment mFragment; private AppInfoDashboardFragment mFragment;
@Mock @Mock
@@ -108,7 +107,7 @@ public class AppActionButtonPreferenceControllerTest {
@Test @Test
public void getAvailabilityStatus_notInstantApp_shouldReturnAvailable() { public void getAvailabilityStatus_notInstantApp_shouldReturnAvailable() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false)); (InstantAppDataProvider) (i -> false));
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE); assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
} }
@@ -116,7 +115,7 @@ public class AppActionButtonPreferenceControllerTest {
@Test @Test
public void getAvailabilityStatus_isInstantApp_shouldReturnDisabled() { public void getAvailabilityStatus_isInstantApp_shouldReturnDisabled() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> true)); (InstantAppDataProvider) (i -> true));
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
} }
@@ -220,7 +219,7 @@ public class AppActionButtonPreferenceControllerTest {
@Test @Test
public void checkForceStop_isStateProtected_shouldDisableForceStop() { public void checkForceStop_isStateProtected_shouldDisableForceStop() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false)); (InstantAppDataProvider) (i -> false));
final String packageName = "Package1"; final String packageName = "Package1";
final PackageInfo packageInfo = new PackageInfo(); final PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = packageName; packageInfo.packageName = packageName;
@@ -228,7 +227,7 @@ public class AppActionButtonPreferenceControllerTest {
appInfo.uid = 42; appInfo.uid = 42;
appInfo.sourceDir = "source"; appInfo.sourceDir = "source";
final ApplicationsState.AppEntry appEntry = new ApplicationsState.AppEntry( final ApplicationsState.AppEntry appEntry = new ApplicationsState.AppEntry(
mContext, appInfo, 0); mContext, appInfo, 0);
when(mPackageManager.isPackageStateProtected(packageName, 0)).thenReturn(true); when(mPackageManager.isPackageStateProtected(packageName, 0)).thenReturn(true);
mController.checkForceStop(appEntry, packageInfo); mController.checkForceStop(appEntry, packageInfo);
@@ -278,7 +277,7 @@ public class AppActionButtonPreferenceControllerTest {
mController.checkForceStop(appEntry, packageInfo); mController.checkForceStop(appEntry, packageInfo);
verify(mContext).sendOrderedBroadcastAsUser(argThat(intent-> intent != null verify(mContext).sendOrderedBroadcastAsUser(argThat(intent -> intent != null
&& intent.getAction().equals(Intent.ACTION_QUERY_PACKAGE_RESTART)), && intent.getAction().equals(Intent.ACTION_QUERY_PACKAGE_RESTART)),
any(UserHandle.class), nullable(String.class), any(BroadcastReceiver.class), any(UserHandle.class), nullable(String.class), any(BroadcastReceiver.class),
nullable(Handler.class), anyInt(), nullable(String.class), nullable(Bundle.class)); nullable(Handler.class), anyInt(), nullable(String.class), nullable(Bundle.class));

View File

@@ -17,7 +17,8 @@
package com.android.settings.applications.appinfo; package com.android.settings.applications.appinfo;
import static com.android.settings.applications.appinfo.AppInfoDashboardFragment.ARG_PACKAGE_NAME; import static com.android.settings.applications.appinfo.AppInfoDashboardFragment.ARG_PACKAGE_NAME;
import static com.android.settings.applications.appinfo.AppInfoDashboardFragment.UNINSTALL_ALL_USERS_MENU; import static com.android.settings.applications.appinfo.AppInfoDashboardFragment
.UNINSTALL_ALL_USERS_MENU;
import static com.android.settings.applications.appinfo.AppInfoDashboardFragment.UNINSTALL_UPDATES; import static com.android.settings.applications.appinfo.AppInfoDashboardFragment.UNINSTALL_UPDATES;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@@ -31,6 +32,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@@ -45,7 +47,6 @@ import android.view.MenuItem;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider; import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
@@ -75,7 +76,7 @@ public final class AppInfoDashboardFragmentTest {
@Mock @Mock
private SettingsActivity mActivity; private SettingsActivity mActivity;
@Mock @Mock
private DevicePolicyManagerWrapper mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
@Mock @Mock
private PackageManager mPackageManager; private PackageManager mPackageManager;
@@ -249,7 +250,7 @@ public final class AppInfoDashboardFragmentTest {
@Test @Test
public void getNumberOfUserWithPackageInstalled_twoUsersInstalled_shouldReturnTwo() public void getNumberOfUserWithPackageInstalled_twoUsersInstalled_shouldReturnTwo()
throws PackageManager.NameNotFoundException{ throws PackageManager.NameNotFoundException {
final String packageName = "Package1"; final String packageName = "Package1";
final int userID1 = 1; final int userID1 = 1;
final int userID2 = 2; final int userID2 = 2;
@@ -273,7 +274,7 @@ public final class AppInfoDashboardFragmentTest {
@Test @Test
public void getNumberOfUserWithPackageInstalled_oneUserInstalled_shouldReturnOne() public void getNumberOfUserWithPackageInstalled_oneUserInstalled_shouldReturnOne()
throws PackageManager.NameNotFoundException{ throws PackageManager.NameNotFoundException {
final String packageName = "Package1"; final String packageName = "Package1";
final int userID1 = 1; final int userID1 = 1;
final int userID2 = 2; final int userID2 = 2;
@@ -311,7 +312,7 @@ public final class AppInfoDashboardFragmentTest {
@Test @Test
public void startAppInfoFragment_noCrashOnNullArgs() { public void startAppInfoFragment_noCrashOnNullArgs() {
final SettingsPreferenceFragment caller = mock(SettingsPreferenceFragment.class); final SettingsPreferenceFragment caller = mock(SettingsPreferenceFragment.class);
final SettingsActivity sa = mock (SettingsActivity.class); final SettingsActivity sa = mock(SettingsActivity.class);
when(caller.getActivity()).thenReturn(sa); when(caller.getActivity()).thenReturn(sa);
when(caller.getContext()).thenReturn(sa); when(caller.getContext()).thenReturn(sa);
final AppEntry appEntry = mock(AppEntry.class); final AppEntry appEntry = mock(AppEntry.class);
@@ -324,7 +325,7 @@ public final class AppInfoDashboardFragmentTest {
@Test @Test
public void startAppInfoFragment_includesNewAndOldArgs() { public void startAppInfoFragment_includesNewAndOldArgs() {
final SettingsPreferenceFragment caller = mock(SettingsPreferenceFragment.class); final SettingsPreferenceFragment caller = mock(SettingsPreferenceFragment.class);
final SettingsActivity sa = mock (SettingsActivity.class); final SettingsActivity sa = mock(SettingsActivity.class);
when(caller.getContext()).thenReturn(sa); when(caller.getContext()).thenReturn(sa);
final AppEntry appEntry = mock(AppEntry.class); final AppEntry appEntry = mock(AppEntry.class);
appEntry.info = mock(ApplicationInfo.class); appEntry.info = mock(ApplicationInfo.class);
@@ -339,10 +340,10 @@ public final class AppInfoDashboardFragmentTest {
verify(caller).startActivityForResult(intent.capture(), any(Integer.class)); verify(caller).startActivityForResult(intent.capture(), any(Integer.class));
assertThat(intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS) assertThat(intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
.containsKey("test")) .containsKey("test"))
.isTrue(); .isTrue();
assertThat(intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS) assertThat(intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
.containsKey(ARG_PACKAGE_NAME)) .containsKey(ARG_PACKAGE_NAME))
.isTrue(); .isTrue();
} }
} }

View File

@@ -110,7 +110,7 @@ public class AppMemoryPreferenceControllerTest {
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0); Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
assertThat(mController.getAvailabilityStatus()) assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING); .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
} }
@Test @Test

View File

@@ -25,12 +25,13 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.os.UserManager;
import android.util.Pair; import android.util.Pair;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.UserManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.junit.Before; import org.junit.Before;
@@ -52,7 +53,7 @@ public class PictureInPictureSettingsTest {
@Mock @Mock
private PackageManagerWrapper mPackageManager; private PackageManagerWrapper mPackageManager;
@Mock @Mock
private UserManagerWrapper mUserManager; private UserManager mUserManager;
private ArrayList<PackageInfo> mPrimaryUserPackages; private ArrayList<PackageInfo> mPrimaryUserPackages;
private ArrayList<PackageInfo> mProfileUserPackages; private ArrayList<PackageInfo> mProfileUserPackages;

View File

@@ -18,6 +18,8 @@ package com.android.settings.connecteddevice.usb;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.Answers.RETURNS_DEEP_STUBS;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -27,9 +29,10 @@ import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus; import android.hardware.usb.UsbPortStatus;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.os.UserHandle;
import android.os.UserManager;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.UserManagerWrapper;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -45,7 +48,7 @@ public class UsbBackendTest {
@Mock @Mock
private UsbManager mUsbManager; private UsbManager mUsbManager;
@Mock @Mock
private UserManagerWrapper mUserManagerWrapper; private UserManager mUserManager;
@Mock @Mock
private ConnectivityManager mConnectivityManager; private ConnectivityManager mConnectivityManager;
@Mock @Mock
@@ -68,7 +71,7 @@ public class UsbBackendTest {
@Test @Test
public void setDataRole_allRolesSupported_shouldSetDataRole() { public void setDataRole_allRolesSupported_shouldSetDataRole() {
final UsbBackend usbBackend = new UsbBackend(mContext, mUserManagerWrapper); final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
when(mUsbPortStatus when(mUsbPortStatus
.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE)) .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
@@ -91,7 +94,7 @@ public class UsbBackendTest {
@Test @Test
public void setDataRole_notAllRolesSupported_shouldSetDataAndPowerRole() { public void setDataRole_notAllRolesSupported_shouldSetDataAndPowerRole() {
final UsbBackend usbBackend = new UsbBackend(mContext, mUserManagerWrapper); final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
when(mUsbPortStatus when(mUsbPortStatus
.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE)) .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
@@ -109,7 +112,7 @@ public class UsbBackendTest {
@Test @Test
public void setPowerRole_allRolesSupported_shouldSetPowerRole() { public void setPowerRole_allRolesSupported_shouldSetPowerRole() {
final UsbBackend usbBackend = new UsbBackend(mContext, mUserManagerWrapper); final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
when(mUsbPortStatus when(mUsbPortStatus
.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE)) .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
@@ -133,7 +136,7 @@ public class UsbBackendTest {
@Test @Test
public void setPowerRole_notAllRolesSupported_shouldSetDataAndPowerRole() { public void setPowerRole_notAllRolesSupported_shouldSetDataAndPowerRole() {
final UsbBackend usbBackend = new UsbBackend(mContext, mUserManagerWrapper); final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
when(mUsbPortStatus when(mUsbPortStatus
.isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE)) .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
@@ -151,20 +154,26 @@ public class UsbBackendTest {
@Test @Test
public void areFunctionsSupported_fileTransferDisallowed_shouldReturnFalse() { public void areFunctionsSupported_fileTransferDisallowed_shouldReturnFalse() {
when(mUserManagerWrapper.isUsbFileTransferRestricted()).thenReturn(true); when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER))
when(mUserManagerWrapper.isUsbFileTransferRestrictedBySystem()).thenReturn(true); .thenReturn(true);
when(mUserManager.hasBaseUserRestriction(
eq(UserManager.DISALLOW_USB_FILE_TRANSFER), any(UserHandle.class)))
.thenReturn(true);
final UsbBackend usbBackend = new UsbBackend(mContext, mUserManagerWrapper); final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
assertThat(usbBackend.areFunctionsSupported(UsbManager.FUNCTION_MTP)).isFalse(); assertThat(usbBackend.areFunctionsSupported(UsbManager.FUNCTION_MTP)).isFalse();
} }
@Test @Test
public void areFunctionsSupported_fileTransferAllowed_shouldReturnTrue() { public void areFunctionsSupported_fileTransferAllowed_shouldReturnTrue() {
when(mUserManagerWrapper.isUsbFileTransferRestricted()).thenReturn(false); when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER))
when(mUserManagerWrapper.isUsbFileTransferRestrictedBySystem()).thenReturn(false); .thenReturn(false);
when(mUserManager.hasBaseUserRestriction(
eq(UserManager.DISALLOW_USB_FILE_TRANSFER), any(UserHandle.class)))
.thenReturn(false);
final UsbBackend usbBackend = new UsbBackend(mContext, mUserManagerWrapper); final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
assertThat(usbBackend.areFunctionsSupported(UsbManager.FUNCTION_MTP)).isTrue(); assertThat(usbBackend.areFunctionsSupported(UsbManager.FUNCTION_MTP)).isTrue();
} }

View File

@@ -21,27 +21,37 @@ import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_US
import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED; import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
import static com.android.settings.core.BasePreferenceController.UNAVAILABLE_UNKNOWN; import static com.android.settings.core.BasePreferenceController.UNAVAILABLE_UNKNOWN;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.content.Context;
import com.android.settings.slices.SliceData; import com.android.settings.slices.SliceData;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
public class BasePreferenceControllerTest { public class BasePreferenceControllerTest {
@Mock private final String KEY = "fake_key";
private BasePreferenceController mPreferenceController;
private Context mContext;
private FakeBasePreferenceController mPreferenceController;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application;
mPreferenceController = new FakeBasePreferenceController(mContext, KEY);
} }
@@ -57,70 +67,70 @@ public class BasePreferenceControllerTest {
@Test @Test
public void isAvailable_availableStatusAvailable_returnsTrue() { public void isAvailable_availableStatusAvailable_returnsTrue() {
when(mPreferenceController.getAvailabilityStatus()).thenReturn(AVAILABLE); mPreferenceController.setAvailability(AVAILABLE);
assertThat(mPreferenceController.isAvailable()).isTrue(); assertThat(mPreferenceController.isAvailable()).isTrue();
} }
@Test @Test
public void isAvailable_availableStatusUnsupported_returnsFalse() { public void isAvailable_availableStatusUnsupported_returnsFalse() {
when(mPreferenceController.getAvailabilityStatus()).thenReturn(DISABLED_UNSUPPORTED); mPreferenceController.setAvailability(DISABLED_UNSUPPORTED);
assertThat(mPreferenceController.isAvailable()).isFalse(); assertThat(mPreferenceController.isAvailable()).isFalse();
} }
@Test @Test
public void isAvailable_availableStatusDisabled_returnsFalse() { public void isAvailable_availableStatusDisabledForUser_returnsFalse() {
when(mPreferenceController.getAvailabilityStatus()).thenReturn(DISABLED_FOR_USER); mPreferenceController.setAvailability(DISABLED_FOR_USER);
assertThat(mPreferenceController.isAvailable()).isFalse(); assertThat(mPreferenceController.isAvailable()).isFalse();
} }
@Test @Test
public void isAvailable_availableStatusBlockedDependent_returnsFalse() { public void isAvailable_availableStatusBlockedDependent_returnsFalse() {
when(mPreferenceController.getAvailabilityStatus()).thenReturn(DISABLED_DEPENDENT_SETTING); mPreferenceController.setAvailability(DISABLED_DEPENDENT_SETTING);
assertThat(mPreferenceController.isAvailable()).isFalse(); assertThat(mPreferenceController.isAvailable()).isTrue();
} }
@Test @Test
public void isAvailable_availableStatusUnavailable_returnsFalse() { public void isAvailable_availableStatusUnavailable_returnsFalse() {
when(mPreferenceController.getAvailabilityStatus()).thenReturn(UNAVAILABLE_UNKNOWN); mPreferenceController.setAvailability(UNAVAILABLE_UNKNOWN);
assertThat(mPreferenceController.isAvailable()).isFalse(); assertThat(mPreferenceController.isAvailable()).isFalse();
} }
@Test @Test
public void isSupported_availableStatusAvailable_returnsTrue() { public void isSupported_availableStatusAvailable_returnsTrue() {
when(mPreferenceController.getAvailabilityStatus()).thenReturn(AVAILABLE); mPreferenceController.setAvailability(AVAILABLE);
assertThat(mPreferenceController.isSupported()).isTrue(); assertThat(mPreferenceController.isSupported()).isTrue();
} }
@Test @Test
public void isSupported_availableStatusUnsupported_returnsFalse() { public void isSupported_availableStatusUnsupported_returnsFalse() {
when(mPreferenceController.getAvailabilityStatus()).thenReturn(DISABLED_UNSUPPORTED); mPreferenceController.setAvailability(DISABLED_UNSUPPORTED);
assertThat(mPreferenceController.isSupported()).isFalse(); assertThat(mPreferenceController.isSupported()).isFalse();
} }
@Test @Test
public void isSupported_availableStatusDisabled_returnsTrue() { public void isSupported_availableStatusDisabledForUser_returnsTrue() {
when(mPreferenceController.getAvailabilityStatus()).thenReturn(DISABLED_FOR_USER); mPreferenceController.setAvailability(DISABLED_FOR_USER);
assertThat(mPreferenceController.isSupported()).isTrue(); assertThat(mPreferenceController.isSupported()).isTrue();
} }
@Test @Test
public void isSupported_availableStatusDependentSetting_returnsTrue() { public void isSupported_availableStatusDependentSetting_returnsTrue() {
when(mPreferenceController.getAvailabilityStatus()).thenReturn(DISABLED_DEPENDENT_SETTING); mPreferenceController.setAvailability(DISABLED_DEPENDENT_SETTING);
assertThat(mPreferenceController.isSupported()).isTrue(); assertThat(mPreferenceController.isSupported()).isTrue();
} }
@Test @Test
public void isSupported_availableStatusUnavailable_returnsTrue() { public void isSupported_availableStatusUnavailable_returnsTrue() {
when(mPreferenceController.getAvailabilityStatus()).thenReturn(UNAVAILABLE_UNKNOWN); mPreferenceController.setAvailability(UNAVAILABLE_UNKNOWN);
assertThat(mPreferenceController.isSupported()).isTrue(); assertThat(mPreferenceController.isSupported()).isTrue();
} }
@@ -129,4 +139,48 @@ public class BasePreferenceControllerTest {
public void getSliceType_shouldReturnIntent() { public void getSliceType_shouldReturnIntent() {
assertThat(mPreferenceController.getSliceType()).isEqualTo(SliceData.SliceType.INTENT); assertThat(mPreferenceController.getSliceType()).isEqualTo(SliceData.SliceType.INTENT);
} }
@Test
public void settingAvailable_disabledOnDisplayPreference_preferenceEnabled() {
final PreferenceScreen screen = mock(PreferenceScreen.class);
final Preference preference = new Preference(mContext);
preference.setEnabled(true);
when(screen.findPreference(anyString())).thenReturn(preference);
mPreferenceController.displayPreference(screen);
assertThat(preference.isEnabled()).isTrue();
}
@Test
public void disabledDependentSetting_disabledOnDisplayPreference_preferenceDisabled() {
final PreferenceScreen screen = mock(PreferenceScreen.class);
final Preference preference = new Preference(mContext);
preference.setEnabled(true);
when(screen.findPreference(anyString())).thenReturn(preference);
mPreferenceController.setAvailability(DISABLED_DEPENDENT_SETTING);
mPreferenceController.displayPreference(screen);
assertThat(preference.isEnabled()).isFalse();
}
private class FakeBasePreferenceController extends BasePreferenceController {
public int mAvailable;
public FakeBasePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mAvailable = AVAILABLE;
}
@Override
public int getAvailabilityStatus() {
return mAvailable;
}
public void setAvailability(int availability) {
mAvailable = availability;
}
}
} }

View File

@@ -26,13 +26,13 @@ import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.UserManager;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.PreferenceScreen;
import android.util.SparseArray; import android.util.SparseArray;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.UserManagerWrapper;
import com.android.settingslib.applications.StorageStatsSource; import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.drawable.UserIconDrawable; import com.android.settingslib.drawable.UserIconDrawable;
@@ -54,7 +54,7 @@ public class SecondaryUserControllerTest {
private static final String TEST_NAME = "Fred"; private static final String TEST_NAME = "Fred";
private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users"; private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users";
@Mock @Mock
private UserManagerWrapper mUserManager; private UserManager mUserManager;
@Mock @Mock
private PreferenceScreen mScreen; private PreferenceScreen mScreen;
@Mock @Mock

View File

@@ -35,7 +35,6 @@ import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings; import com.android.settings.SubSettings;
import com.android.settings.deviceinfo.StorageProfileFragment; import com.android.settings.deviceinfo.StorageProfileFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.UserManagerWrapper;
import com.android.settingslib.applications.StorageStatsSource; import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.drawable.UserIconDrawable; import com.android.settingslib.drawable.UserIconDrawable;
@@ -52,8 +51,6 @@ public class UserProfileControllerTest {
private static final String TEST_NAME = "Fred"; private static final String TEST_NAME = "Fred";
@Mock
private UserManagerWrapper mUserManager;
@Mock @Mock
private PreferenceScreen mScreen; private PreferenceScreen mScreen;
@@ -66,7 +63,7 @@ public class UserProfileControllerTest {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application); mContext = spy(RuntimeEnvironment.application);
mPrimaryProfile = new UserInfo(); mPrimaryProfile = new UserInfo();
mController = new UserProfileController(mContext, mPrimaryProfile, mUserManager, 0); mController = new UserProfileController(mContext, mPrimaryProfile, 0);
when(mScreen.getContext()).thenReturn(mContext); when(mScreen.getContext()).thenReturn(mContext);
mPrimaryProfile.name = TEST_NAME; mPrimaryProfile.name = TEST_NAME;
mPrimaryProfile.id = 10; mPrimaryProfile.id = 10;
@@ -96,7 +93,7 @@ public class UserProfileControllerTest {
final Intent intent = intentCaptor.getValue(); final Intent intent = intentCaptor.getValue();
assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName()); assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)) assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(StorageProfileFragment.class.getName()); .isEqualTo(StorageProfileFragment.class.getName());
} }
@Test @Test

View File

@@ -33,7 +33,7 @@ import android.provider.Settings;
import com.android.settings.TimeoutListPreference; import com.android.settings.TimeoutListPreference;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManagerWrapper; import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import org.junit.Before; import org.junit.Before;
@@ -50,7 +50,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = ShadowDevicePolicyManagerWrapper.class) @Config(shadows = ShadowDevicePolicyManager.class)
public class TimeoutPreferenceControllerTest { public class TimeoutPreferenceControllerTest {
private static final int TIMEOUT = 30; private static final int TIMEOUT = 30;
@@ -93,7 +93,7 @@ public class TimeoutPreferenceControllerTest {
final int profileUserId = UserHandle.myUserId(); final int profileUserId = UserHandle.myUserId();
final long timeout = 10000; final long timeout = 10000;
when(mUserManager.getProfiles(profileUserId)).thenReturn(Collections.emptyList()); when(mUserManager.getProfiles(profileUserId)).thenReturn(Collections.emptyList());
ShadowDevicePolicyManagerWrapper.setMaximumTimeToLock(profileUserId, timeout); ShadowDevicePolicyManager.getShadow().setMaximumTimeToLock(profileUserId, timeout);
mController.updateState(mPreference); mController.updateState(mPreference);
verify(mPreference).removeUnusableTimeouts(timeout, null); verify(mPreference).removeUnusableTimeouts(timeout, null);
@@ -104,7 +104,7 @@ public class TimeoutPreferenceControllerTest {
final int profileUserId = UserHandle.myUserId(); final int profileUserId = UserHandle.myUserId();
final long timeout = 100; final long timeout = 100;
when(mUserManager.getProfiles(profileUserId)).thenReturn(Collections.emptyList()); when(mUserManager.getProfiles(profileUserId)).thenReturn(Collections.emptyList());
ShadowDevicePolicyManagerWrapper.setMaximumTimeToLock(profileUserId, timeout); ShadowDevicePolicyManager.getShadow().setMaximumTimeToLock(profileUserId, timeout);
int userId = UserHandle.myUserId(); int userId = UserHandle.myUserId();
List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>(); List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
@@ -124,8 +124,8 @@ public class TimeoutPreferenceControllerTest {
ArgumentCaptor<EnforcedAdmin> adminCaptor = ArgumentCaptor.forClass(EnforcedAdmin.class); ArgumentCaptor<EnforcedAdmin> adminCaptor = ArgumentCaptor.forClass(EnforcedAdmin.class);
verify(mPreference, times(2)) verify(mPreference, times(2))
.removeUnusableTimeouts(longCaptor.capture(), adminCaptor.capture()); .removeUnusableTimeouts(longCaptor.capture(), adminCaptor.capture());
assertEquals(0, (long)longCaptor.getValue()); assertEquals(0, (long) longCaptor.getValue());
assertTrue(adminCaptor.getValue() != null); assertTrue(adminCaptor.getValue() != null);
} }
} }

View File

@@ -94,7 +94,7 @@ public class ActionDisabledByAdminDialogHelperTest {
mHelper.showAdminPolicies(admin, mActivity); mHelper.showAdminPolicies(admin, mActivity);
final Intent intent = mActivityShadow.getNextStartedActivity(); final Intent intent = mActivityShadow.getNextStartedActivity();
assertEquals(intent.getComponent(), new ComponentName(mActivity, assertEquals(intent.getComponent(), new ComponentName(mActivity,
Settings.DeviceAdminSettingsActivity.class.getName())); Settings.DeviceAdminSettingsActivity.class.getName()));
} }
@Test @Test
@@ -139,9 +139,7 @@ public class ActionDisabledByAdminDialogHelperTest {
@Test @Test
public void testSetAdminSupportDetails() { public void testSetAdminSupportDetails() {
final DevicePolicyManager dpm = RuntimeEnvironment.application.getSystemService( final ShadowDevicePolicyManager dpmShadow = ShadowDevicePolicyManager.getShadow();
DevicePolicyManager.class);
final ShadowDevicePolicyManager dpmShadow = Shadow.extract(dpm);
final UserManager userManager = RuntimeEnvironment.application.getSystemService( final UserManager userManager = RuntimeEnvironment.application.getSystemService(
UserManager.class); UserManager.class);
final ShadowUserManager userManagerShadow = Shadow.extract(userManager); final ShadowUserManager userManagerShadow = Shadow.extract(userManager);
@@ -165,9 +163,7 @@ public class ActionDisabledByAdminDialogHelperTest {
@Test @Test
public void testSetAdminSupportDetailsNotAdmin() { public void testSetAdminSupportDetailsNotAdmin() {
final DevicePolicyManager dpm = RuntimeEnvironment.application.getSystemService( final ShadowDevicePolicyManager dpmShadow = ShadowDevicePolicyManager.getShadow();
DevicePolicyManager.class);
final ShadowDevicePolicyManager dpmShadow = Shadow.extract(dpm);
final UserManager userManager = RuntimeEnvironment.application.getSystemService( final UserManager userManager = RuntimeEnvironment.application.getSystemService(
UserManager.class); UserManager.class);
final ShadowUserManager userManagerShadow = Shadow.extract(userManager); final ShadowUserManager userManagerShadow = Shadow.extract(userManager);

View File

@@ -21,6 +21,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset; import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@@ -36,7 +37,6 @@ import android.text.SpannableStringBuilder;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.ConnectivityManagerWrapper; import com.android.settings.wrapper.ConnectivityManagerWrapper;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
import org.junit.Before; import org.junit.Before;
@@ -68,7 +68,7 @@ public class EnterprisePrivacyFeatureProviderImplTest {
private List<UserInfo> mProfiles = new ArrayList<>(); private List<UserInfo> mProfiles = new ArrayList<>();
private @Mock Context mContext; private @Mock Context mContext;
private @Mock DevicePolicyManagerWrapper mDevicePolicyManager; private @Mock DevicePolicyManager mDevicePolicyManager;
private @Mock PackageManagerWrapper mPackageManagerWrapper; private @Mock PackageManagerWrapper mPackageManagerWrapper;
private @Mock PackageManager mPackageManager; private @Mock PackageManager mPackageManager;
private @Mock UserManager mUserManager; private @Mock UserManager mUserManager;

View File

@@ -34,6 +34,7 @@ import static org.mockito.Mockito.when;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.Application; import android.app.Application;
import android.app.Fragment; import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@@ -46,7 +47,6 @@ import com.android.settings.SettingsActivity;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.widget.ActionButtonPreference; import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.ActionButtonPreferenceTest; import com.android.settings.widget.ActionButtonPreferenceTest;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider; import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
@@ -87,7 +87,7 @@ public class AppButtonsPreferenceControllerTest {
@Mock @Mock
private PackageManager mPackageManger; private PackageManager mPackageManger;
@Mock @Mock
private DevicePolicyManagerWrapper mDpm; private DevicePolicyManager mDpm;
@Mock @Mock
private ActivityManager mAm; private ActivityManager mAm;
@Mock @Mock
@@ -367,7 +367,7 @@ public class AppButtonsPreferenceControllerTest {
* {@link ButtonActionDialogFragment.AppButtonsDialogListener} * {@link ButtonActionDialogFragment.AppButtonsDialogListener}
*/ */
public static class TestFragment extends Fragment public static class TestFragment extends Fragment
implements ButtonActionDialogFragment.AppButtonsDialogListener { implements ButtonActionDialogFragment.AppButtonsDialogListener {
@Override @Override
public void handleDialogClick(int type) { public void handleDialogClick(int type) {

View File

@@ -38,7 +38,6 @@ import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.SettingsShadowResources; import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.ShadowFragment; import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend; import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
import org.junit.Before; import org.junit.Before;
@@ -74,7 +73,7 @@ public class BackgroundActivityPreferenceControllerTest {
@Mock @Mock
private DevicePolicyManager mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
@Mock @Mock
private DevicePolicyManagerWrapper mDevicePolicyManagerWrapper; private DevicePolicyManager mDevicePolicyManagerWrapper;
@Mock(answer = Answers.RETURNS_DEEP_STUBS) @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private AdvancedPowerUsageDetail mFragment; private AdvancedPowerUsageDetail mFragment;
@Mock @Mock

View File

@@ -18,10 +18,16 @@ package com.android.settings.fuelgauge.batterytip;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.RuntimeEnvironment.application; import static org.robolectric.RuntimeEnvironment.application;
import android.app.job.JobInfo; import android.app.job.JobInfo;
import android.app.job.JobScheduler; import android.app.job.JobScheduler;
import android.content.Context;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -30,6 +36,7 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows; import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowJobScheduler; import org.robolectric.shadows.ShadowJobScheduler;
@@ -38,23 +45,39 @@ import java.util.concurrent.TimeUnit;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
public class AnomalyCleanupJobServiceTest { public class AnomalyCleanupJobServiceTest {
private Context mContext;
private JobScheduler mJobScheduler;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mJobScheduler = spy(mContext.getSystemService(JobScheduler.class));
when(mContext.getSystemService(JobScheduler.class)).thenReturn(mJobScheduler);
} }
@Test @Test
public void testScheduleCleanUp() { public void testScheduleCleanUp() {
AnomalyCleanupJobService.scheduleCleanUp(application); AnomalyCleanupJobService.scheduleCleanUp(mContext);
ShadowJobScheduler shadowJobScheduler = ShadowJobScheduler shadowJobScheduler =
Shadows.shadowOf(application.getSystemService(JobScheduler.class)); Shadows.shadowOf(mContext.getSystemService(JobScheduler.class));
List<JobInfo> pendingJobs = shadowJobScheduler.getAllPendingJobs(); List<JobInfo> pendingJobs = shadowJobScheduler.getAllPendingJobs();
assertEquals(1, pendingJobs.size()); assertEquals(1, pendingJobs.size());
JobInfo pendingJob = pendingJobs.get(0); JobInfo pendingJob = pendingJobs.get(0);
assertThat(pendingJob.getId()).isEqualTo(R.id.job_anomaly_clean_up); assertThat(pendingJob.getId()).isEqualTo(R.integer.job_anomaly_clean_up);
assertThat(pendingJob.getIntervalMillis()).isEqualTo(TimeUnit.DAYS.toMillis(1)); assertThat(pendingJob.getIntervalMillis()).isEqualTo(TimeUnit.DAYS.toMillis(1));
assertThat(pendingJob.isRequireDeviceIdle()).isTrue(); assertThat(pendingJob.isRequireDeviceIdle()).isTrue();
assertThat(pendingJob.isRequireCharging()).isTrue(); assertThat(pendingJob.isRequireCharging()).isTrue();
assertThat(pendingJob.isPersisted()).isTrue();
}
@Test
public void testScheduleCleanUp_invokeTwice_onlyScheduleOnce() {
AnomalyCleanupJobService.scheduleCleanUp(mContext);
AnomalyCleanupJobService.scheduleCleanUp(mContext);
verify(mJobScheduler, times(1)).schedule(any());
} }
} }

View File

@@ -25,7 +25,9 @@ import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.RuntimeEnvironment.application; import static org.robolectric.RuntimeEnvironment.application;
import android.app.StatsManager; import android.app.StatsManager;
@@ -43,6 +45,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows; import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowJobScheduler; import org.robolectric.shadows.ShadowJobScheduler;
@@ -57,12 +60,18 @@ public class AnomalyConfigJobServiceTest {
@Mock @Mock
private StatsManager mStatsManager; private StatsManager mStatsManager;
private Context mContext;
private JobScheduler mJobScheduler;
private AnomalyConfigJobService mJobService; private AnomalyConfigJobService mJobService;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mJobScheduler = spy(mContext.getSystemService(JobScheduler.class));
when(mContext.getSystemService(JobScheduler.class)).thenReturn(mJobScheduler);
mJobService = spy(new AnomalyConfigJobService()); mJobService = spy(new AnomalyConfigJobService());
doReturn(application.getSharedPreferences(AnomalyConfigJobService.PREF_DB, doReturn(application.getSharedPreferences(AnomalyConfigJobService.PREF_DB,
Context.MODE_PRIVATE)).when(mJobService).getSharedPreferences(anyString(), Context.MODE_PRIVATE)).when(mJobService).getSharedPreferences(anyString(),
@@ -71,18 +80,27 @@ public class AnomalyConfigJobServiceTest {
} }
@Test @Test
public void testScheduleCleanUp() { public void testScheduleConfigUpdate() {
AnomalyConfigJobService.scheduleConfigUpdate(application); AnomalyConfigJobService.scheduleConfigUpdate(mContext);
ShadowJobScheduler shadowJobScheduler = ShadowJobScheduler shadowJobScheduler =
Shadows.shadowOf(application.getSystemService(JobScheduler.class)); Shadows.shadowOf(mContext.getSystemService(JobScheduler.class));
List<JobInfo> pendingJobs = shadowJobScheduler.getAllPendingJobs(); List<JobInfo> pendingJobs = shadowJobScheduler.getAllPendingJobs();
assertEquals(1, pendingJobs.size()); assertEquals(1, pendingJobs.size());
JobInfo pendingJob = pendingJobs.get(0); JobInfo pendingJob = pendingJobs.get(0);
assertThat(pendingJob.getId()).isEqualTo(R.id.job_anomaly_config_update); assertThat(pendingJob.getId()).isEqualTo(R.integer.job_anomaly_config_update);
assertThat(pendingJob.getIntervalMillis()).isEqualTo(TimeUnit.DAYS.toMillis(1)); assertThat(pendingJob.getIntervalMillis()).isEqualTo(TimeUnit.DAYS.toMillis(1));
assertThat(pendingJob.isRequireDeviceIdle()).isTrue(); assertThat(pendingJob.isRequireDeviceIdle()).isTrue();
assertThat(pendingJob.isRequireCharging()).isTrue(); assertThat(pendingJob.isRequireCharging()).isTrue();
assertThat(pendingJob.isPersisted()).isTrue();
}
@Test
public void testScheduleConfigUpdate_invokeTwice_onlyScheduleOnce() {
AnomalyConfigJobService.scheduleConfigUpdate(mContext);
AnomalyConfigJobService.scheduleConfigUpdate(mContext);
verify(mJobScheduler, times(1)).schedule(any());
} }
@Test @Test

View File

@@ -113,7 +113,7 @@ public class AnomalyDetectionJobServiceTest {
assertThat(pendingJobs).hasSize(1); assertThat(pendingJobs).hasSize(1);
JobInfo pendingJob = pendingJobs.get(0); JobInfo pendingJob = pendingJobs.get(0);
assertThat(pendingJob.getId()).isEqualTo(R.id.job_anomaly_detection); assertThat(pendingJob.getId()).isEqualTo(R.integer.job_anomaly_detection);
assertThat(pendingJob.getMaxExecutionDelayMillis()) assertThat(pendingJob.getMaxExecutionDelayMillis())
.isEqualTo(TimeUnit.MINUTES.toMillis(30)); .isEqualTo(TimeUnit.MINUTES.toMillis(30));
} }

View File

@@ -76,9 +76,7 @@ public class NetworkDashboardFragmentTest {
public void testPrepareActionBar_networkResetShouldBeCreated() { public void testPrepareActionBar_networkResetShouldBeCreated() {
final NetworkResetActionMenuController resetController = final NetworkResetActionMenuController resetController =
mock(NetworkResetActionMenuController.class); mock(NetworkResetActionMenuController.class);
final PrivateDnsMenuController privateDnsController = mock(PrivateDnsMenuController.class);
ReflectionHelpers.setField(mFragment, "mNetworkResetController", resetController); ReflectionHelpers.setField(mFragment, "mNetworkResetController", resetController);
ReflectionHelpers.setField(mFragment, "mPrivateDnsMenuController", privateDnsController);
mFragment.onCreateOptionsMenu(null, null); mFragment.onCreateOptionsMenu(null, null);

View File

@@ -1,65 +0,0 @@
/*
* Copyright (C) 2017 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.network;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.FragmentManager;
import android.view.Menu;
import android.view.MenuItem;
import com.android.settings.R;
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;
@RunWith(SettingsRobolectricTestRunner.class)
public class PrivateDnsMenuControllerTest {
private static final int MENU_ID = 0;
private PrivateDnsMenuController mController;
@Mock
private Menu mMenu;
@Mock
private MenuItem mMenuItem;
@Mock
private FragmentManager mFragmentManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = new PrivateDnsMenuController(mFragmentManager, MENU_ID);
when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);
}
@Test
public void buildMenuItem_available_shouldAddToMenu() {
mController.buildMenuItem(mMenu);
verify(mMenu).add(0 /* groupId */, MENU_ID, 0 /* order */,
R.string.select_private_dns_configuration_title);
verify(mMenuItem).setOnMenuItemClickListener(any(MenuItem.OnMenuItemClickListener.class));
}
}

View File

@@ -1,117 +0,0 @@
/*
* Copyright (C) 2017 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.network;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.provider.Settings;
import android.widget.Button;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowHelpUtils;
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;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = ShadowHelpUtils.class)
public class PrivateDnsModeDialogFragmentTest {
private static final String HOST_NAME = "192.168.1.1";
private static final String INVALID_HOST_NAME = "...,";
private Context mContext;
private PrivateDnsModeDialogFragment mFragment;
private Button mSaveButton;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mSaveButton = new Button(mContext);
mFragment = spy(new PrivateDnsModeDialogFragment());
doReturn(mContext).when(mFragment).getContext();
mFragment.onCreateDialog(null);
mFragment.mSaveButton = mSaveButton;
}
@Test
public void testOnCheckedChanged_dnsModeOff_disableEditText() {
mFragment.onCheckedChanged(null, R.id.private_dns_mode_off);
assertThat(mFragment.mMode).isEqualTo(PRIVATE_DNS_MODE_OFF);
assertThat(mFragment.mEditText.isEnabled()).isFalse();
}
@Test
public void testOnCheckedChanged_dnsModeOpportunistic_disableEditText() {
mFragment.onCheckedChanged(null, R.id.private_dns_mode_opportunistic);
assertThat(mFragment.mMode).isEqualTo(PRIVATE_DNS_MODE_OPPORTUNISTIC);
assertThat(mFragment.mEditText.isEnabled()).isFalse();
}
@Test
public void testOnCheckedChanged_dnsModeProvider_enableEditText() {
mFragment.onCheckedChanged(null, R.id.private_dns_mode_provider);
assertThat(mFragment.mMode).isEqualTo(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
assertThat(mFragment.mEditText.isEnabled()).isTrue();
}
@Test
public void testOnCreateDialog_containsCorrectData() {
Settings.Global.putString(mContext.getContentResolver(),
PrivateDnsModeDialogFragment.MODE_KEY, PRIVATE_DNS_MODE_OPPORTUNISTIC);
Settings.Global.putString(mContext.getContentResolver(),
PrivateDnsModeDialogFragment.HOSTNAME_KEY, HOST_NAME);
mFragment.onCreateDialog(null);
assertThat(mFragment.mEditText.getText().toString()).isEqualTo(HOST_NAME);
assertThat(mFragment.mRadioGroup.getCheckedRadioButtonId()).isEqualTo(
R.id.private_dns_mode_opportunistic);
}
@Test
public void testOnCheckedChanged_switchMode_saveButtonHasCorrectState() {
// Set invalid hostname
mFragment.mEditText.setText(INVALID_HOST_NAME);
mFragment.onCheckedChanged(null, R.id.private_dns_mode_opportunistic);
assertThat(mSaveButton.isEnabled()).isTrue();
mFragment.onCheckedChanged(null, R.id.private_dns_mode_provider);
assertThat(mSaveButton.isEnabled()).isFalse();
mFragment.onCheckedChanged(null, R.id.private_dns_mode_off);
assertThat(mSaveButton.isEnabled()).isTrue();
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) 2017 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.network;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.Context;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import com.android.settings.R;
import com.android.settingslib.CustomDialogPreference.CustomPreferenceDialogFragment;
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.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
public class PrivateDnsModeDialogPreferenceTest {
private static final String HOST_NAME = "dns.example.com";
private static final String INVALID_HOST_NAME = "...,";
private PrivateDnsModeDialogPreference mPreference;
private Context mContext;
private Button mSaveButton;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mSaveButton = new Button(mContext);
final CustomPreferenceDialogFragment fragment = mock(CustomPreferenceDialogFragment.class);
final AlertDialog dialog = mock(AlertDialog.class);
when(fragment.getDialog()).thenReturn(dialog);
when(dialog.getButton(anyInt())).thenReturn(mSaveButton);
mPreference = new PrivateDnsModeDialogPreference(mContext);
ReflectionHelpers.setField(mPreference, "mFragment", fragment);
final LayoutInflater inflater = LayoutInflater.from(mContext);
final View view = inflater.inflate(R.layout.private_dns_mode_dialog,
new LinearLayout(mContext), false);
mPreference.onBindDialogView(view);
}
@Test
public void testOnCheckedChanged_dnsModeOff_disableEditText() {
mPreference.onCheckedChanged(null, R.id.private_dns_mode_off);
assertThat(mPreference.mMode).isEqualTo(PRIVATE_DNS_MODE_OFF);
assertThat(mPreference.mEditText.isEnabled()).isFalse();
}
@Test
public void testOnCheckedChanged_dnsModeOpportunistic_disableEditText() {
mPreference.onCheckedChanged(null, R.id.private_dns_mode_opportunistic);
assertThat(mPreference.mMode).isEqualTo(PRIVATE_DNS_MODE_OPPORTUNISTIC);
assertThat(mPreference.mEditText.isEnabled()).isFalse();
}
@Test
public void testOnCheckedChanged_dnsModeProvider_enableEditText() {
mPreference.onCheckedChanged(null, R.id.private_dns_mode_provider);
assertThat(mPreference.mMode).isEqualTo(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
assertThat(mPreference.mEditText.isEnabled()).isTrue();
}
@Test
public void testOnBindDialogView_containsCorrectData() {
Settings.Global.putString(mContext.getContentResolver(),
PrivateDnsModeDialogPreference.MODE_KEY, PRIVATE_DNS_MODE_OPPORTUNISTIC);
Settings.Global.putString(mContext.getContentResolver(),
PrivateDnsModeDialogPreference.HOSTNAME_KEY, HOST_NAME);
final LayoutInflater inflater = LayoutInflater.from(mContext);
final View view = inflater.inflate(R.layout.private_dns_mode_dialog,
new LinearLayout(mContext), false);
mPreference.onBindDialogView(view);
assertThat(mPreference.mEditText.getText().toString()).isEqualTo(HOST_NAME);
assertThat(mPreference.mRadioGroup.getCheckedRadioButtonId()).isEqualTo(
R.id.private_dns_mode_opportunistic);
}
@Test
public void testOnCheckedChanged_switchMode_saveButtonHasCorrectState() {
// Set invalid hostname
mPreference.mEditText.setText(INVALID_HOST_NAME);
mPreference.onCheckedChanged(null, R.id.private_dns_mode_opportunistic);
assertThat(mSaveButton.isEnabled()).isTrue();
mPreference.onCheckedChanged(null, R.id.private_dns_mode_provider);
assertThat(mSaveButton.isEnabled()).isFalse();
mPreference.onCheckedChanged(null, R.id.private_dns_mode_off);
assertThat(mSaveButton.isEnabled()).isTrue();
}
}

View File

@@ -34,7 +34,7 @@ import com.android.settings.TimeoutListPreference;
import com.android.settings.security.trustagent.TrustAgentManager; import com.android.settings.security.trustagent.TrustAgentManager;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManagerWrapper; import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -47,7 +47,7 @@ import org.robolectric.annotation.Config;
import java.util.Collections; import java.util.Collections;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = ShadowDevicePolicyManagerWrapper.class) @Config(shadows = ShadowDevicePolicyManager.class)
public class LockAfterTimeoutPreferenceControllerTest { public class LockAfterTimeoutPreferenceControllerTest {
private static final int TEST_USER_ID = 0; private static final int TEST_USER_ID = 0;
@@ -120,11 +120,11 @@ public class LockAfterTimeoutPreferenceControllerTest {
when(um.getProfiles(userId)).thenReturn(Collections.emptyList()); when(um.getProfiles(userId)).thenReturn(Collections.emptyList());
// Fake list of timeout values. // Fake list of timeout values.
when(mPreference.getEntries()).thenReturn(new CharSequence[] {"10"} ); when(mPreference.getEntries()).thenReturn(new CharSequence[] {"10"});
when(mPreference.getEntryValues()).thenReturn(new CharSequence[] {"10000"} ); when(mPreference.getEntryValues()).thenReturn(new CharSequence[] {"10000"});
Settings.System.putInt(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, displayTimeout); Settings.System.putInt(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, displayTimeout);
ShadowDevicePolicyManagerWrapper.setMaximumTimeToLock(userId, adminTimeout); ShadowDevicePolicyManager.getShadow().setMaximumTimeToLock(userId, adminTimeout);
mController.updateState(mPreference); mController.updateState(mPreference);

View File

@@ -2,33 +2,35 @@ package com.android.settings.testutils.shadow;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.ComponentName; import android.content.ComponentName;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements; import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import org.robolectric.shadow.api.Shadow;
/**
* This shadow if using {@link ShadowDevicePolicyManagerWrapper} is not possible.
*/
@Implements(DevicePolicyManager.class) @Implements(DevicePolicyManager.class)
public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDevicePolicyManager { public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDevicePolicyManager {
private final Map<Integer, Long> mProfileTimeouts = new HashMap<>();
private Map<Integer, CharSequence> mSupportMessagesMap = new HashMap<>(); private Map<Integer, CharSequence> mSupportMessagesMap = new HashMap<>();
private boolean mIsAdminActiveAsUser = false; private boolean mIsAdminActiveAsUser = false;
ComponentName mDeviceOwnerComponentName; ComponentName mDeviceOwnerComponentName;
private int mDeviceOwnerUserId = -1;
public void setShortSupportMessageForUser(ComponentName admin, int userHandle, String message) { public void setShortSupportMessageForUser(ComponentName admin, int userHandle, String message) {
mSupportMessagesMap.put(Objects.hash(admin, userHandle), message); mSupportMessagesMap.put(Objects.hash(admin, userHandle), message);
} }
@Implementation @Implementation
public @Nullable CharSequence getShortSupportMessageForUser(@NonNull ComponentName admin, public @Nullable
CharSequence getShortSupportMessageForUser(@NonNull ComponentName admin,
int userHandle) { int userHandle) {
return mSupportMessagesMap.get(Objects.hash(admin, userHandle)); return mSupportMessagesMap.get(Objects.hash(admin, userHandle));
} }
@@ -38,20 +40,39 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev
return mIsAdminActiveAsUser; return mIsAdminActiveAsUser;
} }
@Implementation
public int getDeviceOwnerUserId() {
return mDeviceOwnerUserId;
}
@Implementation
public long getMaximumTimeToLock(ComponentName admin, @UserIdInt int userHandle) {
return mProfileTimeouts.getOrDefault(userHandle, 0L);
}
@Implementation
public ComponentName getDeviceOwnerComponentOnAnyUser() {
return mDeviceOwnerComponentName;
}
public void setIsAdminActiveAsUser(boolean active) { public void setIsAdminActiveAsUser(boolean active) {
mIsAdminActiveAsUser = active; mIsAdminActiveAsUser = active;
} }
public static ShadowDevicePolicyManager getShadow() { public void setDeviceOwnerUserId(int id) {
return (ShadowDevicePolicyManager) Shadow.extract( mDeviceOwnerUserId = id;
RuntimeEnvironment.application.getSystemService(DevicePolicyManager.class));
} }
public ComponentName getDeviceOwnerComponentOnAnyUser() { public void setMaximumTimeToLock(@UserIdInt int userHandle, Long timeout) {
return mDeviceOwnerComponentName; mProfileTimeouts.put(userHandle, timeout);
} }
public void setDeviceOwnerComponentOnAnyUser(ComponentName admin) { public void setDeviceOwnerComponentOnAnyUser(ComponentName admin) {
mDeviceOwnerComponentName = admin; mDeviceOwnerComponentName = admin;
} }
public static ShadowDevicePolicyManager getShadow() {
return (ShadowDevicePolicyManager) Shadow.extract(
RuntimeEnvironment.application.getSystemService(DevicePolicyManager.class));
}
} }

View File

@@ -1,65 +0,0 @@
/*
* Copyright (C) 2017 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.shadow;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.HashMap;
import java.util.Map;
/**
* Shadow for {@link DevicePolicyManagerWrapper} to allow stubbing hidden methods.
*/
@Implements(DevicePolicyManagerWrapper.class)
public class ShadowDevicePolicyManagerWrapper {
private static ComponentName deviceOComponentName = null;
private static int deviceOwnerUserId = -1;
private static final Map<Integer, Long> profileTimeouts = new HashMap<>();
@Implementation
public ComponentName getDeviceOwnerComponentOnAnyUser() {
return deviceOComponentName;
}
@Implementation
public int getDeviceOwnerUserId() {
return deviceOwnerUserId;
}
@Implementation
public long getMaximumTimeToLock(ComponentName admin, @UserIdInt int userHandle) {
return profileTimeouts.getOrDefault(userHandle, 0L);
}
public static void setDeviceOComponentName(ComponentName deviceOComponentName) {
ShadowDevicePolicyManagerWrapper.deviceOComponentName = deviceOComponentName;
}
public static void setDeviceOwnerUserId(int deviceOwnerUserId) {
ShadowDevicePolicyManagerWrapper.deviceOwnerUserId = deviceOwnerUserId;
}
public static void setMaximumTimeToLock(@UserIdInt int userHandle, Long timeout) {
profileTimeouts.put(userHandle, timeout);
}
}

View File

@@ -20,15 +20,15 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf; import static org.robolectric.Shadows.shadowOf;
import android.app.WallpaperManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import com.android.settings.SubSettings; import com.android.settings.SubSettings;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.WallpaperManagerWrapper;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -40,6 +40,7 @@ import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements; import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
import org.robolectric.shadows.ShadowActivity; import org.robolectric.shadows.ShadowActivity;
import org.robolectric.shadows.ShadowPackageManager; import org.robolectric.shadows.ShadowPackageManager;
@@ -59,10 +60,15 @@ public class WallpaperSuggestionActivityTest {
mController = Robolectric.buildActivity(WallpaperSuggestionActivity.class); mController = Robolectric.buildActivity(WallpaperSuggestionActivity.class);
} }
@After
public void tearDown() {
ShadowWallpaperManager.reset();
}
@Test @Test
public void launch_primarySuggestionActivityDoesNotExist_shouldFallback() { public void launch_primarySuggestionActivityDoesNotExist_shouldFallback() {
ShadowPackageManager packageManager = ShadowPackageManager packageManager =
shadowOf(RuntimeEnvironment.application.getPackageManager()); shadowOf(RuntimeEnvironment.application.getPackageManager());
packageManager.removePackage("com.android.settings"); packageManager.removePackage("com.android.settings");
ShadowActivity activity = shadowOf(mController.setup().get()); ShadowActivity activity = shadowOf(mController.setup().get());
@@ -74,32 +80,34 @@ public class WallpaperSuggestionActivityTest {
} }
@Test @Test
public void wallpaperServiceEnabled_no_shouldReturnFalse() { public void wallpaperServiceEnabled_no_shouldReturnTrue() {
when(mContext.getResources()).thenReturn(mResources); when(mContext.getResources()).thenReturn(mResources);
when(mResources.getBoolean(com.android.internal.R.bool.config_enableWallpaperService)) when(mResources.getBoolean(com.android.internal.R.bool.config_enableWallpaperService))
.thenReturn(false); .thenReturn(false);
assertThat(WallpaperSuggestionActivity.isSuggestionComplete(mContext)).isFalse();
}
@Test
@Config(shadows = WallpaperSuggestionActivityTest.ShadowWallpaperManagerWrapper.class)
public void hasWallpaperSet_no_shouldReturnFalse() {
ShadowWallpaperManagerWrapper.setWallpaperId(0);
assertThat(WallpaperSuggestionActivity.isSuggestionComplete(mContext)).isFalse();
}
@Test
@Config(shadows = WallpaperSuggestionActivityTest.ShadowWallpaperManagerWrapper.class)
public void hasWallpaperSet_yes_shouldReturnTrue() {
ShadowWallpaperManagerWrapper.setWallpaperId(100);
assertThat(WallpaperSuggestionActivity.isSuggestionComplete(mContext)).isTrue(); assertThat(WallpaperSuggestionActivity.isSuggestionComplete(mContext)).isTrue();
} }
@Implements(WallpaperManagerWrapper.class) @Test
public static class ShadowWallpaperManagerWrapper { @Config(shadows = ShadowWallpaperManager.class)
public void hasWallpaperSet_no_shouldReturnFalse() {
ShadowWallpaperManager.setWallpaperId(0);
assertThat(WallpaperSuggestionActivity.isSuggestionComplete(RuntimeEnvironment.application))
.isFalse();
}
@Test
@Config(shadows = ShadowWallpaperManager.class)
public void hasWallpaperSet_yes_shouldReturnTrue() {
ShadowWallpaperManager.setWallpaperId(100);
assertThat(WallpaperSuggestionActivity.isSuggestionComplete(RuntimeEnvironment.application))
.isTrue();
}
@Implements(WallpaperManager.class)
public static class ShadowWallpaperManager {
private static int sWallpaperId; private static int sWallpaperId;
@@ -107,13 +115,11 @@ public class WallpaperSuggestionActivityTest {
sWallpaperId = id; sWallpaperId = id;
} }
@Resetter
public static void reset() { public static void reset() {
sWallpaperId = 0; sWallpaperId = 0;
} }
public void __constructor__(Context context) {
}
@Implementation @Implementation
public boolean isWallpaperServiceEnabled() { public boolean isWallpaperServiceEnabled() {
return true; return true;

View File

@@ -63,7 +63,7 @@ import com.android.settings.R;
import com.android.settings.applications.LayoutPreference; import com.android.settings.applications.LayoutPreference;
import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowBidiFormatter; import com.android.settings.testutils.shadow.ShadowBidiFormatter;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManagerWrapper; import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController; import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.testutils.shadow.ShadowPackageManagerWrapper; import com.android.settings.testutils.shadow.ShadowPackageManagerWrapper;
import com.android.settings.widget.ActionButtonPreference; import com.android.settings.widget.ActionButtonPreference;
@@ -96,10 +96,10 @@ import java.util.stream.Collectors;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = { @Config(shadows = {
ShadowDevicePolicyManagerWrapper.class, ShadowDevicePolicyManager.class,
ShadowEntityHeaderController.class, ShadowEntityHeaderController.class,
ShadowPackageManagerWrapper.class, ShadowPackageManagerWrapper.class,
ShadowBidiFormatter.class ShadowBidiFormatter.class
}) })
public class WifiDetailPreferenceControllerTest { public class WifiDetailPreferenceControllerTest {
@@ -372,7 +372,7 @@ public class WifiDetailPreferenceControllerTest {
mController.onPause(); mController.onPause();
verify(mockConnectivityManager, times(1)) verify(mockConnectivityManager, times(1))
.unregisterNetworkCallback(mCallbackCaptor.getValue()); .unregisterNetworkCallback(mCallbackCaptor.getValue());
} }
@Test @Test
@@ -469,16 +469,16 @@ public class WifiDetailPreferenceControllerTest {
@Test @Test
public void dnsServersPref_shouldHaveDetailTextSet() throws UnknownHostException { public void dnsServersPref_shouldHaveDetailTextSet() throws UnknownHostException {
mLinkProperties.addDnsServer(InetAddress.getByAddress(new byte[]{8,8,4,4})); mLinkProperties.addDnsServer(InetAddress.getByAddress(new byte[] {8, 8, 4, 4}));
mLinkProperties.addDnsServer(InetAddress.getByAddress(new byte[]{8,8,8,8})); mLinkProperties.addDnsServer(InetAddress.getByAddress(new byte[] {8, 8, 8, 8}));
mLinkProperties.addDnsServer(Constants.IPV6_DNS); mLinkProperties.addDnsServer(Constants.IPV6_DNS);
displayAndResume(); displayAndResume();
verify(mockDnsPref).setDetailText( verify(mockDnsPref).setDetailText(
"8.8.4.4\n" + "8.8.4.4\n" +
"8.8.8.8\n" + "8.8.8.8\n" +
Constants.IPV6_DNS.getHostAddress()); Constants.IPV6_DNS.getHostAddress());
} }
@Test @Test
@@ -591,8 +591,8 @@ public class WifiDetailPreferenceControllerTest {
updateLinkProperties(lp); updateLinkProperties(lp);
inOrder.verify(mockDnsPref).setDetailText( inOrder.verify(mockDnsPref).setDetailText(
Constants.IPV6_DNS.getHostAddress() + "\n" + Constants.IPV6_DNS.getHostAddress() + "\n" +
Constants.IPV4_DNS1.getHostAddress() + "\n" + Constants.IPV4_DNS1.getHostAddress() + "\n" +
Constants.IPV4_DNS2.getHostAddress()); Constants.IPV4_DNS2.getHostAddress());
inOrder.verify(mockDnsPref).setVisible(true); inOrder.verify(mockDnsPref).setVisible(true);
} }
@@ -693,8 +693,8 @@ public class WifiDetailPreferenceControllerTest {
mockWifiConfig.creatorUid = doUid; mockWifiConfig.creatorUid = doUid;
ComponentName doComponent = new ComponentName(doPackage, "some.Class"); ComponentName doComponent = new ComponentName(doPackage, "some.Class");
ShadowPackageManagerWrapper.setPackageUidAsUser(doPackage, doUserId, doUid); ShadowPackageManagerWrapper.setPackageUidAsUser(doPackage, doUserId, doUid);
ShadowDevicePolicyManagerWrapper.setDeviceOComponentName(doComponent); ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(doComponent);
ShadowDevicePolicyManagerWrapper.setDeviceOwnerUserId(doUserId); ShadowDevicePolicyManager.getShadow().setDeviceOwnerUserId(doUserId);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 1); Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 1);
@@ -779,7 +779,7 @@ public class WifiDetailPreferenceControllerTest {
displayAndResume(); displayAndResume();
List <Preference> addrs = mIpv6AddressCaptor.getAllValues(); List<Preference> addrs = mIpv6AddressCaptor.getAllValues();
String expectedAddresses = String.join("\n", String expectedAddresses = String.join("\n",
asString(Constants.IPV6_LINKLOCAL), asString(Constants.IPV6_LINKLOCAL),
@@ -840,6 +840,7 @@ public class WifiDetailPreferenceControllerTest {
verify(mockAccessPoint, times(2)).getLevel(); verify(mockAccessPoint, times(2)).getLevel();
verify(mockIconInjector, times(1)).getIcon(anyInt()); verify(mockIconInjector, times(1)).getIcon(anyInt());
} }
@Test @Test
public void testRefreshRssiViews_shouldUpdateOnLevelChange() { public void testRefreshRssiViews_shouldUpdateOnLevelChange() {
displayAndResume(); displayAndResume();

View File

@@ -17,7 +17,6 @@
package com.android.settings.deviceinfo.storage; package com.android.settings.deviceinfo.storage;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
@@ -31,11 +30,11 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.net.TrafficStats; import android.net.TrafficStats;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager;
import android.support.test.filters.SmallTest; import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.AndroidJUnit4;
import android.util.SparseArray; import android.util.SparseArray;
import com.android.settings.wrapper.UserManagerWrapper;
import com.android.settingslib.applications.StorageStatsSource; import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.wrapper.PackageManagerWrapper; import com.android.settingslib.wrapper.PackageManagerWrapper;
@@ -65,7 +64,7 @@ public class StorageAsyncLoaderTest {
@Mock @Mock
private PackageManagerWrapper mPackageManager; private PackageManagerWrapper mPackageManager;
@Mock @Mock
private UserManagerWrapper mUserManager; private UserManager mUserManager;
private List<ApplicationInfo> mInfo = new ArrayList<>(); private List<ApplicationInfo> mInfo = new ArrayList<>();
private List<UserInfo> mUsers; private List<UserInfo> mUsers;