Merge "Add summary with accessibility timeout item"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1b4304b..c5e512e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -114,11 +114,12 @@
<uses-library android:name="org.apache.http.legacy" />
<!-- Settings -->
+ <!-- TODO(b/118444000): Remove this. -->
<activity android:name="SettingsActivity"
- android:label="@string/settings_label_launcher"
- android:launchMode="singleTask">
+ android:label="@string/settings_label_launcher"
+ android:launchMode="singleTask">
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
- android:value="true" />
+ android:value="true" />
</activity>
<activity android:name=".homepage.SettingsHomepageActivity"
@@ -3043,7 +3044,17 @@
</provider>
<activity
- android:name=".wifi.dpp.WifiDppConfiguratorActivity"/>
+ android:name=".wifi.dpp.WifiDppConfiguratorActivity">
+ <intent-filter>
+ <action android:name="android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER"/>
+ <action android:name="android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR"/>
+ <action android:name="android.settings.WIFI_DPP_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".homepage.contextualcards.ContextualCardFeedbackDialog"
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
<!-- This is the longest AndroidManifest.xml ever. -->
</application>
</manifest>
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index eb2e730..787c559 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -2,6 +2,18 @@
<issues format="4">
<issue
+ id="LintError"
+ severity="Error"
+ message="No `.class` files were found in project ".", so none of the classfile based checks could be run. Does the project need to be built first?"
+ category="Lint"
+ priority="10"
+ summary="Lint Failure"
+ explanation="This issue type represents a problem running lint itself. Examples include failure to find bytecode for source files (which means certain detectors could not be run), parsing errors in lint configuration files, etc.
These errors are not errors in your own code, but they are shown to make it clear that some checks were not completed.">
+ <location
+ file="."/>
+ </issue>
+
+ <issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
@@ -169,12 +181,12 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="material_empty_color_light">#FFCED7DB</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" <color name="homepage_accessibility_background">#783BE5</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="res/values/colors.xml"
+ file="res/values-night/colors.xml"
line="22"
- column="5"/>
+ column="3"/>
</issue>
<issue
@@ -189,7 +201,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="24"
+ line="22"
column="5"/>
</issue>
@@ -201,11 +213,27 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+ errorLine1=" <color name="homepage_support_background">#3F5FBD</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values-night/colors.xml"
+ line="23"
+ column="3"/>
+ </issue>
+
+ <issue
+ id="HardCodedColor"
+ severity="Error"
+ message="Avoid using hardcoded color"
+ category="Correctness"
+ priority="4"
+ summary="Using hardcoded color"
+ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" <color name="crypt_keeper_clock_background">#ff9a9a9a</color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="26"
+ line="24"
column="5"/>
</issue>
@@ -221,7 +249,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="27"
+ line="25"
column="5"/>
</issue>
@@ -237,7 +265,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="28"
+ line="26"
column="5"/>
</issue>
@@ -253,7 +281,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="29"
+ line="27"
column="5"/>
</issue>
@@ -269,23 +297,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="31"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="setup_lock_pattern_view_regular_color_dark">#ffbdbdbd</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="33"
+ line="29"
column="5"/>
</issue>
@@ -301,7 +313,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="35"
+ line="32"
column="5"/>
</issue>
@@ -317,7 +329,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="37"
+ line="34"
column="5"/>
</issue>
@@ -333,7 +345,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="38"
+ line="35"
column="5"/>
</issue>
@@ -349,7 +361,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="39"
+ line="36"
column="5"/>
</issue>
@@ -365,7 +377,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="41"
+ line="38"
column="5"/>
</issue>
@@ -381,7 +393,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="42"
+ line="39"
column="5"/>
</issue>
@@ -397,7 +409,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="44"
+ line="41"
column="5"/>
</issue>
@@ -413,7 +425,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="49"
+ line="46"
column="5"/>
</issue>
@@ -429,7 +441,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="50"
+ line="47"
column="5"/>
</issue>
@@ -445,7 +457,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="52"
+ line="49"
column="5"/>
</issue>
@@ -461,23 +473,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="53"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="wifi_divider">#ffe0e0e0</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="55"
+ line="50"
column="5"/>
</issue>
@@ -493,103 +489,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="58"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="voice_interaction_highlight">#33b5e5</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="59"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="memory_normal">#ff009587</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="61"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="memory_moderate">#ffF3B300</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="62"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="memory_low">#ffff9700</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="63"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="memory_critical">#ffff5621</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="64"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="memory_avg_use">#ff384248</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="66"
+ line="54"
column="5"/>
</issue>
@@ -605,39 +505,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="69"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="importance_icon_tint">#8a000000</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="71"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="importance_disabled_tint">#4d000000</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="72"
+ line="57"
column="5"/>
</issue>
@@ -653,7 +521,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="75"
+ line="60"
column="5"/>
</issue>
@@ -669,7 +537,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="76"
+ line="61"
column="5"/>
</issue>
@@ -685,7 +553,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="77"
+ line="62"
column="5"/>
</issue>
@@ -701,7 +569,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="78"
+ line="63"
column="5"/>
</issue>
@@ -717,7 +585,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="79"
+ line="64"
column="5"/>
</issue>
@@ -733,7 +601,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="82"
+ line="66"
column="5"/>
</issue>
@@ -749,7 +617,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="83"
+ line="67"
column="5"/>
</issue>
@@ -765,7 +633,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="84"
+ line="68"
column="5"/>
</issue>
@@ -781,7 +649,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="85"
+ line="69"
column="5"/>
</issue>
@@ -797,7 +665,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="86"
+ line="70"
column="5"/>
</issue>
@@ -813,7 +681,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="87"
+ line="71"
column="5"/>
</issue>
@@ -829,7 +697,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="88"
+ line="72"
column="5"/>
</issue>
@@ -845,7 +713,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="89"
+ line="73"
column="5"/>
</issue>
@@ -861,7 +729,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="90"
+ line="74"
column="5"/>
</issue>
@@ -877,7 +745,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="91"
+ line="75"
column="5"/>
</issue>
@@ -893,7 +761,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="92"
+ line="76"
column="5"/>
</issue>
@@ -909,7 +777,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="94"
+ line="78"
column="5"/>
</issue>
@@ -925,7 +793,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="97"
+ line="81"
column="5"/>
</issue>
@@ -941,7 +809,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="100"
+ line="84"
column="5"/>
</issue>
@@ -953,43 +821,11 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="wifi_details_icon_color">#8A000000</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" <color name="fallback_tintColor">#89000000</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="103"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="suggestion_condition_background">#f2f2f2</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="106"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="condition_card_background">#f8f8f8</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="107"
+ line="87"
column="5"/>
</issue>
@@ -1005,7 +841,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="110"
+ line="90"
column="5"/>
</issue>
@@ -1021,7 +857,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="111"
+ line="91"
column="5"/>
</issue>
@@ -1037,7 +873,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="112"
+ line="92"
column="5"/>
</issue>
@@ -1053,7 +889,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="113"
+ line="93"
column="5"/>
</issue>
@@ -1069,7 +905,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="114"
+ line="94"
column="5"/>
</issue>
@@ -1085,7 +921,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="115"
+ line="95"
column="5"/>
</issue>
@@ -1101,7 +937,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="116"
+ line="96"
column="5"/>
</issue>
@@ -1117,7 +953,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="117"
+ line="97"
column="5"/>
</issue>
@@ -1133,7 +969,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="118"
+ line="98"
column="5"/>
</issue>
@@ -1145,11 +981,11 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="homepage_accessibility_background">#783BE5</color>"
+ errorLine1=" <color name="homepage_accessibility_background">#5011C1</color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="119"
+ line="99"
column="5"/>
</issue>
@@ -1165,7 +1001,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="120"
+ line="100"
column="5"/>
</issue>
@@ -1177,11 +1013,11 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="homepage_support_background">#3F5FBD</color>"
+ errorLine1=" <color name="homepage_support_background">#26459C</color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="121"
+ line="101"
column="5"/>
</issue>
@@ -1197,7 +1033,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="122"
+ line="102"
column="5"/>
</issue>
@@ -1213,7 +1049,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="123"
+ line="103"
column="5"/>
</issue>
@@ -1229,7 +1065,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="124"
+ line="104"
column="5"/>
</issue>
@@ -1245,7 +1081,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="125"
+ line="105"
column="5"/>
</issue>
@@ -1261,7 +1097,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="126"
+ line="106"
column="5"/>
</issue>
@@ -1277,7 +1113,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="130"
+ line="110"
column="5"/>
</issue>
@@ -1293,7 +1129,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="135"
+ line="115"
column="5"/>
</issue>
@@ -1309,7 +1145,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="136"
+ line="116"
column="5"/>
</issue>
@@ -1325,7 +1161,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="137"
+ line="117"
column="5"/>
</issue>
@@ -1341,7 +1177,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="138"
+ line="118"
column="5"/>
</issue>
@@ -1357,7 +1193,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="139"
+ line="119"
column="5"/>
</issue>
@@ -1373,7 +1209,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="140"
+ line="120"
column="5"/>
</issue>
@@ -1389,7 +1225,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="143"
+ line="123"
column="5"/>
</issue>
@@ -1405,7 +1241,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="144"
+ line="124"
column="5"/>
</issue>
@@ -1421,7 +1257,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="145"
+ line="125"
column="5"/>
</issue>
@@ -1437,7 +1273,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="146"
+ line="126"
column="5"/>
</issue>
@@ -1453,7 +1289,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="147"
+ line="127"
column="5"/>
</issue>
@@ -1737,12 +1573,12 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" android:tint="@color/wifi_details_icon_color">"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" android:color="@color/homepage_about_background" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="res/drawable/ic_frequency_antenna.xml"
- line="22"
- column="9"/>
+ file="res/drawable/ic_homepage_about.xml"
+ line="23"
+ column="17"/>
</issue>
<issue
@@ -1753,10 +1589,10 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" android:color="@color/homepage_about_background" />"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ errorLine1=" android:color="@color/homepage_accessibility_background" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="res/drawable/ic_homepage_about.xml"
+ file="res/drawable/ic_homepage_accessibility.xml"
line="23"
column="17"/>
</issue>
@@ -1993,6 +1829,22 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+ errorLine1=" android:color="@color/homepage_support_background" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/drawable/ic_homepage_support.xml"
+ line="23"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="HardCodedColor"
+ severity="Error"
+ message="Avoid using hardcoded color"
+ category="Correctness"
+ priority="4"
+ summary="Using hardcoded color"
+ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color="@color/homepage_system_background" />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -2041,22 +1893,6 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" android:tint="@color/wifi_details_icon_color">"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/drawable/ic_security_lock_24dp.xml"
- line="22"
- column="9"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" <background android:drawable="@color/shortcut_background"/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -2605,7 +2441,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/strings.xml"
- line="5806"
+ line="5805"
column="36"/>
</issue>
@@ -2637,7 +2473,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
- line="419"
+ line="425"
column="44"/>
</issue>
@@ -2653,7 +2489,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
- line="425"
+ line="431"
column="44"/>
</issue>
@@ -2669,7 +2505,7 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
- line="426"
+ line="432"
column="44"/>
</issue>
@@ -2685,7 +2521,23 @@
errorLine2=" ^">
<location
file="res/values/styles.xml"
- line="461"
+ line="467"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="HardCodedColor"
+ severity="Error"
+ message="Avoid using hardcoded color"
+ category="Correctness"
+ priority="4"
+ summary="Using hardcoded color"
+ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+ errorLine1=" <item name="strokeColor">@color/homepage_card_stroke_color</item>"
+ errorLine2=" ^">
+ <location
+ file="res/values/styles.xml"
+ line="474"
column="34"/>
</issue>
diff --git a/res/drawable/ic_frequency_antenna.xml b/res/drawable/ic_frequency_antenna.xml
index 581b83e..716a98a 100644
--- a/res/drawable/ic_frequency_antenna.xml
+++ b/res/drawable/ic_frequency_antenna.xml
@@ -19,7 +19,7 @@
android:viewportHeight="24"
android:width="24dp"
android:height="24dp"
- android:tint="@color/wifi_details_icon_color">
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M12,5c-3.9,0-7,3.1-7,7h2c0-2.8,2.2-5,5-5s5,2.2,5,5h2C19,8.1,15.9,5,12,5z M13,14.3c0.9-0.4,1.5-1.3,1.5-2.3
c0-1.4-1.1-2.5-2.5-2.5S9.5,10.6,9.5,12c0,1,0.6,1.9,1.5,2.3v3.3L7.6,21L9,22.4l3-3l3,3l1.4-1.4L13,17.6V14.3z M12,1
diff --git a/res/drawable/ic_security_lock_24dp.xml b/res/drawable/ic_security_lock_24dp.xml
index fd49b23..40b5109 100644
--- a/res/drawable/ic_security_lock_24dp.xml
+++ b/res/drawable/ic_security_lock_24dp.xml
@@ -19,7 +19,7 @@
android:viewportHeight="24"
android:width="24dp"
android:height="24dp"
- android:tint="@color/wifi_details_icon_color">
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"
android:fillColor="#FFFFFFFF" />
diff --git a/res/drawable/ic_wifi_privacy_24dp.xml b/res/drawable/ic_wifi_privacy_24dp.xml
new file mode 100644
index 0000000..c23fbc1
--- /dev/null
+++ b/res/drawable/ic_wifi_privacy_24dp.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M21.25,16.5v-0.66c0,-1.13 -1.03,-2.09 -2.25,-2.09s-2.25,0.96 -2.25,2.09v0.66H16V22h6v-5.5H21.25zM19.75,16.5h-1.5v-0.66c0,-0.29 0.38,-0.59 0.75,-0.59s0.75,0.3 0.75,0.59V16.5z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,17c-3.79,0 -7.17,-2.13 -8.82,-5.5C4.83,8.13 8.21,6 12,6s7.17,2.13 8.82,5.5H23C21.27,7.11 17,4 12,4S2.73,7.11 1,11.5C2.73,15.89 7,19 12,19c0.68,0 1.35,-0.06 2,-0.17v-2.05C13.35,16.91 12.69,17 12,17z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M16.43,12.23c0.04,-0.24 0.07,-0.48 0.07,-0.73C16.5,9.02 14.48,7 12,7s-4.5,2.02 -4.5,4.5S9.52,16 12,16c0.77,0 1.48,-0.21 2.12,-0.55C14.41,14.08 15.27,12.93 16.43,12.23zM12,14.2c-1.49,0 -2.7,-1.21 -2.7,-2.7s1.21,-2.7 2.7,-2.7s2.7,1.21 2.7,2.7S13.49,14.2 12,14.2z"/>
+</vector>
diff --git a/res/layout-land/panel_layout.xml b/res/layout-land/panel_layout.xml
new file mode 100644
index 0000000..3975bfe
--- /dev/null
+++ b/res/layout-land/panel_layout.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingBottom="24dp"
+ android:paddingTop="18dp"
+ android:textColor="?android:attr/colorPrimary"
+ android:textSize="20sp"/>
+
+ <include layout="@layout/horizontal_divider"/>
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/panel_parent_layout"
+ android:scrollbars="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+
+ <include layout="@layout/panel_buttons"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
new file mode 100644
index 0000000..0c938f8
--- /dev/null
+++ b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/root"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <include layout="@layout/wifi_dpp_fragment_header"/>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <SurfaceView
+ android:id="@+id/preview_view"
+ android:layout_width="426dp"
+ android:layout_height="320dp"
+ android:layout_gravity="center"/>
+ <com.android.settings.wifi.qrcode.QrDecorateView
+ android:id="@+id/decorate_view"
+ android:layout_width="426dp"
+ android:layout_height="320dp"
+ android:layout_gravity="center"/>
+ </FrameLayout>
+
+ <TextView android:id="@+id/error_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"/>
+
+ <include layout="@layout/wifi_dpp_fragment_footer"
+ android:gravity="center|bottom"/>
+
+</LinearLayout>
+
diff --git a/res/layout/panel_buttons.xml b/res/layout/panel_buttons.xml
new file mode 100644
index 0000000..1bb3898
--- /dev/null
+++ b/res/layout/panel_buttons.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="14dp"
+ android:paddingBottom="14dp"
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/see_more"
+ style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="20dp"
+ android:text="@string/see_more"/>
+
+ <Space
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="match_parent" />
+
+ <Button
+ android:id="@+id/done"
+ style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="20dp"
+ android:text="@string/done"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/panel_layout.xml b/res/layout/panel_layout.xml
index cbdd53f..a6f62a4 100644
--- a/res/layout/panel_layout.xml
+++ b/res/layout/panel_layout.xml
@@ -14,13 +14,30 @@
See the License for the specific language governing permissions and
limitations under the License
-->
+
+<!-- Note: There is a landscape version of this layout. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/panel_parent_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingLeft="24dp"
- android:paddingRight="24dp"
- android:paddingBottom="8dp"
- android:layout_margin="4dp"
- android:orientation="vertical">
+ android:gravity="center"
+ android:paddingBottom="24dp"
+ android:paddingTop="18dp"
+ android:textColor="?android:attr/colorPrimary"
+ android:textSize="20sp"/>
+
+ <include layout="@layout/horizontal_divider"/>
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/panel_parent_layout"
+ android:scrollbars="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+ <include layout="@layout/panel_buttons"/>
</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/panel_slice_row.xml b/res/layout/panel_slice_row.xml
new file mode 100644
index 0000000..4ce3494
--- /dev/null
+++ b/res/layout/panel_slice_row.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <androidx.slice.widget.SliceView
+ android:id="@+id/slice_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="20dp"
+ android:paddingEnd="20dp" />
+
+ <include layout="@layout/horizontal_divider"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/search_bar.xml b/res/layout/search_bar.xml
index 9135ebf..be8aa3b 100644
--- a/res/layout/search_bar.xml
+++ b/res/layout/search_bar.xml
@@ -15,42 +15,33 @@
limitations under the License.
-->
-<FrameLayout
+<com.google.android.material.card.MaterialCardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/search_bar_container"
+ android:id="@+id/search_bar"
+ style="@style/SearchBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="?android:attr/colorBackground"
- android:theme="@style/ThemeOverlay.Settings.SearchBar"
app:layout_scrollFlags="scroll|enterAlways">
- <androidx.cardview.widget.CardView
- android:id="@+id/search_bar"
+ <Toolbar
+ android:id="@+id/search_action_bar"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_margin="@dimen/search_bar_margin"
- app:cardCornerRadius="@dimen/search_bar_corner_radius"
- app:cardElevation="@dimen/search_bar_card_elevation">
- <Toolbar
- android:id="@+id/search_action_bar"
- android:layout_width="match_parent"
- android:layout_height="@dimen/search_bar_height"
- android:background="?android:attr/selectableItemBackground"
- android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset"
- android:navigationIcon="@drawable/ic_search_24dp">
- <TextView
- android:id="@+id/search_action_bar_title"
- style="@style/TextAppearance.SearchBar"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/search_menu"/>
- </Toolbar>
- <ImageView
- android:id="@+id/account_avatar"
- android:layout_marginStart="@dimen/search_bar_avatar_start_margin"
- android:layout_marginEnd="@dimen/search_bar_avatar_end_margin"
- android:layout_width="@dimen/search_bar_avatar_size"
- android:layout_height="@dimen/search_bar_avatar_size"
- android:layout_gravity="end|center_vertical"/>
- </androidx.cardview.widget.CardView>
-</FrameLayout>
\ No newline at end of file
+ android:layout_height="@dimen/search_bar_height"
+ android:background="?android:attr/selectableItemBackground"
+ android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset"
+ android:navigationIcon="@drawable/ic_search_24dp">
+ <TextView
+ android:id="@+id/search_action_bar_title"
+ style="@style/TextAppearance.SearchBar"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/search_menu"/>
+ </Toolbar>
+ <ImageView
+ android:id="@+id/account_avatar"
+ android:layout_marginStart="@dimen/search_bar_avatar_start_margin"
+ android:layout_marginEnd="@dimen/search_bar_avatar_end_margin"
+ android:layout_width="@dimen/search_bar_avatar_size"
+ android:layout_height="@dimen/search_bar_avatar_size"
+ android:layout_gravity="end|center_vertical"/>
+</com.google.android.material.card.MaterialCardView>
diff --git a/res/layout/settings_action_buttons.xml b/res/layout/settings_action_buttons.xml
deleted file mode 100644
index 56e1a36..0000000
--- a/res/layout/settings_action_buttons.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
- -->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="8dp"
- android:orientation="horizontal">
-
- <Button
- android:id="@+id/button1"
- style="@style/SettingsActionButton"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
-
- <Button
- android:id="@+id/button2"
- style="@style/SettingsActionButton"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
-
- <Button
- android:id="@+id/button3"
- style="@style/SettingsActionButton"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
-
- <Button
- android:id="@+id/button4"
- style="@style/SettingsActionButton"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 0223573..8d81e82 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -23,11 +23,12 @@
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:background="@android:color/transparent"
+ app:elevation="0dp">
<include layout="@layout/search_bar"/>
</com.google.android.material.appbar.AppBarLayout>
-
<androidx.core.widget.NestedScrollView
android:id="@+id/main_content_scrollable_container"
android:layout_width="match_parent"
diff --git a/res/layout/settings_main_dashboard.xml b/res/layout/settings_main_dashboard.xml
index 3994092..ee84576 100644
--- a/res/layout/settings_main_dashboard.xml
+++ b/res/layout/settings_main_dashboard.xml
@@ -1,25 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ 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.
-->
+<!-- TODO(118444000): Remove this -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@@ -30,4 +28,4 @@
android:id="@+id/main_content"
android:layout_height="match_parent"
android:layout_width="match_parent" />
-</LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/wifi_dpp_add_device_fragment.xml b/res/layout/wifi_dpp_add_device_fragment.xml
new file mode 100644
index 0000000..03add62
--- /dev/null
+++ b/res/layout/wifi_dpp_add_device_fragment.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/root"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <include layout="@layout/wifi_dpp_fragment_header"/>
+
+ <ProgressBar
+ android:id="@+id/progress_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:indeterminate="true"/>
+
+ <ImageView
+ android:id="@+id/wifi_ap_picture_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"/>
+
+ <TextView android:id="@+id/choose_different_network"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"/>
+
+ <include layout="@layout/wifi_dpp_fragment_footer"
+ android:gravity="center|bottom"/>
+
+</LinearLayout>
+
diff --git a/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml b/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml
new file mode 100644
index 0000000..a65cf3e
--- /dev/null
+++ b/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/root"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <include layout="@layout/wifi_dpp_fragment_header"/>
+
+ <ListView android:id="@+id/saved_wifi_network_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+ <include layout="@layout/wifi_dpp_fragment_footer"
+ android:gravity="center|bottom"/>
+
+</LinearLayout>
+
diff --git a/res/layout/wifi_dpp_qrcode_generator_fragment.xml b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
new file mode 100644
index 0000000..789b3a3
--- /dev/null
+++ b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/root"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <include layout="@layout/wifi_dpp_fragment_header"/>
+
+ <ImageView
+ android:id="@+id/barcode_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"/>
+
+</LinearLayout>
+
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index 130bb6d..ab38ac1 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -17,7 +17,6 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -33,7 +32,7 @@
android:layout_width="320dp"
android:layout_height="426dp"
android:layout_gravity="center"/>
- <ImageView
+ <com.android.settings.wifi.qrcode.QrDecorateView
android:id="@+id/decorate_view"
android:layout_width="320dp"
android:layout_height="426dp"
diff --git a/res/layout/zen_onboarding.xml b/res/layout/zen_onboarding.xml
index 33cdbdd..35b992d 100644
--- a/res/layout/zen_onboarding.xml
+++ b/res/layout/zen_onboarding.xml
@@ -47,7 +47,8 @@
android:id="@+id/zen_onboarding_new_setting_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingHorizontal="8dp" />
+ android:paddingHorizontal="8dp"
+ android:minHeight="48dp"/>
<LinearLayout
android:layout_width="match_parent"
@@ -83,7 +84,8 @@
android:id="@+id/zen_onboarding_current_setting_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingHorizontal="8dp" />
+ android:paddingHorizontal="8dp"
+ android:minHeight="48dp"/>
<LinearLayout
android:layout_width="match_parent"
diff --git a/res/layout/zen_rule_widget.xml b/res/layout/zen_rule_widget.xml
index d502243..c6214e7 100644
--- a/res/layout/zen_rule_widget.xml
+++ b/res/layout/zen_rule_widget.xml
@@ -20,13 +20,13 @@
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
- android:id="@+id/delete_zen_rule"
+ android:id="@+id/zen_automatic_rule_widget"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:paddingStart="16dip"
android:paddingEnd="16dip"
- android:src="@drawable/ic_delete"
- android:contentDescription="@string/zen_mode_delete_rule"
+ android:src="@drawable/ic_settings"
+ android:contentDescription="zen_mode_rule_settings"
android:layout_gravity="center"
android:background="?android:attr/selectableItemBackground" />
</LinearLayout>
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 595f429..bc06f47 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -19,5 +19,7 @@
<color name="switch_bar_background">#dadce0</color>
<color name="switchbar_switch_track_tint">#82000000</color>
<color name="switchbar_switch_thumb_tint">@android:color/black</color>
+ <color name="homepage_accessibility_background">#783BE5</color>
+ <color name="homepage_support_background">#3F5FBD</color>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index e477277..587184b 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -19,8 +19,6 @@
<color name="red">#F00</color>
<color name="blue">#00F</color>
- <color name="material_empty_color_light">#FFCED7DB</color>
-
<color name="bluetooth_dialog_text_color">#8a000000</color>
<color name="crypt_keeper_clock_background">#ff9a9a9a</color>
@@ -30,7 +28,6 @@
<color name="divider_color">#20ffffff</color>
<color name="title_color">@android:color/holo_blue_light</color>
- <color name="setup_lock_pattern_view_regular_color_dark">#ffbdbdbd</color>
<color name="setup_lock_pattern_view_regular_color_light">@color/lock_pattern_view_regular_color</color>
<color name="setup_lock_pattern_view_success_color_dark">#ff84ffff</color>
<color name="setup_lock_pattern_view_success_color_light">@color/suw_color_accent_light</color>
@@ -52,25 +49,13 @@
<color name="running_processes_system_ram">#ff384248</color>
<color name="running_processes_free_ram">#ffced7db</color>
- <color name="wifi_divider">#ffe0e0e0</color>
<color name="sim_noitification">@*android:color/accent_device_default_light</color>
<color name="confirm_device_credential_transparent_black">#60000000</color>
- <color name="voice_interaction_highlight">#33b5e5</color>
-
- <color name="memory_normal">#ff009587</color>
- <color name="memory_moderate">#ffF3B300</color>
- <color name="memory_low">#ffff9700</color>
- <color name="memory_critical">#ffff5621</color>
-
- <color name="memory_avg_use">#ff384248</color>
<!-- Accent color that matches the settings launcher icon -->
<color name="icon_accent">#ffabffec</color>
- <color name="importance_icon_tint">#8a000000</color>
- <color name="importance_disabled_tint">#4d000000</color>
-
<!-- Accessibility SUW colors -->
<color name="material_blue_500">#4285F4</color>
<color name="material_blue_700">#3367D6</color>
@@ -78,7 +63,6 @@
<color name="material_grey_200">#ffffff</color>
<color name="switch_bar_background">#ff80868B</color>
-
<color name="message_text_incoming">#ffffffff</color>
<color name="message_text_outgoing">#ff323232</color>
<color name="timestamp_text_outgoing">#99323232</color>
@@ -99,12 +83,8 @@
<!-- Color for the background of the shortcut icons.-->
<color name="shortcut_background">#fff5f5f5</color>
- <!-- Color for preference icons on the Wifi Network Details page -->
- <color name="wifi_details_icon_color">#8A000000</color>
-
- <!-- Suggestion/condition colors -->
- <color name="suggestion_condition_background">#f2f2f2</color>
- <color name="condition_card_background">#f8f8f8</color>
+ <!-- The fallback color for tinting icons. Only used when colorControlNormal is unavailable -->
+ <color name="fallback_tintColor">#89000000</color>
<!-- Dashboard/homepage icon background colors -->
<color name="homepage_network_background">#2196F3</color>
@@ -116,9 +96,9 @@
<color name="homepage_storage_background">#C14CE6</color>
<color name="homepage_security_background">#0F9D58</color>
<color name="homepage_accounts_background">#F15B8D</color>
- <color name="homepage_accessibility_background">#783BE5</color>
+ <color name="homepage_accessibility_background">#5011C1</color>
<color name="homepage_system_background">#9E9E9E</color>
- <color name="homepage_support_background">#3F5FBD</color>
+ <color name="homepage_support_background">#26459C</color>
<color name="homepage_generic_icon_background">#1A73E8</color>
<color name="homepage_location_background">#2EC7DC</color>
<color name="homepage_about_background">#9FA8DA</color>
diff --git a/res/values/config.xml b/res/values/config.xml
index 917f14d..edd948f 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -151,6 +151,9 @@
com.android.settings.intelligence
</string>
+ <!-- Settings intelligence interaction log intent action -->
+ <string name="config_settingsintelligence_log_action" translatable="false"></string>
+
<!-- Emergency app package name -->
<string name="config_emergency_package_name" translatable="false">
com.android.emergency
@@ -160,4 +163,6 @@
android.settings.EDIT_EMERGENCY_INFO
</string>
+ <!-- Email address for the homepage contextual cards feedback -->
+ <string name="config_contextual_card_feedback_email" translatable="false"></string>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f55ef10..83848af 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -95,11 +95,7 @@
<dimen name="switchbar_subsettings_margin_start">72dp</dimen>
<dimen name="switchbar_subsettings_margin_end">16dp</dimen>
- <!-- The following two margins need to match, with the caveat that
- the second should be negative. The second one ensures that the icons and text
- align despite the additional padding caused by the search bar's card background. -->
<dimen name="search_bar_margin">16dp</dimen>
- <dimen name="search_bar_negative_margin">-16dp</dimen>
<dimen name="search_bar_height">48dp</dimen>
<dimen name="search_bar_corner_radius">2dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 876be51..4aa0951 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3456,9 +3456,9 @@
<!-- Button title to factory data reset the entire device. The "(factory reset)" part is optional for translation. [CHAR LIMIT=30 BACKUP_MESSAGE_ID=3531267871084279512]-->
<string name="master_clear_short_title">Erase all data (factory reset)</string>
<!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset [CHAR LIMIT=NONE] -->
- <string name="master_clear_desc" product="tablet">"This will erase all data from your tablet\u2019s <b>internal storage</b>, including:\n\n<li>Your Google account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
+ <string name="master_clear_desc" product="tablet">"This will erase all data from your tablet\u2019s <b>internal storage</b>, including:\n\n<li>Your Google Account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
<!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset [CHAR LIMIT=NONE] -->
- <string name="master_clear_desc" product="default">"This will erase all data from your phone\u2019s <b>internal storage</b>, including:\n\n<li>Your Google account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
+ <string name="master_clear_desc" product="default">"This will erase all data from your phone\u2019s <b>internal storage</b>, including:\n\n<li>Your Google Account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
<!-- SD card & phone storage settings screen, instructions and list of current accounts. The list of accounts follows this text[CHAR LIMIT=NONE] -->
<string name="master_clear_accounts" product="default">"\n\nYou are currently signed into the following accounts:\n"</string>
<!-- SD card & phone storage settings screen, notification if other users are present on the device [CHAR LIMIT=NONE] -->
@@ -3488,17 +3488,17 @@
<!-- SD card & phone storage settings screen, description for check box to erase eSIMs for tablets [CHAR LIMIT=NONE] -->
<string name="erase_esim_storage_description" product="tablet">Erase all eSIMs on the tablet. This will not cancel your mobile service plan.</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Factory data reset -->
- <string name="master_clear_button_text" product="tablet">Reset tablet</string>
+ <string name="master_clear_button_text" product="tablet">Erase all data</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Factory data reset -->
- <string name="master_clear_button_text" product="default">Reset phone</string>
+ <string name="master_clear_button_text" product="default">Erase all data</string>
<!-- SD card & phone storage settings screen, message on screen after user selects Reset phone button -->
- <string name="master_clear_final_desc">Erase all your personal information and downloaded apps? You can\u2019t undo this action!</string>
+ <string name="master_clear_final_desc">All of your personal information and downloaded apps will be deleted. You can\u2019t undo this action!</string>
<!-- SD card & phone storage settings screen, button on screen after user selects Reset phone button -->
<string name="master_clear_final_button_text">Erase everything</string>
<!-- Master clear failed message -->
<string name="master_clear_failed">No reset was performed because the System Clear service isn\u2019t available.</string>
<!-- Master clear confirmation screen title [CHAR LIMIT=30] -->
- <string name="master_clear_confirm_title">Reset?</string>
+ <string name="master_clear_confirm_title">Erase all data?</string>
<!-- Error message for users that aren't allowed to factory reset [CHAR LIMIT=none] -->
<string name="master_clear_not_available">Factory reset is not available for this user</string>
<!-- Master clear progress screen title [CHAR LIMIT=30] -->
@@ -7117,6 +7117,12 @@
<!-- Do not disturb: Title for the zen mode automation option in Settings. [CHAR LIMIT=40] -->
<string name="zen_mode_automation_settings_title">Schedules</string>
+ <!-- Do not disturb: Title for dialog that allows users to delete DND rules/schedules[CHAR LIMIT=40] -->
+ <string name="zen_mode_delete_automatic_rules">Delete schedules</string>
+
+ <!-- Do not disturb: Delete text button presented in a dialog to confirm the user would like to delete the selected DND rules. [CHAR LIMIT=30] -->
+ <string name="zen_mode_schedule_delete">Delete</string>
+
<!-- Do not disturb: Title for the zen mode automatic rules page in settings. [CHAR LIMIT=30] -->
<string name="zen_mode_automation_settings_page_title">Do Not Disturb</string>
@@ -7253,6 +7259,9 @@
<!-- [CHAR LIMIT=110] Zen mode settings footer: Footer how DND was triggered by an app -->
<string name="zen_mode_settings_dnd_automatic_rule_app">Do Not Disturb was automatically turned on by an app (<xliff:g id="app_name" example="Android Services">%s</xliff:g>)</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings footer: Footer informing user DND has custom settings. -->
+ <string name="zen_mode_settings_dnd_custom_settings_footer">Do Not Disturb is on for <xliff:g id="rule_names" example="Sleeping and Work">%s</xliff:g> with custom settings.</string>
+
<!--[CHAR LIMIT=40] Zen Interruption level: Priority. -->
<string name="zen_interruption_level_priority">Priority only</string>
@@ -7848,6 +7857,15 @@
<!-- [CHAR LIMIT=NONE] Zen mode settings: Downtime rule setting -->
<string name="zen_mode_schedule_alarm_summary">Stop at the end time or next alarm, whichever comes first</string>
+ <!-- [CHAR LIMIT=80] Zen mode settings: Title for preference to allow custom behavior for the dnd schedule -->
+ <string name="zen_mode_custom_behavior_title">Do Not Disturb behavior</string>
+
+ <!-- [CHAR LIMIT=120] Zen mode settings: Summay text indicating the currenty dnd schedule is using the default dnd settings -->
+ <string name="zen_mode_custom_behavior_summary_default">Use default settings</string>
+
+ <!-- [CHAR LIMIT=120] Zen mode settings: Summay text indicating the currenty dnd schedule is using custom behavior -->
+ <string name="zen_mode_custom_behavior_summary">Create custom settings for this schedule</string>
+
<!-- [CHAR LIMIT=40] General divider text when concatenating multiple items in a text summary -->
<string name="summary_divider_text">,\u0020</string>
@@ -8931,25 +8949,28 @@
<string name="condition_expand_hide">Hide</string>
<!-- Title of condition that hotspot is on [CHAR LIMIT=30] -->
- <string name="condition_hotspot_title">Hotspot is on</string>
+ <string name="condition_hotspot_title">Hotspot</string>
<!-- Summary of condition that hotspot is on [CHAR LIMIT=NONE] -->
- <string name="condition_hotspot_summary">Portable Wi-Fi hotspot <xliff:g name="ap_name" example="AndroidAP">%1$s</xliff:g> is active, Wi-Fi for this device is turned off.</string>
+ <string name="condition_hotspot_summary"><xliff:g name="ap_name" example="AndroidAP">%1$s</xliff:g> on</string>
<!-- Title of condition that airplane mode is on [CHAR LIMIT=30] -->
<string name="condition_airplane_title">Airplane mode is on</string>
<!-- Summary of condition that airplane mode is on [CHAR LIMIT=NONE] -->
- <string name="condition_airplane_summary">When airplane mode is turned on, Wi\u2011Fi, Bluetooth, and mobile network are turned off. Wi\u2011Fi and Bluetooth can be turned back on.</string>
+ <string name="condition_airplane_summary">Networks unavailable</string>
<!-- Title of condition that do not disturb is on [CHAR LIMIT=36] -->
<string name="condition_zen_title">Do Not Disturb is on</string>
+ <!-- Summary of condition that do not disturb is on [CHAR LIMIT=36] -->
+ <string name="condition_zen_summary">Impacts what you hear and see</string>
+
<!-- Title of condition that battery saver is on [CHAR LIMIT=30] -->
<string name="condition_battery_title">Battery Saver is on</string>
<!-- Summary of condition that battery saver is on [CHAR LIMIT=NONE] -->
- <string name="condition_battery_summary">Battery Saver turns off some device features and restricts apps</string>
+ <string name="condition_battery_summary">Features restricted</string>
<!-- Title of condition that cellular data is off [CHAR LIMIT=50] -->
<string name="condition_cellular_title">Mobile data is off</string>
@@ -8958,10 +8979,10 @@
<string name="condition_cellular_summary">Internet is available only via Wi-Fi</string>
<!-- Title of condition that background data is off [CHAR LIMIT=30] -->
- <string name="condition_bg_data_title">Data Saver is on</string>
+ <string name="condition_bg_data_title">Data Saver</string>
<!-- Summary of condition that background data is off [CHAR LIMIT=NONE] -->
- <string name="condition_bg_data_summary">Background data is only available via Wi-Fi. This may affect some apps or services when Wi-Fi is not available.</string>
+ <string name="condition_bg_data_summary">Features restricted</string>
<!-- Title of condition that work mode is off [CHAR LIMIT=30] -->
<string name="condition_work_title">Work profile is off</string>
@@ -8976,22 +8997,22 @@
<string name="condition_device_muted_title" product="tablet">Device is muted</string>
<!-- Title of condition that indicates device is muted [CHAR LIMIT=50] -->
- <string name="condition_device_muted_title" product="default">Phone is muted</string>
+ <string name="condition_device_muted_title" product="default">Phone muted</string>
<!-- Summary of condition that indicates device is muted -->
- <string name="condition_device_muted_summary">Calls and notifications will be muted</string>
+ <string name="condition_device_muted_summary">For calls & notifications</string>
<!-- Title of condition that indicates device is set to vibrate [CHAR LIMIT=50] -->
<string name="condition_device_vibrate_title" product="tablet">Device is set to vibrate</string>
<!-- Title of condition that indicates device is muted [CHAR LIMIT=50] -->
- <string name="condition_device_vibrate_title" product="default">Phone is set to vibrate</string>
+ <string name="condition_device_vibrate_title" product="default">Vibration only</string>
<!-- Summary of condition that indicates device is set to vibrate -->
<string name="condition_device_vibrate_summary" product="tablet">Calls and notifications will vibrate device</string>
<!-- Summary of condition that indicates device is set to vibrate -->
- <string name="condition_device_vibrate_summary" product="default">Calls and notifications will vibrate phone</string>
+ <string name="condition_device_vibrate_summary" product="default">For calls & notifications</string>
<!-- Night display: Title for the night display option Suggestion (renamed "Night Light" with title caps). [CHAR LIMIT=46] -->
<string name="night_display_suggestion_title">Set Night Light schedule</string>
@@ -9003,7 +9024,7 @@
<string name="condition_night_display_title">Night Light is on</string>
<!-- Summary of condition that night display is on (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
- <string name="condition_night_display_summary">Screen is tinted amber. This may help you fall asleep.</string>
+ <string name="condition_night_display_summary">Screen tinted amber</string>
<!-- Summary for the condition section on the dashboard, representing number of conditions. [CHAR LIMIT=10] -->
<string name="condition_summary" translatable="false"><xliff:g name="count" example="3">%1$d</xliff:g></string>
@@ -9889,6 +9910,11 @@
<!-- UI debug setting: preference summary - describes the behavior of forcing full raw GNSS satellite measurements [CHAR LIMIT=NONE] -->
<string name="enable_gnss_raw_meas_full_tracking_summary">Track all GNSS constellations and frequencies with no duty cycling</string>
+ <!-- UI debug setting: preference title - allow background activity starts [CHAR LIMIT=60] -->
+ <string name="allow_background_activity_starts">Allow background activity starts</string>
+ <!-- UI debug setting: preference summary - describes the behavior of allowing background activity starts [CHAR LIMIT=NONE] -->
+ <string name="allow_background_activity_starts_summary">Allows all background activity starts</string>
+
<!-- UI debug setting: preference title - show all crash dialogs [CHAR LIMIT=60] -->
<string name="show_first_crash_dialog">Always show crash dialog</string>
<!-- UI debug setting: preference summary - describes the behavior of showing a dialog every time an app crashes [CHAR LIMIT=NONE] -->
@@ -10216,6 +10242,8 @@
<item quantity="one"><xliff:g id="number_device_count">%1$d</xliff:g> device connected</item>
<item quantity="other"><xliff:g id="number_device_count">%1$d</xliff:g> devices connected</item>
</plurals>
+ <!-- Title for bluetooth connected devices in connected device slice. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_connected_devices">Bluetooth Devices</string>
<!-- Title for no connected devices in connected device slice. [CHAR LIMIT=NONE] -->
<string name="no_connected_devices">No connected devices</string>
@@ -10225,14 +10253,17 @@
<!-- Title for the Internet Connectivity dialog (settings panel) with Internet related settings [CHAR LIMIT=50] -->
<string name="internet_connectivity_panel_title">Internet Connectivity</string>
+ <!-- Title for the Volume dialog (settings panel) with all volume streams[CHAR LIMIT=50] -->
+ <string name="volume_connectivity_panel_title">Volume</string>
+
<!-- UI debug setting: force desktop mode [CHAR LIMIT=50] -->
<string name="force_desktop_mode">Force desktop mode</string>
<!-- UI debug setting: force desktop mode summary [CHAR LIMIT=NONE] -->
<string name="force_desktop_mode_summary">Force experimental desktop mode on secondary displays</string>
- <!-- UI debug setting: Force enable "smart dark" UI rendering feature [CHAR LIMIT=40] -->
+ <!-- UI debug setting: Force enable "smart dark" UI rendering feature [CHAR LIMIT=60] -->
<string name="hwui_force_dark_title">Override force-dark</string>
- <!-- UI debug setting: Force enable "smart dark" UI rendering feature summary [CHAR LIMIT=100] -->
+ <!-- UI debug setting: Force enable "smart dark" UI rendering feature summary [CHAR LIMIT=NONE] -->
<string name="hwui_force_dark_summary">Overrides the force-dark feature to be always-on</string>
<!-- Title for the top level Privacy Settings [CHAR LIMIT=30]-->
@@ -10249,4 +10280,9 @@
<!-- Summary for low storage slice. [CHAR LIMIT=NONE] -->
<string name="low_storage_summary">Storage is low. <xliff:g id="percentage" example="54%">%1$s</xliff:g> used - <xliff:g id="free_space" example="32GB">%2$s</xliff:g> free</string>
-</resources>
\ No newline at end of file
+
+ <!-- Label for button in contextual card feedback dialog for users to send feedback [CHAR LIMIT=30] -->
+ <string name="contextual_card_feedback_send">Send feedback</string>
+ <!-- String for contextual card feedback dialog [CHAR LIMIT=NONE] -->
+ <string name="contextual_card_feedback_confirm_message">Would you like to give us feedback on this suggestion?</string>
+</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 1b311aa..141426e 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -17,7 +17,7 @@
<resources>
<style name="Widget.ActionBar.Base"
- parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid"/>
+ parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid"/>
<style name="Widget.ActionBar"
parent="Widget.ActionBar.Base">
@@ -259,7 +259,8 @@
<style name="TextAppearance.Medium" parent="@android:style/TextAppearance.Material.Medium"/>
<style name="TextAppearance.Small" parent="@android:style/TextAppearance.Material.Small"/>
- <style name="TextAppearance.Switch" parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
+ <style name="TextAppearance.Switch"
+ parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
<item name="android:textSize">16sp</item>
</style>
@@ -400,14 +401,6 @@
<style name="ActionSecondaryButton" parent="android:Widget.DeviceDefault.Button"/>
- <style name="SettingsActionButton" parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
- <item name="android:drawablePadding">4dp</item>
- <item name="android:drawableTint">@*android:color/btn_colored_borderless_text_material</item>
- <item name="android:layout_marginEnd">8dp</item>
- <item name="android:paddingTop">20dp</item>
- <item name="android:paddingBottom">20dp</item>
- </style>
-
<style name="LockPatternContainerStyle">
<item name="android:maxHeight">400dp</item>
<item name="android:maxWidth">420dp</item>
@@ -465,6 +458,13 @@
<item name="strokeWidth">1dp</item>
</style>
+ <style name="SearchBarStyle">
+ <item name="android:layout_margin">@dimen/search_bar_margin</item>
+ <item name="cardCornerRadius">8dp</item>
+ <item name="strokeColor">@color/homepage_card_stroke_color</item>
+ <item name="strokeWidth">1dp</item>
+ </style>
+
<style name="ConditionCardBorderlessButton"
parent="android:Widget.DeviceDefault.Button.Borderless">
<item name="android:textColor">?android:attr/colorAccent</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 873216d..1e24770 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -54,6 +54,10 @@
<item name="batteryGoodColor">@color/battery_good_color_light</item>
<item name="batteryMaybeColor">@color/battery_maybe_color_light</item>
<item name="batteryBadColor">@color/battery_bad_color_light</item>
+
+ <!-- TODO(118444000): Remove colorPrimary and colorPrimaryVariant -->
+ <item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
+ <item name="colorPrimaryVariant">@android:color/white</item>
</style>
<!-- Variant of the settings theme with no action bar. -->
@@ -185,6 +189,8 @@
<item name="batteryGoodColor">@color/battery_good_color_light</item>
<item name="batteryMaybeColor">@color/battery_maybe_color_light</item>
<item name="batteryBadColor">@color/battery_bad_color_light</item>
+ <!-- Define this color for material design -->
+ <item name="colorPrimaryVariant">@android:color/white</item>
</style>
<style name="Theme.Settings.Home" parent="Theme.Settings.HomeBase">
@@ -195,13 +201,11 @@
<item name="android:windowLightNavigationBar">true</item>
</style>
- <style name="ThemeOverlay.Settings.SearchBar" parent="Theme.Settings">
- <item name="android:colorBackground">?android:attr/colorPrimary</item>
- <item name="cardBackgroundColor">?android:attr/colorBackground</item>
- </style>
-
<style name="Theme.BottomDialog" parent="@*android:style/Theme.DeviceDefault.Settings.Dialog">
<item name="android:windowBackground">@drawable/settings_panel_background</item>
+ <item name="android:dividerHorizontal">@*android:drawable/list_divider_material</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
</style>
</resources>
diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml
index 8f99ce1..506686a 100644
--- a/res/xml/app_info_settings.xml
+++ b/res/xml/app_info_settings.xml
@@ -36,7 +36,7 @@
settings:allowDividerAbove="true"
settings:allowDividerBelow="true"/>
- <com.android.settings.widget.ActionButtonPreference
+ <com.android.settingslib.widget.ActionButtonsPreference
android:key="action_buttons"
android:order="-9998" />
@@ -72,12 +72,6 @@
settings:controller="com.android.settings.applications.appinfo.AppDataUsagePreferenceController" />
<Preference
- android:key="data_settings_v2"
- android:title="@string/data_usage_app_summary_title"
- android:summary="@string/summary_placeholder"
- settings:controller="com.android.settings.applications.appinfo.AppDataUsagePreferenceControllerV2" />
-
- <Preference
android:key="time_spent_in_app"
android:title="@string/time_spent_in_app_pref_title"
settings:controller="com.android.settings.applications.appinfo.TimeSpentInAppPreferenceController" />
@@ -185,4 +179,4 @@
settings:allowDividerAbove="true"
settings:enableCopying="true"/>
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/res/xml/app_storage_settings.xml b/res/xml/app_storage_settings.xml
index 7036d27..376f09e 100644
--- a/res/xml/app_storage_settings.xml
+++ b/res/xml/app_storage_settings.xml
@@ -19,7 +19,7 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/storage_label">
- <com.android.settings.widget.ActionButtonPreference
+ <com.android.settingslib.widget.ActionButtonsPreference
android:key="header_view" />
<com.android.settings.applications.SpacePreference
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index 6449e4b..40ce93d 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -25,7 +25,7 @@
android:selectable="false"
settings:allowDividerBelow="true"/>
- <com.android.settings.widget.ActionButtonPreference
+ <com.android.settingslib.widget.ActionButtonsPreference
android:key="action_buttons" />
<PreferenceCategory
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index cc724b8..a0f019d 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -485,6 +485,11 @@
android:title="@string/background_check_pref" />
<SwitchPreference
+ android:key="allow_background_activity_starts"
+ android:title="@string/allow_background_activity_starts"
+ android:summary="@string/allow_background_activity_starts_summary" />
+
+ <SwitchPreference
android:key="show_first_crash_dialog"
android:title="@string/show_first_crash_dialog"
android:summary="@string/show_first_crash_dialog_summary" />
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index b0e362c..50a5649 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -44,7 +44,6 @@
android:title="@string/auto_brightness_title"
android:summary="@string/summary_placeholder"
android:fragment="com.android.settings.display.AutoBrightnessSettings"
- settings:searchable="false"
settings:controller="com.android.settings.display.AutoBrightnessPreferenceController" />
<com.android.settingslib.RestrictedPreference
diff --git a/res/xml/enterprise_privacy_settings.xml b/res/xml/enterprise_privacy_settings.xml
index 4fa50e7..e8b26b0 100644
--- a/res/xml/enterprise_privacy_settings.xml
+++ b/res/xml/enterprise_privacy_settings.xml
@@ -21,82 +21,107 @@
<!-- Header -->
<Preference android:key="enterprise_privacy_header"
+ android:order="100"
android:icon="@drawable/ic_info_outline_24dp"
android:summary="@string/enterprise_privacy_header"
android:selectable="false"/>
<PreferenceCategory android:key="exposure_category"
+ android:order="200"
android:title="@string/enterprise_privacy_exposure_category"
android:contentDescription="@string/enterprise_privacy_exposure_category">
<Preference android:key="enterprise_privacy_enterprise_data"
+ android:order="210"
android:layout_height="wrap_content"
android:title="@string/enterprise_privacy_enterprise_data"
android:selectable="false"/>
<Preference android:key="enterprise_privacy_installed_packages"
+ android:order="220"
android:title="@string/enterprise_privacy_installed_packages"
android:selectable="false"/>
<Preference android:key="enterprise_privacy_usage_stats"
+ android:order="230"
android:title="@string/enterprise_privacy_usage_stats"
android:selectable="false"/>
<Preference android:key="network_logs"
+ android:order="240"
android:title="@string/enterprise_privacy_network_logs"
android:selectable="false"/>
<Preference android:key="bug_reports"
+ android:order="250"
android:title="@string/enterprise_privacy_bug_reports"
android:selectable="false"/>
<Preference android:key="security_logs"
+ android:order="260"
android:title="@string/enterprise_privacy_security_logs"
android:selectable="false"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/enterprise_privacy_exposure_changes_category"
+ android:order="300"
android:key="exposure_changes_category">
<Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$EnterpriseInstalledPackages"
+ android:order="310"
android:key="number_enterprise_installed_packages"
android:title="@string/enterprise_privacy_enterprise_installed_packages"/>
<Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionLocation"
+ android:order="320"
android:key="enterprise_privacy_number_location_access_packages"
android:title="@string/enterprise_privacy_location_access"/>
<Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionMicrophone"
+ android:order="330"
android:key="enterprise_privacy_number_microphone_access_packages"
android:title="@string/enterprise_privacy_microphone_access"/>
<Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionCamera"
+ android:order="340"
android:key="enterprise_privacy_number_camera_access_packages"
android:title="@string/enterprise_privacy_camera_access"/>
<Preference android:fragment="com.android.settings.enterprise.EnterpriseSetDefaultAppsListFragment"
+ android:order="350"
android:key="number_enterprise_set_default_apps"
android:title="@string/enterprise_privacy_enterprise_set_default_apps"/>
<Preference android:key="always_on_vpn_primary_user"
+ android:order="360"
android:selectable="false"/>
<Preference android:key="always_on_vpn_managed_profile"
+ android:order="370"
android:title="@string/enterprise_privacy_always_on_vpn_work"
android:selectable="false"/>
<Preference android:key="input_method"
+ android:order="380"
android:title="@string/enterprise_privacy_input_method"
android:selectable="false"/>
<Preference android:key="global_http_proxy"
+ android:order="390"
android:title="@string/enterprise_privacy_global_http_proxy"
android:selectable="false"/>
<Preference android:key="ca_certs_current_user"
+ android:order="400"
android:title="@string/enterprise_privacy_ca_certs_personal"
android:selectable="false"/>
<Preference android:key="ca_certs_managed_profile"
+ android:order="410"
android:title="@string/enterprise_privacy_ca_certs_work"
android:selectable="false"/>
</PreferenceCategory>
<PreferenceCategory android:key="device_access_category"
+ android:order="500"
android:title="@string/enterprise_privacy_device_access_category">
<Preference android:key="enterprise_privacy_lock_device"
+ android:order="510"
android:title="@string/enterprise_privacy_lock_device"
android:selectable="false"/>
<Preference android:key="enterprise_privacy_wipe_device"
+ android:order="520"
android:title="@string/enterprise_privacy_wipe_device"
android:selectable="false"/>
<Preference android:key="failed_password_wipe_current_user"
+ android:order="530"
android:title="@string/enterprise_privacy_failed_password_wipe_device"
android:selectable="false"/>
<Preference android:key="failed_password_wipe_managed_profile"
+ android:order="540"
android:title="@string/enterprise_privacy_failed_password_wipe_work"
android:selectable="false"/>
</PreferenceCategory>
diff --git a/res/xml/power_usage_detail.xml b/res/xml/power_usage_detail.xml
index 12c7e21..945ceed 100644
--- a/res/xml/power_usage_detail.xml
+++ b/res/xml/power_usage_detail.xml
@@ -26,7 +26,7 @@
android:order="-10000"
settings:allowDividerBelow="true"/>
- <com.android.settings.widget.ActionButtonPreference
+ <com.android.settingslib.widget.ActionButtonsPreference
android:key="action_buttons"
android:order="-9999"/>
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index d38a8e4..ee8613d 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -28,6 +28,7 @@
android:icon="@drawable/ic_media_stream"
android:title="@string/media_volume_option_title"
android:order="-180"
+ settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.notification.MediaVolumePreferenceController"/>
<!-- Media output switcher -->
@@ -44,6 +45,7 @@
android:icon="@drawable/ic_local_phone_24_lib"
android:title="@string/call_volume_option_title"
android:order="-170"
+ settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.notification.CallVolumePreferenceController"/>
<!-- Hands free profile output switcher -->
@@ -60,6 +62,7 @@
android:icon="@drawable/ic_notifications"
android:title="@string/ring_volume_option_title"
android:order="-160"
+ settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.notification.RingVolumePreferenceController"/>
@@ -69,6 +72,7 @@
android:icon="@*android:drawable/ic_audio_alarm"
android:title="@string/alarm_volume_option_title"
android:order="-150"
+ settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/>
<!-- Notification volume -->
diff --git a/res/xml/tts_settings.xml b/res/xml/tts_settings.xml
index e76cdb7..92bf5d7 100644
--- a/res/xml/tts_settings.xml
+++ b/res/xml/tts_settings.xml
@@ -50,7 +50,7 @@
android:defaultValue="100"
android:max="400"/>
- <com.android.settings.widget.ActionButtonPreference
+ <com.android.settingslib.widget.ActionButtonsPreference
android:key="action_buttons" />
</PreferenceCategory>
diff --git a/res/xml/wifi_network_details_fragment.xml b/res/xml/wifi_network_details_fragment.xml
index b33cb75..70bd194 100644
--- a/res/xml/wifi_network_details_fragment.xml
+++ b/res/xml/wifi_network_details_fragment.xml
@@ -27,25 +27,25 @@
settings:allowDividerBelow="true"/>
<!-- Buttons -->
- <com.android.settings.widget.ActionButtonPreference
+ <com.android.settingslib.widget.ActionButtonsPreference
android:key="buttons"
android:selectable="false" />
<!-- General Details Category -->
<PreferenceCategory
android:key="general_details_category" >
- <com.android.settings.wifi.WifiDetailPreference
+ <Preference
android:key="signal_strength"
android:title="@string/wifi_signal"
android:selectable="false"/>
- <com.android.settings.wifi.WifiDetailPreference
+ <Preference
android:key="frequency"
android:icon="@drawable/ic_frequency_antenna"
android:title="@string/wifi_frequency"
android:selectable="false"/>
- <com.android.settings.wifi.WifiDetailPreference
+ <Preference
android:key="security"
android:icon="@drawable/ic_security_lock_24dp"
android:title="@string/wifi_security"
@@ -60,6 +60,7 @@
<DropDownPreference
android:key="privacy"
+ android:icon="@drawable/ic_wifi_privacy_24dp"
android:title="@string/wifi_privacy_settings"
android:entries="@array/wifi_privacy_entries"
android:entryValues="@array/wifi_privacy_values"/>
@@ -69,30 +70,36 @@
<PreferenceCategory
android:key="ip_details_category"
android:title="@string/wifi_setup_detail">
- <com.android.settings.wifi.WifiDetailPreference
- android:key="mac_address"
- android:title="@string/wifi_advanced_mac_address_title"
- android:selectable="false"/>
- <com.android.settings.wifi.WifiDetailPreference
+ <Preference
+ android:key="mac_address"
+ android:title="@string/wifi_advanced_mac_address_title"
+ android:selectable="false"
+ settings:enableCopying="true"/>
+ <Preference
android:key="ip_address"
android:title="@string/wifi_ip_address"
- android:selectable="false"/>
- <com.android.settings.wifi.WifiDetailPreference
+ android:selectable="false"
+ settings:enableCopying="true"/>
+ <Preference
android:key="gateway"
android:title="@string/wifi_gateway"
- android:selectable="false"/>
- <com.android.settings.wifi.WifiDetailPreference
+ android:selectable="false"
+ settings:enableCopying="true"/>
+ <Preference
android:key="subnet_mask"
android:title="@string/wifi_details_subnet_mask"
- android:selectable="false"/>
- <com.android.settings.wifi.WifiDetailPreference
+ android:selectable="false"
+ settings:enableCopying="true"/>
+ <Preference
android:key="dns"
android:title="@string/wifi_details_dns"
- android:selectable="false"/>
- <com.android.settings.wifi.WifiDetailPreference
+ android:selectable="false"
+ settings:enableCopying="true"/>
+ <Preference
android:key="link_speed"
android:title="@string/wifi_speed"
- android:selectable="false"/>
+ android:selectable="false"
+ settings:enableCopying="true"/>
</PreferenceCategory>
<!-- IPv6 Details -->
diff --git a/res/xml/zen_mode_schedule_rule_settings.xml b/res/xml/zen_mode_schedule_rule_settings.xml
index d05bbd2..c257d87 100644
--- a/res/xml/zen_mode_schedule_rule_settings.xml
+++ b/res/xml/zen_mode_schedule_rule_settings.xml
@@ -43,4 +43,10 @@
android:summary="@string/zen_mode_schedule_alarm_summary"
android:order="99" />
+ <!-- Custom Do Not Disturb Setting-->
+ <Preference
+ android:key="zen_schedule_custom_setting"
+ android:title="@string/zen_mode_custom_behavior_title"
+ android:order="100" />
+
</PreferenceScreen>
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index 1f331d7..ca54b07 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -33,11 +33,11 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.Settings;
+import android.sysprop.VoldProperties;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.text.Editable;
@@ -400,7 +400,7 @@
super.onCreate(savedInstanceState);
// If we are not encrypted or encrypting, get out quickly.
- final String state = SystemProperties.get("vold.decrypt");
+ final String state = VoldProperties.decrypt().orElse("");
if (!isDebugView() && ("".equals(state) || DECRYPT_STATE.equals(state))) {
disableCryptKeeperComponent(this);
// Typically CryptKeeper is launched as the home app. We didn't
@@ -468,7 +468,7 @@
return;
}
- final String progress = SystemProperties.get("vold.encrypt_progress");
+ final String progress = VoldProperties.encrypt_progress().orElse("");
if (!"".equals(progress) || isDebugView(FORCE_VIEW_PROGRESS)) {
setContentView(R.layout.crypt_keeper_progress);
encryptionProgressInit();
@@ -636,7 +636,7 @@
}
private void updateProgress() {
- final String state = SystemProperties.get("vold.encrypt_progress");
+ final String state = VoldProperties.encrypt_progress().orElse("");
if ("error_partially_encrypted".equals(state)) {
showFactoryReset(false);
@@ -657,8 +657,7 @@
// Now try to get status as time remaining and replace as appropriate
Log.v(TAG, "Encryption progress: " + progress);
try {
- final String timeProperty = SystemProperties.get("vold.encrypt_time_remaining");
- int time = Integer.parseInt(timeProperty);
+ int time = VoldProperties.encrypt_time_remaining().get();
if (time >= 0) {
// Round up to multiple of 10 - this way display is less jerky
time = (time + 9) / 10 * 10;
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 97942fe..307bbc1 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -39,6 +39,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.sysprop.VoldProperties;
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
import android.util.Log;
@@ -440,7 +441,7 @@
}
private boolean isExtStorageEncrypted() {
- String state = SystemProperties.get("vold.decrypt");
+ String state = VoldProperties.decrypt().orElse("");
return !"".equals(state);
}
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 07f59e2..9b5fc00 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -35,7 +35,6 @@
import android.transition.TransitionManager;
import android.util.Log;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toolbar;
@@ -169,6 +168,10 @@
private Button mNextButton;
+ /**
+ * TODO(b/118444000): Remove this and all related code.
+ */
+ @Deprecated
private boolean mIsShowingDashboard;
private ViewGroup mContent;
@@ -241,9 +244,6 @@
// Getting Intent properties can only be done after the super.onCreate(...)
final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
- mIsShowingDashboard = TextUtils.equals(
- SettingsActivity.class.getName(), intent.getComponent().getClassName());
-
// This is a "Sub Settings" when:
// - this is a real SubSettings
// - or :settings:show_fragment_as_subsetting is passed to the Intent
@@ -256,6 +256,9 @@
setTheme(R.style.Theme_SubSettings);
}
+ mIsShowingDashboard = TextUtils.equals(
+ SettingsActivity.class.getName(), intent.getComponent().getClassName());
+
setContentView(mIsShowingDashboard ?
R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
@@ -276,7 +279,7 @@
setTitleFromBackStack();
}
} else {
- launchSettingFragment(initialFragmentName, isSubSettings, intent);
+ launchSettingFragment(initialFragmentName, intent);
}
final boolean deviceProvisioned = Utils.isDeviceProvisioned(this);
@@ -308,26 +311,20 @@
if (buttonBar != null) {
buttonBar.setVisibility(View.VISIBLE);
- Button backButton = (Button) findViewById(R.id.back_button);
- backButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- setResult(RESULT_CANCELED, null);
- finish();
- }
+ Button backButton = findViewById(R.id.back_button);
+ backButton.setOnClickListener(v -> {
+ setResult(RESULT_CANCELED, null);
+ finish();
});
- Button skipButton = (Button) findViewById(R.id.skip_button);
- skipButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- setResult(RESULT_OK, null);
- finish();
- }
+ Button skipButton = findViewById(R.id.skip_button);
+ skipButton.setOnClickListener(v -> {
+ setResult(RESULT_OK, null);
+ finish();
});
- mNextButton = (Button) findViewById(R.id.next_button);
- mNextButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- setResult(RESULT_OK, null);
- finish();
- }
+ mNextButton = findViewById(R.id.next_button);
+ mNextButton.setOnClickListener(v -> {
+ setResult(RESULT_OK, null);
+ finish();
});
// set our various button parameters
@@ -372,8 +369,8 @@
}
@VisibleForTesting
- void launchSettingFragment(String initialFragmentName, boolean isSubSettings, Intent intent) {
- if (!mIsShowingDashboard && initialFragmentName != null) {
+ void launchSettingFragment(String initialFragmentName, Intent intent) {
+ if (initialFragmentName != null) {
setTitleFromIntent(intent);
Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 61ce33d..61293c5 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -53,11 +53,11 @@
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.deviceinfo.StorageWizardMoveConfirm;
-import com.android.settings.widget.ActionButtonPreference;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.ApplicationsState.Callbacks;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
+import com.android.settingslib.widget.ActionButtonsPreference;
import com.android.settingslib.widget.LayoutPreference;
import java.util.Collections;
@@ -107,7 +107,7 @@
// Views related to cache info
@VisibleForTesting
- ActionButtonPreference mButtonsPref;
+ ActionButtonsPreference mButtonsPref;
private Preference mStorageUsed;
private Button mChangeStorageButton;
@@ -168,7 +168,7 @@
.setComputingString(R.string.computing_size)
.setErrorString(R.string.invalid_size_value)
.build();
- mButtonsPref = ((ActionButtonPreference) findPreference(KEY_HEADER_BUTTONS));
+ mButtonsPref = ((ActionButtonsPreference) findPreference(KEY_HEADER_BUTTONS));
mStorageUsed = findPreference(KEY_STORAGE_USED);
mChangeStorageButton = (Button) ((LayoutPreference) findPreference(KEY_CHANGE_STORAGE))
.findViewById(R.id.button);
diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
index 9740ecb..2e528a7 100644
--- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
@@ -54,7 +54,6 @@
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.widget.ActionButtonPreference;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.applications.AppUtils;
@@ -64,6 +63,7 @@
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.widget.ActionButtonsPreference;
import java.util.ArrayList;
import java.util.HashSet;
@@ -99,8 +99,9 @@
@VisibleForTesting
boolean mDisableAfterUninstall = false;
@VisibleForTesting
- ActionButtonPreference mButtonsPref;
+ ActionButtonsPreference mButtonsPref;
+ private final int mUserId;
private final int mRequestUninstall;
private final int mRequestRemoveDeviceAdmin;
private final DevicePolicyManager mDpm;
@@ -110,8 +111,8 @@
private final InstrumentedPreferenceFragment mFragment;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final ApplicationFeatureProvider mApplicationFeatureProvider;
- private final int mUserId;
+ private Intent mAppLaunchIntent;
private ApplicationsState.Session mSession;
private RestrictedLockUtils.EnforcedAdmin mAppsControlDisallowedAdmin;
@@ -144,6 +145,7 @@
mUserId = UserHandle.myUserId();
mRequestUninstall = requestUninstall;
mRequestRemoveDeviceAdmin = requestRemoveDeviceAdmin;
+ mAppLaunchIntent = mPm.getLaunchIntentForPackage(mPackageName);
if (packageName != null) {
mAppEntry = mState.getEntry(packageName, mUserId);
@@ -158,21 +160,25 @@
public int getAvailabilityStatus() {
// TODO(b/37313605): Re-enable once this controller supports instant apps
return mAppEntry != null && !AppUtils.isInstant(mAppEntry.info)
- ? AVAILABLE : DISABLED_FOR_USER ;
+ ? AVAILABLE : DISABLED_FOR_USER;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
if (isAvailable()) {
- mButtonsPref = ((ActionButtonPreference) screen.findPreference(KEY_ACTION_BUTTONS))
- .setButton1Text(R.string.uninstall_text)
- .setButton1Icon(R.drawable.ic_settings_delete)
- .setButton2Text(R.string.force_stop)
- .setButton2Icon(R.drawable.ic_settings_force_stop)
- .setButton1OnClickListener(new UninstallAndDisableButtonListener())
- .setButton2OnClickListener(new ForceStopButtonListener())
- .setButton2Enabled(false);
+ mButtonsPref = ((ActionButtonsPreference) screen.findPreference(
+ KEY_ACTION_BUTTONS))
+ .setButton1Text(R.string.launch_instant_app)
+ .setButton1Icon(R.drawable.ic_settings_open)
+ .setButton1OnClickListener(v -> launchApplication())
+ .setButton2Text(R.string.uninstall_text)
+ .setButton2Icon(R.drawable.ic_settings_delete)
+ .setButton2OnClickListener(new UninstallAndDisableButtonListener())
+ .setButton3Text(R.string.force_stop)
+ .setButton3Icon(R.drawable.ic_settings_force_stop)
+ .setButton3OnClickListener(new ForceStopButtonListener())
+ .setButton3Enabled(false);
}
}
@@ -361,6 +367,12 @@
}
@VisibleForTesting
+ void updateOpenButton() {
+ mAppLaunchIntent = mPm.getLaunchIntentForPackage(mPackageName);
+ mButtonsPref.setButton1Visible(mAppLaunchIntent != null);
+ }
+
+ @VisibleForTesting
void updateUninstallButton() {
final boolean isBundled = (mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
boolean enabled = true;
@@ -430,7 +442,7 @@
enabled = false;
}
- mButtonsPref.setButton1Enabled(enabled);
+ mButtonsPref.setButton2Enabled(enabled);
}
/**
@@ -484,7 +496,7 @@
} else {
Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
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_USER_HANDLE, UserHandle.getUserId(mAppEntry.info.uid));
Log.d(TAG, "Sending broadcast to query restart status for "
@@ -497,9 +509,9 @@
@VisibleForTesting
void updateForceStopButtonInner(boolean enabled) {
if (mAppsControlDisallowedBySystem) {
- mButtonsPref.setButton2Enabled(false);
+ mButtonsPref.setButton3Enabled(false);
} else {
- mButtonsPref.setButton2Enabled(enabled);
+ mButtonsPref.setButton3Enabled(enabled);
}
}
@@ -547,16 +559,16 @@
if (mHomePackages.contains(mAppEntry.info.packageName)
|| isSystemPackage(mActivity.getResources(), mPm, mPackageInfo)) {
// Disable button for core system applications.
- mButtonsPref.setButton1Text(R.string.uninstall_text)
- .setButton1Icon(R.drawable.ic_settings_delete);
+ mButtonsPref.setButton2Text(R.string.uninstall_text)
+ .setButton2Icon(R.drawable.ic_settings_delete);
} else if (mAppEntry.info.enabled && !isDisabledUntilUsed()) {
- mButtonsPref.setButton1Text(R.string.uninstall_text)
- .setButton1Icon(R.drawable.ic_settings_delete);
+ mButtonsPref.setButton2Text(R.string.uninstall_text)
+ .setButton2Icon(R.drawable.ic_settings_delete);
disableable = !mApplicationFeatureProvider.getKeepEnabledPackages()
.contains(mAppEntry.info.packageName);
} else {
- mButtonsPref.setButton1Text(R.string.install_text)
- .setButton1Icon(R.drawable.ic_settings_install);
+ mButtonsPref.setButton2Text(R.string.install_text)
+ .setButton2Icon(R.drawable.ic_settings_install);
disableable = true;
}
@@ -639,6 +651,7 @@
}
}
+ updateOpenButton();
updateUninstallButton();
updateForceStopButton();
@@ -663,6 +676,11 @@
mActivity.unregisterReceiver(mPackageRemovedReceiver);
}
+ private void launchApplication() {
+ if (mAppLaunchIntent != null) {
+ mContext.startActivityAsUser(mAppLaunchIntent, new UserHandle(mUserId));
+ }
+ }
/**
* Changes the status of disable/enable for a package
diff --git a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
index 9443c93..1bfcd7d 100644
--- a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceController.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -17,15 +17,10 @@
package com.android.settings.applications.appinfo;
import android.content.Context;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
import android.net.NetworkTemplate;
import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.text.format.DateUtils;
import android.text.format.Formatter;
-import android.util.FeatureFlagUtils;
import androidx.annotation.VisibleForTesting;
import androidx.loader.app.LoaderManager;
@@ -36,53 +31,35 @@
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
-import com.android.settings.core.FeatureFlags;
import com.android.settings.datausage.AppDataUsage;
-import com.android.settings.datausage.DataUsageList;
import com.android.settings.datausage.DataUsageUtils;
import com.android.settingslib.AppItem;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
-import com.android.settingslib.net.ChartData;
-import com.android.settingslib.net.ChartDataLoaderCompat;
+import com.android.settingslib.net.NetworkCycleDataForUid;
+import com.android.settingslib.net.NetworkCycleDataForUidLoader;
-/**
- * Deprecated in favor of {@link AppDataUsagePreferenceControllerV2}
- *
- * @deprecated
- */
-@Deprecated
+import java.util.List;
+
public class AppDataUsagePreferenceController extends AppInfoPreferenceControllerBase
- implements LoaderManager.LoaderCallbacks<ChartData>, LifecycleObserver, OnResume, OnPause {
+ implements LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>, LifecycleObserver,
+ OnResume, OnPause {
- private ChartData mChartData;
- private INetworkStatsSession mStatsSession;
+ private List<NetworkCycleDataForUid> mAppUsageData;
- public AppDataUsagePreferenceController(Context context,String key) {
+ public AppDataUsagePreferenceController(Context context, String key) {
super(context, key);
}
@Override
public int getAvailabilityStatus() {
- if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.DATA_USAGE_V2)) {
- return UNSUPPORTED_ON_DEVICE;
- }
return isBandwidthControlEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- if (isAvailable()) {
- final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
- try {
- mStatsSession = statsService.openSession();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
}
@Override
@@ -92,36 +69,42 @@
@Override
public void onResume() {
- if (mStatsSession != null) {
+ if (isAvailable()) {
final int uid = mParent.getAppEntry().info.uid;
final AppItem app = new AppItem(uid);
app.addUid(uid);
- mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA,
- ChartDataLoaderCompat.buildArgs(getTemplate(mContext), app),
+ mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA, null /* args */,
this);
}
}
@Override
public void onPause() {
- if (mStatsSession != null) {
+ if (isAvailable()) {
mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
}
}
@Override
- public Loader<ChartData> onCreateLoader(int id, Bundle args) {
- return new ChartDataLoaderCompat(mContext, mStatsSession, args);
+ public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
+ final NetworkTemplate template = getTemplate(mContext);
+ return NetworkCycleDataForUidLoader.builder(mContext)
+ .setUid(mParent.getAppEntry().info.uid)
+ .setRetrieveDetail(false)
+ .setNetworkTemplate(template)
+ .setSubscriberId(template.getSubscriberId())
+ .build();
}
@Override
- public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
- mChartData = data;
+ public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
+ List<NetworkCycleDataForUid> data) {
+ mAppUsageData = data;
updateState(mPreference);
}
@Override
- public void onLoaderReset(Loader<ChartData> loader) {
+ public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
// Leave last result.
}
@@ -131,14 +114,22 @@
}
private CharSequence getDataSummary() {
- if (mChartData != null) {
- final long totalBytes = mChartData.detail.getTotalBytes();
+ if (mAppUsageData != null) {
+ long totalBytes = 0;
+ long startTime = System.currentTimeMillis();
+ for (NetworkCycleDataForUid data : mAppUsageData) {
+ totalBytes += data.getTotalUsage();
+ final long cycleStart = data.getStartTime();
+ if (cycleStart < startTime) {
+ startTime = cycleStart;
+ }
+ }
if (totalBytes == 0) {
return mContext.getString(R.string.no_data_usage);
}
return mContext.getString(R.string.data_summary_format,
Formatter.formatFileSize(mContext, totalBytes),
- DateUtils.formatDateTime(mContext, mChartData.detail.getStart(),
+ DateUtils.formatDateTime(mContext, startTime,
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH));
}
return mContext.getString(R.string.computing_size);
diff --git a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java b/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java
deleted file mode 100644
index 9bbc5c0..0000000
--- a/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications.appinfo;
-
-import android.content.Context;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.text.format.DateUtils;
-import android.text.format.Formatter;
-import android.util.FeatureFlagUtils;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.loader.app.LoaderManager;
-import androidx.loader.content.Loader;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.Utils;
-import com.android.settings.core.FeatureFlags;
-import com.android.settings.datausage.AppDataUsageV2;
-import com.android.settings.datausage.DataUsageUtils;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
-import com.android.settingslib.net.NetworkCycleDataForUid;
-import com.android.settingslib.net.NetworkCycleDataForUidLoader;
-
-import java.util.List;
-
-public class AppDataUsagePreferenceControllerV2 extends AppInfoPreferenceControllerBase
- implements LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>, LifecycleObserver,
- OnResume, OnPause {
-
- private List<NetworkCycleDataForUid> mAppUsageData;
-
- public AppDataUsagePreferenceControllerV2(Context context, String key) {
- super(context, key);
- }
-
- @Override
- public int getAvailabilityStatus() {
- if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlags.DATA_USAGE_V2)) {
- return UNSUPPORTED_ON_DEVICE;
- }
- return isBandwidthControlEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- }
-
- @Override
- public void updateState(Preference preference) {
- preference.setSummary(getDataSummary());
- }
-
- @Override
- public void onResume() {
- if (isAvailable()) {
- final int uid = mParent.getAppEntry().info.uid;
- final AppItem app = new AppItem(uid);
- app.addUid(uid);
- mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA, null /* args */,
- this);
- }
- }
-
- @Override
- public void onPause() {
- if (isAvailable()) {
- mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
- }
- }
-
- @Override
- public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
- final NetworkTemplate template = getTemplate(mContext);
- return NetworkCycleDataForUidLoader.builder(mContext)
- .setUid(mParent.getAppEntry().info.uid)
- .setRetrieveDetail(false)
- .setNetworkTemplate(template)
- .setSubscriberId(template.getSubscriberId())
- .build();
- }
-
- @Override
- public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
- List<NetworkCycleDataForUid> data) {
- mAppUsageData = data;
- updateState(mPreference);
- }
-
- @Override
- public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
- // Leave last result.
- }
-
- @Override
- protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
- return AppDataUsageV2.class;
- }
-
- private CharSequence getDataSummary() {
- if (mAppUsageData != null) {
- long totalBytes = 0;
- long startTime = System.currentTimeMillis();
- for (NetworkCycleDataForUid data : mAppUsageData) {
- totalBytes += data.getTotalUsage();
- final long cycleStart = data.getStartTime();
- if (cycleStart < startTime) {
- startTime = cycleStart;
- }
- }
- if (totalBytes == 0) {
- return mContext.getString(R.string.no_data_usage);
- }
- return mContext.getString(R.string.data_summary_format,
- Formatter.formatFileSize(mContext, totalBytes),
- DateUtils.formatDateTime(mContext, startTime,
- DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH));
- }
- return mContext.getString(R.string.computing_size);
- }
-
- private static NetworkTemplate getTemplate(Context context) {
- if (DataUsageUtils.hasReadyMobileRadio(context)) {
- return NetworkTemplate.buildTemplateMobileWildcard();
- }
- if (DataUsageUtils.hasWifiRadio(context)) {
- return NetworkTemplate.buildTemplateWifiWildcard();
- }
- return NetworkTemplate.buildTemplateEthernet();
- }
-
- @VisibleForTesting
- boolean isBandwidthControlEnabled() {
- return Utils.isBandwidthControlEnabled();
- }
-
-}
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index 32880d3..80cc6ae 100755
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -34,7 +34,6 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -49,7 +48,6 @@
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.applications.specialaccess.pictureinpicture
.PictureInPictureDetailPreferenceController;
-import com.android.settings.core.FeatureFlags;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -141,11 +139,7 @@
final String packageName = getPackageName();
use(TimeSpentInAppPreferenceController.class).setPackageName(packageName);
- if (FeatureFlagUtils.isEnabled(context, FeatureFlags.DATA_USAGE_V2)) {
- use(AppDataUsagePreferenceControllerV2.class).setParentFragment(this);
- } else {
- use(AppDataUsagePreferenceController.class).setParentFragment(this);
- }
+ use(AppDataUsagePreferenceController.class).setParentFragment(this);
final AppInstallerInfoPreferenceController installer =
use(AppInstallerInfoPreferenceController.class);
installer.setPackageName(packageName);
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
index 563a06a..a438f09 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
@@ -22,9 +22,9 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
-import com.android.settings.widget.ActionButtonPreference;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.ActionButtonsPreference;
/**
* This class adds two buttons: one to connect/disconnect from a device (depending on the current
@@ -35,7 +35,7 @@
private boolean mIsConnected;
private boolean mConnectButtonInitialized;
- private ActionButtonPreference mActionButtons;
+ private ActionButtonsPreference mActionButtons;
public BluetoothDetailsButtonsController(Context context, PreferenceFragmentCompat fragment,
CachedBluetoothDevice device, Lifecycle lifecycle) {
@@ -51,7 +51,8 @@
@Override
protected void init(PreferenceScreen screen) {
- mActionButtons = ((ActionButtonPreference) screen.findPreference(getPreferenceKey()))
+ mActionButtons = ((ActionButtonsPreference) screen.findPreference(
+ getPreferenceKey()))
.setButton1Text(R.string.forget)
.setButton1Icon(R.drawable.ic_settings_delete)
.setButton1OnClickListener((view) -> onForgetButtonPressed())
@@ -76,7 +77,7 @@
if (!mConnectButtonInitialized || previouslyConnected) {
mActionButtons
.setButton2Text(R.string.bluetooth_device_context_connect)
- // TODO (b/119646923) Icon is not ready.
+ .setButton2Icon(R.drawable.ic_add_24dp)
.setButton2OnClickListener(
view -> mCachedDevice.connect(true /* connectAllProfiles */));
mConnectButtonInitialized = true;
diff --git a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
index 1462f91..67e8b19 100644
--- a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
+++ b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
@@ -20,7 +20,6 @@
import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -37,6 +36,7 @@
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.connecteddevice.BluetoothDashboardFragment;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
@@ -48,16 +48,6 @@
private static final String TAG = "BluetoothSliceBuilder";
/**
- * Backing Uri for the Bluetooth Slice.
- */
- public static final Uri BLUETOOTH_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSlicesContract.AUTHORITY)
- .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
- .appendPath(SettingsSlicesContract.KEY_BLUETOOTH)
- .build();
-
- /**
* Action notifying a change on the BluetoothSlice.
*/
public static final String ACTION_BLUETOOTH_SLICE_CHANGED =
@@ -74,7 +64,7 @@
}
/**
- * Return a Bluetooth Slice bound to {@link #BLUETOOTH_URI}.
+ * Return a Bluetooth Slice bound to {@link CustomSliceRegistry#BLUETOOTH_URI}.
* <p>
* Note that you should register a listener for {@link #INTENT_FILTER} to get changes for
* Bluetooth.
@@ -88,11 +78,12 @@
context).getDefaultColor();
final PendingIntent toggleAction = getBroadcastIntent(context);
final PendingIntent primaryAction = getPrimaryAction(context);
- final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
- final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
- isBluetoothEnabled);
+ final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
+ ListBuilder.ICON_IMAGE, title);
+ final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
+ null /* actionTitle */, isBluetoothEnabled);
- return new ListBuilder(context, BLUETOOTH_URI, ListBuilder.INFINITY)
+ return new ListBuilder(context, CustomSliceRegistry.BLUETOOTH_URI, ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index 0a26b79..daa1e7b 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -24,7 +24,6 @@
public static final String DYNAMIC_HOMEPAGE = "settings_dynamic_homepage";
public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
public static final String MOBILE_NETWORK_V2 = "settings_mobile_network_v2";
- public static final String DATA_USAGE_V2 = "settings_data_usage_v2";
public static final String WIFI_MAC_RANDOMIZATION = "settings_wifi_mac_randomization";
public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2";
}
diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
index 8b5d521..2f447d4 100644
--- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
+++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
@@ -28,6 +28,7 @@
import com.android.settings.development.DevelopmentSettingsDashboardFragment;
import com.android.settings.deviceinfo.StorageDashboardFragment;
import com.android.settings.display.NightDisplaySettings;
+import com.android.settings.enterprise.EnterprisePrivacySettings;
import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.gestures.GestureSettings;
import com.android.settings.homepage.TopLevelSettings;
@@ -107,6 +108,8 @@
CategoryKey.CATEGORY_NIGHT_DISPLAY);
PARENT_TO_CATEGORY_KEY_MAP.put(PrivacyDashboardFragment.class.getName(),
CategoryKey.CATEGORY_PRIVACY);
+ PARENT_TO_CATEGORY_KEY_MAP.put(EnterprisePrivacySettings.class.getName(),
+ CategoryKey.CATEGORY_ENTERPRISE_PRIVACY);
CATEGORY_KEY_TO_PARENT_MAP = new ArrayMap<>(PARENT_TO_CATEGORY_KEY_MAP.size());
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index 78aa6c2..b6c95dd 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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
@@ -22,13 +22,8 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
-import android.net.INetworkStatsSession;
-import android.net.NetworkPolicy;
-import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
-import android.net.TrafficStats;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.IconDrawableFactory;
@@ -51,11 +46,13 @@
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.net.ChartData;
-import com.android.settingslib.net.ChartDataLoaderCompat;
+import com.android.settingslib.net.NetworkCycleDataForUid;
+import com.android.settingslib.net.NetworkCycleDataForUidLoader;
import com.android.settingslib.net.UidDetail;
import com.android.settingslib.net.UidDetailProvider;
+import java.util.List;
+
public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceChangeListener,
DataSaverBackend.Listener {
@@ -73,7 +70,7 @@
private static final String KEY_CYCLE = "cycle";
private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver";
- private static final int LOADER_CHART_DATA = 2;
+ private static final int LOADER_APP_USAGE_DATA = 2;
private static final int LOADER_APP_PREF = 3;
private PackageManager mPackageManager;
@@ -88,14 +85,10 @@
private Drawable mIcon;
private CharSequence mLabel;
private String mPackageName;
- private INetworkStatsSession mStatsSession;
private CycleAdapter mCycleAdapter;
- private long mStart;
- private long mEnd;
- private ChartData mChartData;
+ private List<NetworkCycleDataForUid> mUsageData;
private NetworkTemplate mTemplate;
- private NetworkPolicy mPolicy;
private AppItem mAppItem;
private Intent mAppSettingsIntent;
private SpinnerPreference mCycle;
@@ -108,12 +101,6 @@
mPackageManager = getPackageManager();
final Bundle args = getArguments();
- try {
- mStatsSession = services.mStatsService.openSession();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
-
mAppItem = (args != null) ? (AppItem) args.getParcelable(ARG_APP_ITEM) : null;
mTemplate = (args != null) ? (NetworkTemplate) args.getParcelable(ARG_NETWORK_TEMPLATE)
: null;
@@ -210,20 +197,13 @@
}
@Override
- public void onDestroy() {
- TrafficStats.closeQuietly(mStatsSession);
- super.onDestroy();
- }
-
- @Override
public void onResume() {
super.onResume();
if (mDataSaverBackend != null) {
mDataSaverBackend.addListener(this);
}
- mPolicy = services.mPolicyEditor.getPolicy(mTemplate);
- LoaderManager.getInstance(this).restartLoader(LOADER_CHART_DATA,
- ChartDataLoaderCompat.buildArgs(mTemplate, mAppItem), mChartDataCallbacks);
+ LoaderManager.getInstance(this).restartLoader(LOADER_APP_USAGE_DATA, null /* args */,
+ mUidDataCallbacks);
updatePrefs();
}
@@ -301,19 +281,17 @@
}
}
- private void bindData() {
+ @VisibleForTesting
+ void bindData(int position) {
final long backgroundBytes, foregroundBytes;
- if (mChartData == null || mStart == 0) {
+ if (mUsageData == null || position >= mUsageData.size()) {
backgroundBytes = foregroundBytes = 0;
mCycle.setVisible(false);
} else {
mCycle.setVisible(true);
- final long now = System.currentTimeMillis();
- NetworkStatsHistory.Entry entry = null;
- entry = mChartData.detailDefault.getValues(mStart, mEnd, now, entry);
- backgroundBytes = entry.rxBytes + entry.txBytes;
- entry = mChartData.detailForeground.getValues(mStart, mEnd, now, entry);
- foregroundBytes = entry.rxBytes + entry.txBytes;
+ final NetworkCycleDataForUid data = mUsageData.get(position);
+ backgroundBytes = data.getBackgroudUsage();
+ foregroundBytes = data.getForegroudUsage();
}
final long totalBytes = backgroundBytes + foregroundBytes;
final Context context = getContext();
@@ -377,11 +355,7 @@
new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem) mCycle.getSelectedItem();
-
- mStart = cycle.start;
- mEnd = cycle.end;
- bindData();
+ bindData(position);
}
@Override
@@ -390,24 +364,30 @@
}
};
- private final LoaderManager.LoaderCallbacks<ChartData> mChartDataCallbacks =
- new LoaderManager.LoaderCallbacks<ChartData>() {
- @Override
- public Loader<ChartData> onCreateLoader(int id, Bundle args) {
- return new ChartDataLoaderCompat(getActivity(), mStatsSession, args);
- }
+ private final LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>> mUidDataCallbacks =
+ new LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>() {
+ @Override
+ public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
+ return NetworkCycleDataForUidLoader.builder(getContext())
+ .setUid(mAppItem.key)
+ .setRetrieveDetail(true)
+ .setNetworkTemplate(mTemplate)
+ .setSubscriberId(mTemplate.getSubscriberId())
+ .build();
+ }
- @Override
- public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
- mChartData = data;
- mCycleAdapter.updateCycleList(mPolicy, mChartData);
- bindData();
- }
+ @Override
+ public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
+ List<NetworkCycleDataForUid> data) {
+ mUsageData = data;
+ mCycleAdapter.updateCycleList(data);
+ bindData(0 /* position */);
+ }
- @Override
- public void onLoaderReset(Loader<ChartData> loader) {
- }
- };
+ @Override
+ public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
+ }
+ };
private final LoaderManager.LoaderCallbacks<ArraySet<Preference>> mAppPrefCallbacks =
new LoaderManager.LoaderCallbacks<ArraySet<Preference>>() {
diff --git a/src/com/android/settings/datausage/AppDataUsageV2.java b/src/com/android/settings/datausage/AppDataUsageV2.java
deleted file mode 100644
index 6a31726..0000000
--- a/src/com/android/settings/datausage/AppDataUsageV2.java
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.settings.datausage;
-
-import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.util.ArraySet;
-import android.util.IconDrawableFactory;
-import android.util.Log;
-import android.view.View;
-import android.widget.AdapterView;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.loader.app.LoaderManager;
-import androidx.loader.content.Loader;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
-import androidx.preference.PreferenceCategory;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.applications.AppInfoBase;
-import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.net.NetworkCycleDataForUid;
-import com.android.settingslib.net.NetworkCycleDataForUidLoader;
-import com.android.settingslib.net.UidDetail;
-import com.android.settingslib.net.UidDetailProvider;
-
-import java.util.List;
-
-public class AppDataUsageV2 extends DataUsageBaseFragment implements OnPreferenceChangeListener,
- DataSaverBackend.Listener {
-
- private static final String TAG = "AppDataUsageV2";
-
- public static final String ARG_APP_ITEM = "app_item";
- public static final String ARG_NETWORK_TEMPLATE = "network_template";
-
- private static final String KEY_TOTAL_USAGE = "total_usage";
- private static final String KEY_FOREGROUND_USAGE = "foreground_usage";
- private static final String KEY_BACKGROUND_USAGE = "background_usage";
- private static final String KEY_APP_SETTINGS = "app_settings";
- private static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
- private static final String KEY_APP_LIST = "app_list";
- private static final String KEY_CYCLE = "cycle";
- private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver";
-
- private static final int LOADER_APP_USAGE_DATA = 2;
- private static final int LOADER_APP_PREF = 3;
-
- private PackageManager mPackageManager;
- private final ArraySet<String> mPackages = new ArraySet<>();
- private Preference mTotalUsage;
- private Preference mForegroundUsage;
- private Preference mBackgroundUsage;
- private Preference mAppSettings;
- private RestrictedSwitchPreference mRestrictBackground;
- private PreferenceCategory mAppList;
-
- private Drawable mIcon;
- private CharSequence mLabel;
- private String mPackageName;
- private CycleAdapter mCycleAdapter;
-
- private List<NetworkCycleDataForUid> mUsageData;
- private NetworkTemplate mTemplate;
- private AppItem mAppItem;
- private Intent mAppSettingsIntent;
- private SpinnerPreference mCycle;
- private RestrictedSwitchPreference mUnrestrictedData;
- private DataSaverBackend mDataSaverBackend;
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- mPackageManager = getPackageManager();
- final Bundle args = getArguments();
-
- mAppItem = (args != null) ? (AppItem) args.getParcelable(ARG_APP_ITEM) : null;
- mTemplate = (args != null) ? (NetworkTemplate) args.getParcelable(ARG_NETWORK_TEMPLATE)
- : null;
- if (mTemplate == null) {
- Context context = getContext();
- mTemplate = DataUsageUtils.getDefaultTemplate(context,
- DataUsageUtils.getDefaultSubscriptionId(context));
- }
- if (mAppItem == null) {
- int uid = (args != null) ? args.getInt(AppInfoBase.ARG_PACKAGE_UID, -1)
- : getActivity().getIntent().getIntExtra(AppInfoBase.ARG_PACKAGE_UID, -1);
- if (uid == -1) {
- // TODO: Log error.
- getActivity().finish();
- } else {
- addUid(uid);
- mAppItem = new AppItem(uid);
- mAppItem.addUid(uid);
- }
- } else {
- for (int i = 0; i < mAppItem.uids.size(); i++) {
- addUid(mAppItem.uids.keyAt(i));
- }
- }
-
- mTotalUsage = findPreference(KEY_TOTAL_USAGE);
- mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE);
- mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE);
-
- mCycle = (SpinnerPreference) findPreference(KEY_CYCLE);
- mCycleAdapter = new CycleAdapter(getContext(), mCycle, mCycleListener);
-
- if (mAppItem.key > 0) {
- if (mPackages.size() != 0) {
- try {
- ApplicationInfo info = mPackageManager.getApplicationInfoAsUser(
- mPackages.valueAt(0), 0, UserHandle.getUserId(mAppItem.key));
- mIcon = IconDrawableFactory.newInstance(getActivity()).getBadgedIcon(info);
- mLabel = info.loadLabel(mPackageManager);
- mPackageName = info.packageName;
- } catch (PackageManager.NameNotFoundException e) {
- }
- }
- if (!UserHandle.isApp(mAppItem.key)) {
- removePreference(KEY_UNRESTRICTED_DATA);
- removePreference(KEY_RESTRICT_BACKGROUND);
- } else {
- mRestrictBackground = (RestrictedSwitchPreference) findPreference(
- KEY_RESTRICT_BACKGROUND);
- mRestrictBackground.setOnPreferenceChangeListener(this);
- mUnrestrictedData = (RestrictedSwitchPreference) findPreference(
- KEY_UNRESTRICTED_DATA);
- mUnrestrictedData.setOnPreferenceChangeListener(this);
- }
- mDataSaverBackend = new DataSaverBackend(getContext());
- mAppSettings = findPreference(KEY_APP_SETTINGS);
-
- mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
- mAppSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
-
- PackageManager pm = getPackageManager();
- boolean matchFound = false;
- for (String packageName : mPackages) {
- mAppSettingsIntent.setPackage(packageName);
- if (pm.resolveActivity(mAppSettingsIntent, 0) != null) {
- matchFound = true;
- break;
- }
- }
- if (!matchFound) {
- removePreference(KEY_APP_SETTINGS);
- mAppSettings = null;
- }
-
- if (mPackages.size() > 1) {
- mAppList = (PreferenceCategory) findPreference(KEY_APP_LIST);
- LoaderManager.getInstance(this).restartLoader(LOADER_APP_PREF, Bundle.EMPTY,
- mAppPrefCallbacks);
- } else {
- removePreference(KEY_APP_LIST);
- }
- } else {
- final Context context = getActivity();
- UidDetail uidDetail = new UidDetailProvider(context).getUidDetail(mAppItem.key, true);
- mIcon = uidDetail.icon;
- mLabel = uidDetail.label;
- mPackageName = context.getPackageName();
-
- removePreference(KEY_UNRESTRICTED_DATA);
- removePreference(KEY_APP_SETTINGS);
- removePreference(KEY_RESTRICT_BACKGROUND);
- removePreference(KEY_APP_LIST);
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- if (mDataSaverBackend != null) {
- mDataSaverBackend.addListener(this);
- }
- LoaderManager.getInstance(this).restartLoader(LOADER_APP_USAGE_DATA, null /* args */,
- mUidDataCallbacks);
- updatePrefs();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- if (mDataSaverBackend != null) {
- mDataSaverBackend.remListener(this);
- }
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (preference == mRestrictBackground) {
- mDataSaverBackend.setIsBlacklisted(mAppItem.key, mPackageName, !(Boolean) newValue);
- updatePrefs();
- return true;
- } else if (preference == mUnrestrictedData) {
- mDataSaverBackend.setIsWhitelisted(mAppItem.key, mPackageName, (Boolean) newValue);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean onPreferenceTreeClick(Preference preference) {
- if (preference == mAppSettings) {
- // TODO: target towards entire UID instead of just first package
- getActivity().startActivityAsUser(mAppSettingsIntent, new UserHandle(
- UserHandle.getUserId(mAppItem.key)));
- return true;
- }
- return super.onPreferenceTreeClick(preference);
- }
-
- @Override
- protected int getPreferenceScreenResId() {
- return R.xml.app_data_usage;
- }
-
- @Override
- protected String getLogTag() {
- return TAG;
- }
-
- @VisibleForTesting
- void updatePrefs() {
- updatePrefs(getAppRestrictBackground(), getUnrestrictData());
- }
-
- private void updatePrefs(boolean restrictBackground, boolean unrestrictData) {
- final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfMeteredDataRestricted(
- getContext(), mPackageName, UserHandle.getUserId(mAppItem.key));
- if (mRestrictBackground != null) {
- mRestrictBackground.setChecked(!restrictBackground);
- mRestrictBackground.setDisabledByAdmin(admin);
- }
- if (mUnrestrictedData != null) {
- if (restrictBackground) {
- mUnrestrictedData.setVisible(false);
- } else {
- mUnrestrictedData.setVisible(true);
- mUnrestrictedData.setChecked(unrestrictData);
- mUnrestrictedData.setDisabledByAdmin(admin);
- }
- }
- }
-
- private void addUid(int uid) {
- String[] packages = getPackageManager().getPackagesForUid(uid);
- if (packages != null) {
- for (int i = 0; i < packages.length; i++) {
- mPackages.add(packages[i]);
- }
- }
- }
-
- @VisibleForTesting
- void bindData(int position) {
- final long backgroundBytes, foregroundBytes;
- if (mUsageData == null || position >= mUsageData.size()) {
- backgroundBytes = foregroundBytes = 0;
- mCycle.setVisible(false);
- } else {
- mCycle.setVisible(true);
- final NetworkCycleDataForUid data = mUsageData.get(position);
- backgroundBytes = data.getBackgroudUsage();
- foregroundBytes = data.getForegroudUsage();
- }
- final long totalBytes = backgroundBytes + foregroundBytes;
- final Context context = getContext();
-
- mTotalUsage.setSummary(DataUsageUtils.formatDataUsage(context, totalBytes));
- mForegroundUsage.setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
- mBackgroundUsage.setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
- }
-
- private boolean getAppRestrictBackground() {
- final int uid = mAppItem.key;
- final int uidPolicy = services.mPolicyManager.getUidPolicy(uid);
- return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
- }
-
- private boolean getUnrestrictData() {
- if (mDataSaverBackend != null) {
- return mDataSaverBackend.isWhitelisted(mAppItem.key);
- }
- return false;
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- String pkg = mPackages.size() != 0 ? mPackages.valueAt(0) : null;
- int uid = 0;
- if (pkg != null) {
- try {
- uid = mPackageManager.getPackageUidAsUser(pkg,
- UserHandle.getUserId(mAppItem.key));
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Skipping UID because cannot find package " + pkg);
- }
- }
-
- final boolean showInfoButton = mAppItem.key > 0;
-
- final Activity activity = getActivity();
- final Preference pref = EntityHeaderController
- .newInstance(activity, this, null /* header */)
- .setRecyclerView(getListView(), getSettingsLifecycle())
- .setUid(uid)
- .setHasAppInfoLink(showInfoButton)
- .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
- EntityHeaderController.ActionType.ACTION_NONE)
- .setIcon(mIcon)
- .setLabel(mLabel)
- .setPackageName(pkg)
- .done(activity, getPrefContext());
- getPreferenceScreen().addPreference(pref);
- }
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.APP_DATA_USAGE;
- }
-
- private AdapterView.OnItemSelectedListener mCycleListener =
- new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- bindData(position);
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- // ignored
- }
- };
-
- private final LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>> mUidDataCallbacks =
- new LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>() {
- @Override
- public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
- return NetworkCycleDataForUidLoader.builder(getContext())
- .setUid(mAppItem.key)
- .setRetrieveDetail(true)
- .setNetworkTemplate(mTemplate)
- .setSubscriberId(mTemplate.getSubscriberId())
- .build();
- }
-
- @Override
- public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
- List<NetworkCycleDataForUid> data) {
- mUsageData = data;
- mCycleAdapter.updateCycleList(data);
- bindData(0 /* position */);
- }
-
- @Override
- public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
- }
- };
-
- private final LoaderManager.LoaderCallbacks<ArraySet<Preference>> mAppPrefCallbacks =
- new LoaderManager.LoaderCallbacks<ArraySet<Preference>>() {
- @Override
- public Loader<ArraySet<Preference>> onCreateLoader(int i, Bundle bundle) {
- return new AppPrefLoader(getPrefContext(), mPackages, getPackageManager());
- }
-
- @Override
- public void onLoadFinished(Loader<ArraySet<Preference>> loader,
- ArraySet<Preference> preferences) {
- if (preferences != null && mAppList != null) {
- for (Preference preference : preferences) {
- mAppList.addPreference(preference);
- }
- }
- }
-
- @Override
- public void onLoaderReset(Loader<ArraySet<Preference>> loader) {
- }
- };
-
- @Override
- public void onDataSaverChanged(boolean isDataSaving) {
-
- }
-
- @Override
- public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
- if (mAppItem.uids.get(uid, false)) {
- updatePrefs(getAppRestrictBackground(), isWhitelisted);
- }
- }
-
- @Override
- public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
- if (mAppItem.uids.get(uid, false)) {
- updatePrefs(isBlacklisted, getUnrestrictData());
- }
- }
-}
diff --git a/src/com/android/settings/datausage/ChartDataUsagePreference.java b/src/com/android/settings/datausage/ChartDataUsagePreference.java
index a0cef3a..1c8eb52 100644
--- a/src/com/android/settings/datausage/ChartDataUsagePreference.java
+++ b/src/com/android/settings/datausage/ChartDataUsagePreference.java
@@ -16,14 +16,12 @@
import android.content.Context;
import android.net.NetworkPolicy;
-import android.net.NetworkStatsHistory;
import android.net.TrafficStats;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
-import android.util.FeatureFlagUtils;
import android.util.SparseIntArray;
import androidx.annotation.VisibleForTesting;
@@ -32,7 +30,6 @@
import com.android.settings.R;
import com.android.settings.Utils;
-import com.android.settings.core.FeatureFlags;
import com.android.settings.widget.UsageView;
import com.android.settingslib.net.NetworkCycleChartData;
import com.android.settingslib.net.NetworkCycleData;
@@ -51,8 +48,6 @@
private NetworkPolicy mPolicy;
private long mStart;
private long mEnd;
- @Deprecated
- private NetworkStatsHistory mNetwork;
private NetworkCycleChartData mNetworkCycleChartData;
private int mSecondaryColor;
private int mSeriesColor;
@@ -69,24 +64,14 @@
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
final UsageView chart = (UsageView) holder.findViewById(R.id.data_usage);
- if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
- if (mNetworkCycleChartData == null) {
- return;
- }
- } else {
- if (mNetwork == null) {
- return;
- }
+ if (mNetworkCycleChartData == null) {
+ return;
}
final int top = getTop();
chart.clearPaths();
chart.configureGraph(toInt(mEnd - mStart), top);
- if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
- calcPoints(chart, mNetworkCycleChartData.getUsageBuckets());
- } else {
- calcPoints(chart);
- }
+ calcPoints(chart, mNetworkCycleChartData.getUsageBuckets());
chart.setBottomLabels(new CharSequence[] {
Utils.formatDateRange(getContext(), mStart, mStart),
Utils.formatDateRange(getContext(), mEnd, mEnd),
@@ -96,58 +81,12 @@
}
public int getTop() {
- long totalData = 0;
- if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
- totalData = mNetworkCycleChartData.getTotalUsage();
- } else {
- NetworkStatsHistory.Entry entry = null;
- final int start = mNetwork.getIndexBefore(mStart);
- final int end = mNetwork.getIndexAfter(mEnd);
-
- for (int i = start; i <= end; i++) {
- entry = mNetwork.getValues(i, entry);
-
- // increment by current bucket total
- totalData += entry.rxBytes + entry.txBytes;
- }
- }
- long policyMax = mPolicy != null ? Math.max(mPolicy.limitBytes, mPolicy.warningBytes) : 0;
+ final long totalData = mNetworkCycleChartData.getTotalUsage();
+ final long policyMax =
+ mPolicy != null ? Math.max(mPolicy.limitBytes, mPolicy.warningBytes) : 0;
return (int) (Math.max(totalData, policyMax) / RESOLUTION);
}
- @Deprecated
- @VisibleForTesting
- void calcPoints(UsageView chart) {
- SparseIntArray points = new SparseIntArray();
- NetworkStatsHistory.Entry entry = null;
-
- long totalData = 0;
-
- final int start = mNetwork.getIndexAfter(mStart);
- final int end = mNetwork.getIndexAfter(mEnd);
- if (start < 0) return;
-
- points.put(0, 0);
- for (int i = start; i <= end; i++) {
- entry = mNetwork.getValues(i, entry);
-
- final long startTime = entry.bucketStart;
- final long endTime = startTime + entry.bucketDuration;
-
- // increment by current bucket total
- totalData += entry.rxBytes + entry.txBytes;
-
- if (i == 0) {
- points.put(toInt(startTime - mStart) - 1, -1);
- }
- points.put(toInt(startTime - mStart + 1), (int) (totalData / RESOLUTION));
- points.put(toInt(endTime - mStart), (int) (totalData / RESOLUTION));
- }
- if (points.size() > 1) {
- chart.addPath(points);
- }
- }
-
@VisibleForTesting
void calcPoints(UsageView chart, List<NetworkCycleData> usageSummary) {
if (usageSummary == null) {
@@ -220,13 +159,6 @@
notifyChanged();
}
- @Deprecated
- public void setVisibleRange(long start, long end) {
- mStart = start;
- mEnd = end;
- notifyChanged();
- }
-
public long getInspectStart() {
return mStart;
}
@@ -235,12 +167,6 @@
return mEnd;
}
- @Deprecated
- public void setNetworkStats(NetworkStatsHistory network) {
- mNetwork = network;
- notifyChanged();
- }
-
public void setNetworkCycleData(NetworkCycleChartData data) {
mNetworkCycleChartData = data;
mStart = data.getStartTime();
diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java
index 8f0026f..326b0d4 100644
--- a/src/com/android/settings/datausage/DataUsageList.java
+++ b/src/com/android/settings/datausage/DataUsageList.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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
@@ -15,20 +15,22 @@
package com.android.settings.datausage;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
+import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
+import android.app.Activity;
import android.app.ActivityManager;
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStats.Bucket;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.Color;
-import android.net.INetworkStatsSession;
+import android.net.ConnectivityManager;
import android.net.NetworkPolicy;
-import android.net.NetworkStats;
-import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
-import android.net.TrafficStats;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
@@ -37,6 +39,7 @@
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
import android.util.Log;
import android.util.SparseArray;
@@ -58,9 +61,9 @@
import com.android.settings.datausage.CycleAdapter.SpinnerInterface;
import com.android.settings.widget.LoadingViewController;
import com.android.settingslib.AppItem;
-import com.android.settingslib.net.ChartData;
-import com.android.settingslib.net.ChartDataLoaderCompat;
-import com.android.settingslib.net.SummaryForAllUidLoaderCompat;
+import com.android.settingslib.net.NetworkCycleChartDataLoader;
+import com.android.settingslib.net.NetworkCycleChartData;
+import com.android.settingslib.net.NetworkStatsSummaryLoader;
import com.android.settingslib.net.UidDetailProvider;
import java.util.ArrayList;
@@ -70,16 +73,12 @@
/**
* Panel showing data usage history across various networks, including options
* to inspect based on usage cycle and control through {@link NetworkPolicy}.
-
- * Deprecated in favor of {@link DataUsageListV2}
- *
- * @deprecated
*/
-@Deprecated
public class DataUsageList extends DataUsageBaseFragment {
- public static final String EXTRA_SUB_ID = "sub_id";
- public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
+ static final String EXTRA_SUB_ID = "sub_id";
+ static final String EXTRA_NETWORK_TEMPLATE = "network_template";
+ static final String EXTRA_NETWORK_TYPE = "network_type";
private static final String TAG = "DataUsageList";
private static final boolean LOGD = false;
@@ -87,6 +86,9 @@
private static final String KEY_USAGE_AMOUNT = "usage_amount";
private static final String KEY_CHART_DATA = "chart_data";
private static final String KEY_APPS_GROUP = "apps_group";
+ private static final String KEY_TEMPLATE = "template";
+ private static final String KEY_APP = "app";
+ private static final String KEY_FIELDS = "fields";
private static final int LOADER_CHART_DATA = 2;
private static final int LOADER_SUMMARY = 3;
@@ -99,14 +101,16 @@
}
};
- private INetworkStatsSession mStatsSession;
private ChartDataUsagePreference mChart;
+ private TelephonyManager mTelephonyManager;
@VisibleForTesting
NetworkTemplate mTemplate;
@VisibleForTesting
int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- private ChartData mChartData;
+ @VisibleForTesting
+ int mNetworkType;
+ private List<NetworkCycleChartData> mCycleData;
private LoadingViewController mLoadingViewController;
private UidDetailProvider mUidDetailProvider;
@@ -116,7 +120,6 @@
private PreferenceGroup mApps;
private View mHeader;
-
@Override
public int getMetricsCategory() {
return MetricsEvent.DATA_USAGE_LIST;
@@ -125,21 +128,15 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final Context context = getActivity();
+ final Activity activity = getActivity();
if (!isBandwidthControlEnabled()) {
Log.w(TAG, "No bandwidth control; leaving");
- getActivity().finish();
+ activity.finish();
}
- try {
- mStatsSession = services.mStatsService.openSession();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
-
- mUidDetailProvider = new UidDetailProvider(context);
-
+ mUidDetailProvider = new UidDetailProvider(activity);
+ mTelephonyManager = activity.getSystemService(TelephonyManager.class);
mUsageAmount = findPreference(KEY_USAGE_AMOUNT);
mChart = (ChartDataUsagePreference) findPreference(KEY_CHART_DATA);
mApps = (PreferenceGroup) findPreference(KEY_APPS_GROUP);
@@ -194,28 +191,6 @@
super.onResume();
mDataStateListener.setListener(true, mSubId, getContext());
updateBody();
-
- // kick off background task to update stats
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- try {
- // wait a few seconds before kicking off
- Thread.sleep(2 * DateUtils.SECOND_IN_MILLIS);
- services.mStatsService.forceUpdate();
- } catch (InterruptedException e) {
- } catch (RemoteException e) {
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- if (isAdded()) {
- updateBody();
- }
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@Override
@@ -229,8 +204,6 @@
mUidDetailProvider.clearCache();
mUidDetailProvider = null;
- TrafficStats.closeQuietly(mStatsSession);
-
super.onDestroy();
}
@@ -249,6 +222,7 @@
if (args != null) {
mSubId = args.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mTemplate = args.getParcelable(EXTRA_NETWORK_TEMPLATE);
+ mNetworkType = args.getInt(EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_MOBILE);
}
if (mTemplate == null && mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
final Intent intent = getIntent();
@@ -259,8 +233,7 @@
}
/**
- * Update body content based on current tab. Loads
- * {@link NetworkStatsHistory} and {@link NetworkPolicy} from system, and
+ * Update body content based on current tab. Loads network cycle data from system, and
* binds them to visible controls.
*/
private void updateBody() {
@@ -272,7 +245,7 @@
// TODO: consider chaining two loaders together instead of reloading
// network history when showing app detail.
getLoaderManager().restartLoader(LOADER_CHART_DATA,
- ChartDataLoaderCompat.buildArgs(mTemplate, null), mChartDataCallbacks);
+ buildArgs(mTemplate), mNetworkCycleDataCallbacks);
// detail mode can change visible menus, invalidate
getActivity().invalidateOptionsMenu();
@@ -292,6 +265,14 @@
mChart.setColors(seriesColor, secondaryColor);
}
+ private Bundle buildArgs(NetworkTemplate template) {
+ final Bundle args = new Bundle();
+ args.putParcelable(KEY_TEMPLATE, template);
+ args.putParcelable(KEY_APP, null);
+ args.putInt(KEY_FIELDS, FIELD_RX_BYTES | FIELD_TX_BYTES);
+ return args;
+ }
+
/**
* Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
* current {@link #mTemplate}.
@@ -311,7 +292,7 @@
}
// generate cycle list based on policy and available history
- if (mCycleAdapter.updateCycleList(policy, mChartData)) {
+ if (mCycleAdapter.updateCycleList(mCycleData)) {
updateDetailData();
}
}
@@ -324,23 +305,13 @@
private void updateDetailData() {
if (LOGD) Log.d(TAG, "updateDetailData()");
- final long start = mChart.getInspectStart();
- final long end = mChart.getInspectEnd();
- final long now = System.currentTimeMillis();
-
- final Context context = getActivity();
-
- NetworkStatsHistory.Entry entry = null;
- if (mChartData != null) {
- entry = mChartData.network.getValues(start, end, now, null);
- }
-
// kick off loader for detailed stats
- getLoaderManager().restartLoader(LOADER_SUMMARY,
- SummaryForAllUidLoaderCompat.buildArgs(mTemplate, start, end), mSummaryCallbacks);
+ getLoaderManager().restartLoader(LOADER_SUMMARY, null /* args */,
+ mNetworkStatsDetailCallbacks);
- final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
- final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(context, totalBytes);
+ final long totalBytes = mCycleData != null
+ ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getTotalUsage() : 0;
+ final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(getActivity(), totalBytes);
mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase));
}
@@ -348,22 +319,26 @@
* Bind the given {@link NetworkStats}, or {@code null} to clear list.
*/
private void bindStats(NetworkStats stats, int[] restrictedUids) {
- ArrayList<AppItem> items = new ArrayList<>();
+ mApps.removeAll();
+ if (stats == null) {
+ if (LOGD) {
+ Log.d(TAG, "No network stats data. App list cleared.");
+ }
+ return;
+ }
+
+ final ArrayList<AppItem> items = new ArrayList<>();
long largest = 0;
final int currentUserId = ActivityManager.getCurrentUser();
- UserManager userManager = UserManager.get(getContext());
+ final UserManager userManager = UserManager.get(getContext());
final List<UserHandle> profiles = userManager.getUserProfiles();
final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
- NetworkStats.Entry entry = null;
- final int size = stats != null ? stats.size() : 0;
- for (int i = 0; i < size; i++) {
- entry = stats.getValues(i, entry);
-
+ final Bucket bucket = new Bucket();
+ while (stats.hasNextBucket() && stats.getNextBucket(bucket)) {
// Decide how to collapse items together
- final int uid = entry.uid;
-
+ final int uid = bucket.getUid();
final int collapseKey;
final int category;
final int userId = UserHandle.getUserId(uid);
@@ -372,8 +347,8 @@
if (userId != currentUserId) {
// Add to a managed user item.
final int managedKey = UidDetailProvider.buildKeyForUser(userId);
- largest = accumulate(managedKey, knownItems, entry, AppItem.CATEGORY_USER,
- items, largest);
+ largest = accumulate(managedKey, knownItems, bucket,
+ AppItem.CATEGORY_USER, items, largest);
}
// Add to app item.
collapseKey = uid;
@@ -397,8 +372,9 @@
collapseKey = android.os.Process.SYSTEM_UID;
category = AppItem.CATEGORY_APP;
}
- largest = accumulate(collapseKey, knownItems, entry, category, items, largest);
+ largest = accumulate(collapseKey, knownItems, bucket, category, items, largest);
}
+ stats.close();
final int restrictedUidsMax = restrictedUids.length;
for (int i = 0; i < restrictedUidsMax; ++i) {
@@ -419,7 +395,6 @@
}
Collections.sort(items);
- mApps.removeAll();
for (int i = 0; i < items.size(); i++) {
final int percentTotal = largest != 0 ? (int) (items.get(i).total * 100 / largest) : 0;
AppDataUsagePreference preference = new AppDataUsagePreference(getContext(),
@@ -456,12 +431,12 @@
*
* @param collapseKey the collapse key used to map the item.
* @param knownItems collection of known (already existing) items.
- * @param entry the network stats entry to extract data usage from.
+ * @param bucket the network stats bucket to extract data usage from.
* @param itemCategory the item is categorized on the list view by this category. Must be
*/
- private long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
- NetworkStats.Entry entry, int itemCategory, ArrayList<AppItem> items, long largest) {
- final int uid = entry.uid;
+ private static long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
+ Bucket bucket, int itemCategory, ArrayList<AppItem> items, long largest) {
+ final int uid = bucket.getUid();
AppItem item = knownItems.get(collapseKey);
if (item == null) {
item = new AppItem(collapseKey);
@@ -470,7 +445,7 @@
knownItems.put(item.key, item);
}
item.addUid(uid);
- item.total += entry.rxBytes + entry.txBytes;
+ item.total += bucket.getRxBytes() + bucket.getTxBytes();
return Math.max(largest, item.total);
}
@@ -487,7 +462,7 @@
// update chart to show selected cycle, and update detail data
// to match updated sweep bounds.
- mChart.setVisibleRange(cycle.start, cycle.end);
+ mChart.setNetworkCycleData(mCycleData.get(position));
updateDetailData();
}
@@ -498,35 +473,41 @@
}
};
- private final LoaderCallbacks<ChartData> mChartDataCallbacks = new LoaderCallbacks<
- ChartData>() {
+ private final LoaderCallbacks<List<NetworkCycleChartData>> mNetworkCycleDataCallbacks =
+ new LoaderCallbacks<List<NetworkCycleChartData>>() {
@Override
- public Loader<ChartData> onCreateLoader(int id, Bundle args) {
- return new ChartDataLoaderCompat(getActivity(), mStatsSession, args);
+ public Loader<List<NetworkCycleChartData>> onCreateLoader(int id, Bundle args) {
+ return NetworkCycleChartDataLoader.builder(getContext())
+ .setNetworkTemplate(mTemplate)
+ .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
+ .build();
}
@Override
- public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
+ public void onLoadFinished(Loader<List<NetworkCycleChartData>> loader,
+ List<NetworkCycleChartData> data) {
mLoadingViewController.showContent(false /* animate */);
- mChartData = data;
- mChart.setNetworkStats(mChartData.network);
-
+ mCycleData = data;
// calculate policy cycles based on available data
updatePolicy();
}
@Override
- public void onLoaderReset(Loader<ChartData> loader) {
- mChartData = null;
- mChart.setNetworkStats(null);
+ public void onLoaderReset(Loader<List<NetworkCycleChartData>> loader) {
+ mCycleData = null;
}
};
- private final LoaderCallbacks<NetworkStats> mSummaryCallbacks = new LoaderCallbacks<
- NetworkStats>() {
+ private final LoaderCallbacks<NetworkStats> mNetworkStatsDetailCallbacks =
+ new LoaderCallbacks<NetworkStats>() {
@Override
public Loader<NetworkStats> onCreateLoader(int id, Bundle args) {
- return new SummaryForAllUidLoaderCompat(getActivity(), mStatsSession, args);
+ return new NetworkStatsSummaryLoader.Builder(getContext())
+ .setStartTime(mChart.getInspectStart())
+ .setEndTime(mChart.getInspectEnd())
+ .setNetworkType(mNetworkType)
+ .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
+ .build();
}
@Override
diff --git a/src/com/android/settings/datausage/DataUsageListV2.java b/src/com/android/settings/datausage/DataUsageListV2.java
deleted file mode 100644
index 4432fee..0000000
--- a/src/com/android/settings/datausage/DataUsageListV2.java
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.settings.datausage;
-
-import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static android.net.TrafficStats.UID_REMOVED;
-import static android.net.TrafficStats.UID_TETHERING;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.usage.NetworkStats;
-import android.app.usage.NetworkStats.Bucket;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.UserInfo;
-import android.graphics.Color;
-import android.net.ConnectivityManager;
-import android.net.NetworkPolicy;
-import android.net.NetworkTemplate;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.text.format.DateUtils;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.ImageView;
-import android.widget.Spinner;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.loader.app.LoaderManager.LoaderCallbacks;
-import androidx.loader.content.Loader;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.datausage.CycleAdapter.SpinnerInterface;
-import com.android.settings.widget.LoadingViewController;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.net.ChartDataLoaderCompat;
-import com.android.settingslib.net.NetworkCycleChartDataLoader;
-import com.android.settingslib.net.NetworkCycleChartData;
-import com.android.settingslib.net.NetworkStatsSummaryLoader;
-import com.android.settingslib.net.UidDetailProvider;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Panel showing data usage history across various networks, including options
- * to inspect based on usage cycle and control through {@link NetworkPolicy}.
- */
-public class DataUsageListV2 extends DataUsageBaseFragment {
-
- static final String EXTRA_SUB_ID = "sub_id";
- static final String EXTRA_NETWORK_TEMPLATE = "network_template";
- static final String EXTRA_NETWORK_TYPE = "network_type";
-
- private static final String TAG = "DataUsageListV2";
- private static final boolean LOGD = false;
-
- private static final String KEY_USAGE_AMOUNT = "usage_amount";
- private static final String KEY_CHART_DATA = "chart_data";
- private static final String KEY_APPS_GROUP = "apps_group";
-
- private static final int LOADER_CHART_DATA = 2;
- private static final int LOADER_SUMMARY = 3;
-
- private final CellDataPreference.DataStateListener mDataStateListener =
- new CellDataPreference.DataStateListener() {
- @Override
- public void onChange(boolean selfChange) {
- updatePolicy();
- }
- };
-
- private ChartDataUsagePreference mChart;
- private TelephonyManager mTelephonyManager;
-
- @VisibleForTesting
- NetworkTemplate mTemplate;
- @VisibleForTesting
- int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- @VisibleForTesting
- int mNetworkType;
- private List<NetworkCycleChartData> mCycleData;
-
- private LoadingViewController mLoadingViewController;
- private UidDetailProvider mUidDetailProvider;
- private CycleAdapter mCycleAdapter;
- private Spinner mCycleSpinner;
- private Preference mUsageAmount;
- private PreferenceGroup mApps;
- private View mHeader;
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.DATA_USAGE_LIST;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- final Activity activity = getActivity();
-
- if (!isBandwidthControlEnabled()) {
- Log.w(TAG, "No bandwidth control; leaving");
- activity.finish();
- }
-
- mUidDetailProvider = new UidDetailProvider(activity);
- mTelephonyManager = activity.getSystemService(TelephonyManager.class);
- mUsageAmount = findPreference(KEY_USAGE_AMOUNT);
- mChart = (ChartDataUsagePreference) findPreference(KEY_CHART_DATA);
- mApps = (PreferenceGroup) findPreference(KEY_APPS_GROUP);
- processArgument();
- }
-
- @Override
- public void onViewCreated(View v, Bundle savedInstanceState) {
- super.onViewCreated(v, savedInstanceState);
-
- mHeader = setPinnedHeaderView(R.layout.apps_filter_spinner);
- mHeader.findViewById(R.id.filter_settings).setOnClickListener(btn -> {
- final Bundle args = new Bundle();
- args.putParcelable(DataUsageListV2.EXTRA_NETWORK_TEMPLATE, mTemplate);
- new SubSettingLauncher(getContext())
- .setDestination(BillingCycleSettings.class.getName())
- .setTitleRes(R.string.billing_cycle)
- .setSourceMetricsCategory(getMetricsCategory())
- .setArguments(args)
- .launch();
- });
- mCycleSpinner = mHeader.findViewById(R.id.filter_spinner);
- mCycleAdapter = new CycleAdapter(mCycleSpinner.getContext(), new SpinnerInterface() {
- @Override
- public void setAdapter(CycleAdapter cycleAdapter) {
- mCycleSpinner.setAdapter(cycleAdapter);
- }
-
- @Override
- public void setOnItemSelectedListener(OnItemSelectedListener listener) {
- mCycleSpinner.setOnItemSelectedListener(listener);
- }
-
- @Override
- public Object getSelectedItem() {
- return mCycleSpinner.getSelectedItem();
- }
-
- @Override
- public void setSelection(int position) {
- mCycleSpinner.setSelection(position);
- }
- }, mCycleListener);
-
- mLoadingViewController = new LoadingViewController(
- getView().findViewById(R.id.loading_container), getListView());
- mLoadingViewController.showLoadingViewDelayed();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mDataStateListener.setListener(true, mSubId, getContext());
- updateBody();
-
- // kick off background task to update stats
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- try {
- // wait a few seconds before kicking off
- Thread.sleep(2 * DateUtils.SECOND_IN_MILLIS);
- services.mStatsService.forceUpdate();
- } catch (InterruptedException e) {
- } catch (RemoteException e) {
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- if (isAdded()) {
- updateBody();
- }
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mDataStateListener.setListener(false, mSubId, getContext());
- }
-
- @Override
- public void onDestroy() {
- mUidDetailProvider.clearCache();
- mUidDetailProvider = null;
-
- super.onDestroy();
- }
-
- @Override
- protected int getPreferenceScreenResId() {
- return R.xml.data_usage_list;
- }
-
- @Override
- protected String getLogTag() {
- return TAG;
- }
-
- void processArgument() {
- final Bundle args = getArguments();
- if (args != null) {
- mSubId = args.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- mTemplate = args.getParcelable(EXTRA_NETWORK_TEMPLATE);
- mNetworkType = args.getInt(EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_MOBILE);
- }
- if (mTemplate == null && mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- final Intent intent = getIntent();
- mSubId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- mTemplate = intent.getParcelableExtra(Settings.EXTRA_NETWORK_TEMPLATE);
- }
- }
-
- /**
- * Update body content based on current tab. Loads network cycle data from system, and
- * binds them to visible controls.
- */
- private void updateBody() {
- if (!isAdded()) return;
-
- final Context context = getActivity();
-
- // kick off loader for network history
- // TODO: consider chaining two loaders together instead of reloading
- // network history when showing app detail.
- getLoaderManager().restartLoader(LOADER_CHART_DATA,
- ChartDataLoaderCompat.buildArgs(mTemplate, null), mNetworkCycleDataCallbacks);
-
- // detail mode can change visible menus, invalidate
- getActivity().invalidateOptionsMenu();
-
- int seriesColor = context.getColor(R.color.sim_noitification);
- if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- final SubscriptionInfo sir = services.mSubscriptionManager
- .getActiveSubscriptionInfo(mSubId);
-
- if (sir != null) {
- seriesColor = sir.getIconTint();
- }
- }
-
- final int secondaryColor = Color.argb(127, Color.red(seriesColor), Color.green(seriesColor),
- Color.blue(seriesColor));
- mChart.setColors(seriesColor, secondaryColor);
- }
-
- /**
- * Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
- * current {@link #mTemplate}.
- */
- private void updatePolicy() {
- final NetworkPolicy policy = services.mPolicyEditor.getPolicy(mTemplate);
- final View configureButton = mHeader.findViewById(R.id.filter_settings);
- //SUB SELECT
- if (isNetworkPolicyModifiable(policy, mSubId) && isMobileDataAvailable(mSubId)) {
- mChart.setNetworkPolicy(policy);
- configureButton.setVisibility(View.VISIBLE);
- ((ImageView) configureButton).setColorFilter(android.R.color.white);
- } else {
- // controls are disabled; don't bind warning/limit sweeps
- mChart.setNetworkPolicy(null);
- configureButton.setVisibility(View.GONE);
- }
-
- // generate cycle list based on policy and available history
- if (mCycleAdapter.updateCycleList(mCycleData)) {
- updateDetailData();
- }
- }
-
- /**
- * Update details based on {@link #mChart} inspection range depending on
- * current mode. Updates {@link #mAdapter} with sorted list
- * of applications data usage.
- */
- private void updateDetailData() {
- if (LOGD) Log.d(TAG, "updateDetailData()");
-
- // kick off loader for detailed stats
- getLoaderManager().restartLoader(LOADER_SUMMARY, null /* args */,
- mNetworkStatsDetailCallbacks);
-
- final long totalBytes = mCycleData != null
- ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getTotalUsage() : 0;
- final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(getActivity(), totalBytes);
- mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase));
- }
-
- /**
- * Bind the given {@link NetworkStats}, or {@code null} to clear list.
- */
- private void bindStats(NetworkStats stats, int[] restrictedUids) {
- mApps.removeAll();
- if (stats == null) {
- if (LOGD) {
- Log.d(TAG, "No network stats data. App list cleared.");
- }
- return;
- }
-
- final ArrayList<AppItem> items = new ArrayList<>();
- long largest = 0;
-
- final int currentUserId = ActivityManager.getCurrentUser();
- final UserManager userManager = UserManager.get(getContext());
- final List<UserHandle> profiles = userManager.getUserProfiles();
- final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
-
- final Bucket bucket = new Bucket();
- while (stats.hasNextBucket() && stats.getNextBucket(bucket)) {
- // Decide how to collapse items together
- final int uid = bucket.getUid();
- final int collapseKey;
- final int category;
- final int userId = UserHandle.getUserId(uid);
- if (UserHandle.isApp(uid)) {
- if (profiles.contains(new UserHandle(userId))) {
- if (userId != currentUserId) {
- // Add to a managed user item.
- final int managedKey = UidDetailProvider.buildKeyForUser(userId);
- largest = accumulate(managedKey, knownItems, bucket,
- AppItem.CATEGORY_USER, items, largest);
- }
- // Add to app item.
- collapseKey = uid;
- category = AppItem.CATEGORY_APP;
- } else {
- // If it is a removed user add it to the removed users' key
- final UserInfo info = userManager.getUserInfo(userId);
- if (info == null) {
- collapseKey = UID_REMOVED;
- category = AppItem.CATEGORY_APP;
- } else {
- // Add to other user item.
- collapseKey = UidDetailProvider.buildKeyForUser(userId);
- category = AppItem.CATEGORY_USER;
- }
- }
- } else if (uid == UID_REMOVED || uid == UID_TETHERING) {
- collapseKey = uid;
- category = AppItem.CATEGORY_APP;
- } else {
- collapseKey = android.os.Process.SYSTEM_UID;
- category = AppItem.CATEGORY_APP;
- }
- largest = accumulate(collapseKey, knownItems, bucket, category, items, largest);
- }
- stats.close();
-
- final int restrictedUidsMax = restrictedUids.length;
- for (int i = 0; i < restrictedUidsMax; ++i) {
- final int uid = restrictedUids[i];
- // Only splice in restricted state for current user or managed users
- if (!profiles.contains(new UserHandle(UserHandle.getUserId(uid)))) {
- continue;
- }
-
- AppItem item = knownItems.get(uid);
- if (item == null) {
- item = new AppItem(uid);
- item.total = -1;
- items.add(item);
- knownItems.put(item.key, item);
- }
- item.restricted = true;
- }
-
- Collections.sort(items);
- for (int i = 0; i < items.size(); i++) {
- final int percentTotal = largest != 0 ? (int) (items.get(i).total * 100 / largest) : 0;
- AppDataUsagePreference preference = new AppDataUsagePreference(getContext(),
- items.get(i), percentTotal, mUidDetailProvider);
- preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- AppDataUsagePreference pref = (AppDataUsagePreference) preference;
- AppItem item = pref.getItem();
- startAppDataUsage(item);
- return true;
- }
- });
- mApps.addPreference(preference);
- }
- }
-
- private void startAppDataUsage(AppItem item) {
- final Bundle args = new Bundle();
- args.putParcelable(AppDataUsageV2.ARG_APP_ITEM, item);
- args.putParcelable(AppDataUsageV2.ARG_NETWORK_TEMPLATE, mTemplate);
-
- new SubSettingLauncher(getContext())
- .setDestination(AppDataUsageV2.class.getName())
- .setTitleRes(R.string.app_data_usage)
- .setArguments(args)
- .setSourceMetricsCategory(getMetricsCategory())
- .launch();
- }
-
- /**
- * Accumulate data usage of a network stats entry for the item mapped by the collapse key.
- * Creates the item if needed.
- *
- * @param collapseKey the collapse key used to map the item.
- * @param knownItems collection of known (already existing) items.
- * @param bucket the network stats bucket to extract data usage from.
- * @param itemCategory the item is categorized on the list view by this category. Must be
- */
- private static long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
- Bucket bucket, int itemCategory, ArrayList<AppItem> items, long largest) {
- final int uid = bucket.getUid();
- AppItem item = knownItems.get(collapseKey);
- if (item == null) {
- item = new AppItem(collapseKey);
- item.category = itemCategory;
- items.add(item);
- knownItems.put(item.key, item);
- }
- item.addUid(uid);
- item.total += bucket.getRxBytes() + bucket.getTxBytes();
- return Math.max(largest, item.total);
- }
-
- private OnItemSelectedListener mCycleListener = new OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem)
- mCycleSpinner.getSelectedItem();
-
- if (LOGD) {
- Log.d(TAG, "showing cycle " + cycle + ", start=" + cycle.start + ", end="
- + cycle.end + "]");
- }
-
- // update chart to show selected cycle, and update detail data
- // to match updated sweep bounds.
- mChart.setNetworkCycleData(mCycleData.get(position));
-
- updateDetailData();
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- // ignored
- }
- };
-
- private final LoaderCallbacks<List<NetworkCycleChartData>> mNetworkCycleDataCallbacks =
- new LoaderCallbacks<List<NetworkCycleChartData>>() {
- @Override
- public Loader<List<NetworkCycleChartData>> onCreateLoader(int id, Bundle args) {
- return NetworkCycleChartDataLoader.builder(getContext())
- .setNetworkTemplate(mTemplate)
- .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
- .build();
- }
-
- @Override
- public void onLoadFinished(Loader<List<NetworkCycleChartData>> loader,
- List<NetworkCycleChartData> data) {
- mLoadingViewController.showContent(false /* animate */);
- mCycleData = data;
- // calculate policy cycles based on available data
- updatePolicy();
- }
-
- @Override
- public void onLoaderReset(Loader<List<NetworkCycleChartData>> loader) {
- mCycleData = null;
- }
- };
-
- private final LoaderCallbacks<NetworkStats> mNetworkStatsDetailCallbacks =
- new LoaderCallbacks<NetworkStats>() {
- @Override
- public Loader<NetworkStats> onCreateLoader(int id, Bundle args) {
- return new NetworkStatsSummaryLoader.Builder(getContext())
- .setStartTime(mChart.getInspectStart())
- .setEndTime(mChart.getInspectEnd())
- .setNetworkType(mNetworkType)
- .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
- .build();
- }
-
- @Override
- public void onLoadFinished(Loader<NetworkStats> loader, NetworkStats data) {
- final int[] restrictedUids = services.mPolicyManager.getUidsWithPolicy(
- POLICY_REJECT_METERED_BACKGROUND);
- bindStats(data, restrictedUids);
- updateEmptyVisible();
- }
-
- @Override
- public void onLoaderReset(Loader<NetworkStats> loader) {
- bindStats(null, new int[0]);
- updateEmptyVisible();
- }
-
- private void updateEmptyVisible() {
- if ((mApps.getPreferenceCount() != 0) !=
- (getPreferenceScreen().getPreferenceCount() != 0)) {
- if (mApps.getPreferenceCount() != 0) {
- getPreferenceScreen().addPreference(mUsageAmount);
- getPreferenceScreen().addPreference(mApps);
- } else {
- getPreferenceScreen().removeAll();
- }
- }
- }
- };
-}
diff --git a/src/com/android/settings/datausage/DataUsagePreference.java b/src/com/android/settings/datausage/DataUsagePreference.java
index aa4e646..21c0503 100644
--- a/src/com/android/settings/datausage/DataUsagePreference.java
+++ b/src/com/android/settings/datausage/DataUsagePreference.java
@@ -21,7 +21,6 @@
import android.net.NetworkTemplate;
import android.os.Bundle;
import android.util.AttributeSet;
-import android.util.FeatureFlagUtils;
import androidx.annotation.VisibleForTesting;
import androidx.core.content.res.TypedArrayUtils;
@@ -29,7 +28,6 @@
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
-import com.android.settings.core.FeatureFlags;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.net.DataUsageController;
@@ -78,23 +76,14 @@
public Intent getIntent() {
final Bundle args = new Bundle();
final SubSettingLauncher launcher;
- if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
- args.putParcelable(DataUsageListV2.EXTRA_NETWORK_TEMPLATE, mTemplate);
- args.putInt(DataUsageListV2.EXTRA_SUB_ID, mSubId);
- args.putInt(DataUsageListV2.EXTRA_NETWORK_TYPE, mTemplate.isMatchRuleMobile()
- ? ConnectivityManager.TYPE_MOBILE : ConnectivityManager.TYPE_WIFI);
- launcher = new SubSettingLauncher(getContext())
- .setArguments(args)
- .setDestination(DataUsageListV2.class.getName())
- .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
- } else {
- args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate);
- args.putInt(DataUsageList.EXTRA_SUB_ID, mSubId);
- launcher = new SubSettingLauncher(getContext())
- .setArguments(args)
- .setDestination(DataUsageList.class.getName())
- .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
- }
+ args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate);
+ args.putInt(DataUsageList.EXTRA_SUB_ID, mSubId);
+ args.putInt(DataUsageList.EXTRA_NETWORK_TYPE, mTemplate.isMatchRuleMobile()
+ ? ConnectivityManager.TYPE_MOBILE : ConnectivityManager.TYPE_WIFI);
+ launcher = new SubSettingLauncher(getContext())
+ .setArguments(args)
+ .setDestination(DataUsageList.class.getName())
+ .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
if (mTemplate.isMatchRuleMobile()) {
launcher.setTitleRes(R.string.app_cellular_data_usage);
} else {
diff --git a/src/com/android/settings/datausage/DataUsageUtils.java b/src/com/android/settings/datausage/DataUsageUtils.java
index 53565ac..b3d0e61 100644
--- a/src/com/android/settings/datausage/DataUsageUtils.java
+++ b/src/com/android/settings/datausage/DataUsageUtils.java
@@ -22,12 +22,8 @@
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.net.ConnectivityManager;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
import android.net.NetworkTemplate;
-import android.net.TrafficStats;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemProperties;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -35,11 +31,8 @@
import android.text.BidiFormatter;
import android.text.format.Formatter;
import android.text.format.Formatter.BytesResult;
-import android.util.FeatureFlagUtils;
import android.util.Log;
-import com.android.settings.core.FeatureFlags;
-
import java.util.List;
/**
@@ -78,44 +71,21 @@
return false;
}
- if (FeatureFlagUtils.isEnabled(context, FeatureFlags.DATA_USAGE_V2)) {
- final TelephonyManager telephonyManager = TelephonyManager.from(context);;
- final NetworkStatsManager networkStatsManager =
- context.getSystemService(NetworkStatsManager.class);
- boolean hasEthernetUsage = false;
- try {
- final Bucket bucket = networkStatsManager.querySummaryForUser(
- ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(),
- 0L /* startTime */, System.currentTimeMillis() /* endTime */);
- if (bucket != null) {
- hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Exception querying network detail.", e);
+ final TelephonyManager telephonyManager = TelephonyManager.from(context);;
+ final NetworkStatsManager networkStatsManager =
+ context.getSystemService(NetworkStatsManager.class);
+ boolean hasEthernetUsage = false;
+ try {
+ final Bucket bucket = networkStatsManager.querySummaryForUser(
+ ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(),
+ 0L /* startTime */, System.currentTimeMillis() /* endTime */);
+ if (bucket != null) {
+ hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0;
}
- return hasEthernetUsage;
- } else {
- final long ethernetBytes;
- try {
- INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
-
- INetworkStatsSession statsSession = statsService.openSession();
- if (statsSession != null) {
- ethernetBytes = statsSession.getSummaryForNetwork(
- NetworkTemplate.buildTemplateEthernet(), Long.MIN_VALUE, Long.MAX_VALUE)
- .getTotalBytes();
- TrafficStats.closeQuietly(statsSession);
- } else {
- ethernetBytes = 0;
- }
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
-
- // only show ethernet when both hardware present and traffic has occurred
- return ethernetBytes > 0;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception querying network detail.", e);
}
+ return hasEthernetUsage;
}
/**
diff --git a/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceController.java b/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceController.java
new file mode 100644
index 0000000..ea47f35
--- /dev/null
+++ b/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceController.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+public class AllowBackgroundActivityStartsPreferenceController
+ extends DeveloperOptionsPreferenceController
+ implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+ private static final String BACKGROUND_ACTIVITY_STARTS_ENABLED_KEY
+ = "allow_background_activity_starts";
+
+ public AllowBackgroundActivityStartsPreferenceController(Context context) {
+ super(context);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return BACKGROUND_ACTIVITY_STARTS_ENABLED_KEY;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ writeSetting((boolean) newValue);
+ return true;
+ }
+
+ private void writeSetting(boolean isEnabled) {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, isEnabled ? 1 : 0);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1);
+ ((SwitchPreference) mPreference).setChecked(mode != 0);
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ writeSetting(false);
+ ((SwitchPreference) mPreference).setChecked(false);
+ }
+}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 932c0c7..762686a 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -454,6 +454,7 @@
controllers.add(new ProfileGpuRenderingPreferenceController(context));
controllers.add(new KeepActivitiesPreferenceController(context));
controllers.add(new BackgroundProcessLimitPreferenceController(context));
+ controllers.add(new AllowBackgroundActivityStartsPreferenceController(context));
controllers.add(new ShowFirstCrashDialogPreferenceController(context));
controllers.add(new AppsNotRespondingPreferenceController(context));
controllers.add(new NotificationChannelWarningsPreferenceController(context));
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java b/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java
index ce425c6..00a79a0 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuController.java
@@ -67,7 +67,8 @@
if (migrate != null) {
migrate.setVisible((privateVol != null)
&& (privateVol.getType() == VolumeInfo.TYPE_PRIVATE)
- && !Objects.equals(mVolumeInfo, privateVol));
+ && !Objects.equals(mVolumeInfo, privateVol)
+ && privateVol.isMountedWritable());
}
}
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
index 1812974..f516926 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
@@ -416,7 +416,8 @@
.getPrimaryStorageCurrentVolume();
migrate.setVisible((privateVol != null)
&& (privateVol.getType() == VolumeInfo.TYPE_PRIVATE)
- && !Objects.equals(mVolume, privateVol));
+ && !Objects.equals(mVolume, privateVol)
+ && privateVol.isMountedWritable());
}
@Override
diff --git a/src/com/android/settings/display/AutoBrightnessPreferenceController.java b/src/com/android/settings/display/AutoBrightnessPreferenceController.java
index 3f5f2b0..3b53fa8 100644
--- a/src/com/android/settings/display/AutoBrightnessPreferenceController.java
+++ b/src/com/android/settings/display/AutoBrightnessPreferenceController.java
@@ -52,7 +52,7 @@
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(
com.android.internal.R.bool.config_automatic_brightness_available)
- ? AVAILABLE_UNSEARCHABLE
+ ? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
@@ -67,4 +67,4 @@
? R.string.auto_brightness_summary_on
: R.string.auto_brightness_summary_off);
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/flashlight/FlashlightSliceBuilder.java b/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
index d21739e..5833229 100644
--- a/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
+++ b/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
@@ -22,17 +22,14 @@
import android.annotation.ColorInt;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
-import android.net.Uri;
import android.provider.Settings;
import android.provider.Settings.Secure;
-import android.provider.SettingsSlicesContract;
import android.util.Log;
import androidx.core.graphics.drawable.IconCompat;
@@ -43,7 +40,7 @@
import com.android.settings.R;
import com.android.settings.Utils;
-import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBroadcastReceiver;
@@ -54,37 +51,23 @@
private static final String TAG = "FlashlightSliceBuilder";
- public static final String KEY_FLASHLIGHT = "flashlight";
-
- /**
- * Backing Uri for the Flashlight Slice.
- */
- public static final Uri FLASHLIGHT_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
- .appendPath(KEY_FLASHLIGHT)
- .build();
-
/**
* Action notifying a change on the Flashlight Slice.
*/
public static final String ACTION_FLASHLIGHT_SLICE_CHANGED =
- "com.android.settings.flashlight.action.FLASHLIGHT_SLICE_CHANGED";
+ "com.android.settings.flashlight.action.FLASHLIGHT_SLICE_CHANGED";
/**
* Action broadcasting a change on whether flashlight is on or off.
*/
public static final String ACTION_FLASHLIGHT_CHANGED =
- "com.android.settings.flashlight.action.FLASHLIGHT_CHANGED";
+ "com.android.settings.flashlight.action.FLASHLIGHT_CHANGED";
public static final IntentFilter INTENT_FILTER = new IntentFilter(ACTION_FLASHLIGHT_CHANGED);
- private FlashlightSliceBuilder() {}
+ private FlashlightSliceBuilder() {
+ }
- /**
- * Return a Flashlight Slice bound to {@link #FLASHLIGHT_URI}.
- */
public static Slice getSlice(Context context) {
if (!isFlashlightAvailable(context)) {
return null;
@@ -93,14 +76,15 @@
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final IconCompat icon =
IconCompat.createWithResource(context, R.drawable.ic_signal_flashlight);
- return new ListBuilder(context, FLASHLIGHT_URI, ListBuilder.INFINITY)
- .setAccentColor(color)
- .addRow(new RowBuilder()
- .setTitle(context.getText(R.string.power_flashlight))
- .setTitleItem(icon, ICON_IMAGE)
- .setPrimaryAction(
- new SliceAction(toggleAction, null, isFlashlightEnabled(context))))
- .build();
+ return new ListBuilder(context, CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
+ ListBuilder.INFINITY)
+ .setAccentColor(color)
+ .addRow(new RowBuilder()
+ .setTitle(context.getText(R.string.power_flashlight))
+ .setTitleItem(icon, ICON_IMAGE)
+ .setPrimaryAction(
+ SliceAction.createToggle(toggleAction, null, isFlashlightEnabled(context))))
+ .build();
}
/**
@@ -119,7 +103,7 @@
} catch (CameraAccessException e) {
Log.e(TAG, "Camera couldn't set torch mode.", e);
}
- context.getContentResolver().notifyChange(FLASHLIGHT_URI, null);
+ context.getContentResolver().notifyChange(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, null);
}
private static String getCameraId(Context context) throws CameraAccessException {
@@ -130,7 +114,7 @@
Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
if (flashAvailable != null && flashAvailable
- && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
+ && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
return id;
}
}
@@ -141,16 +125,16 @@
final Intent intent = new Intent(ACTION_FLASHLIGHT_SLICE_CHANGED);
intent.setClass(context, SliceBroadcastReceiver.class);
return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT);
}
private static boolean isFlashlightAvailable(Context context) {
return Settings.Secure.getInt(
- context.getContentResolver(), Secure.FLASHLIGHT_AVAILABLE, 0) == 1;
+ context.getContentResolver(), Secure.FLASHLIGHT_AVAILABLE, 0) == 1;
}
private static boolean isFlashlightEnabled(Context context) {
return Settings.Secure.getInt(
- context.getContentResolver(), Secure.FLASHLIGHT_ENABLED, 0) == 1;
+ context.getContentResolver(), Secure.FLASHLIGHT_ENABLED, 0) == 1;
}
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
index eac2bf5..0d9b1c4 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
@@ -42,6 +42,9 @@
* Controller in charge of the battery tip group
*/
public class BatteryTipPreferenceController extends BasePreferenceController {
+
+ public static final String PREF_NAME = "battery_tip";
+
private static final String TAG = "BatteryTipPreferenceController";
private static final int REQUEST_ANOMALY_ACTION = 0;
private static final String KEY_BATTERY_TIPS = "key_battery_tips";
diff --git a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
index 2e9b5a5..00b7a0c 100644
--- a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
+++ b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
@@ -52,7 +52,7 @@
for (AbstractPreferenceController controller : mGestureControllers) {
isAvailable = isAvailable || controller.isAvailable();
}
- return isAvailable ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
+ return isAvailable ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
/**
@@ -101,4 +101,4 @@
}
return mContext.getText(R.string.language_input_gesture_summary_off);
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java
new file mode 100644
index 0000000..8583f38
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.homepage.contextualcards;
+
+import android.content.Context;
+
+import java.util.List;
+
+/** Feature provider for the contextual card feature. */
+public interface ContextualCardFeatureProvider {
+
+ /** Homepage displays. */
+ public void logHomepageDisplay(Context context, Long latency);
+
+ /** When user clicks dismiss in contextual card */
+ public void logContextualCardDismiss(Context context, ContextualCard card);
+
+ /** After ContextualCardManager decides which cards will be displayed/hidden */
+ public void logContextualCardDisplay(Context context, List<ContextualCard> showedCards,
+ List<ContextualCard> hiddenCards);
+
+ /** When user clicks toggle/title area of a contextual card. */
+ public void logContextualCardClick(Context context, ContextualCard card, int row,
+ int tapTarget);
+}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
new file mode 100644
index 0000000..e437e2b
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.homepage.contextualcards;
+
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.slice.widget.EventInfo;
+
+import com.android.settings.R;
+
+import java.util.List;
+
+public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureProvider {
+ private static final String TAG = "ContextualCardFeature";
+
+ // Contextual card interaction logs
+ // Settings Homepage shows
+ private static final int CONTEXTUAL_HOME_SHOW = 38;
+
+ // Contextual card shows, log card name and rank
+ private static final int CONTEXTUAL_CARD_SHOW = 39;
+
+ // Contextual card is eligible to be shown, but doesn't rank high
+ // enough, log card name and score
+ private static final int CONTEXTUAL_CARD_NOT_SHOW = 40;
+
+ // Contextual card is dismissed, log card name
+ private static final int CONTEXTUAL_CARD_DISMISS = 41;
+
+ // Contextual card is clicked , log card name, score, tap area
+ private static final int CONTEXTUAL_CARD_CLICK = 42;
+
+ // SettingsLogBroadcastReceiver contracts
+ // contextual card name
+ private static final String EXTRA_CONTEXTUALCARD_NAME = "name";
+
+ // contextual card score
+ private static final String EXTRA_CONTEXTUALCARD_SCORE = "score";
+
+ // contextual card clicked row
+ private static final String EXTRA_CONTEXTUALCARD_ROW = "row";
+
+ // contextual card tap target
+ private static final String EXTRA_CONTEXTUALCARD_TAP_TARGET = "target";
+
+ // contextual homepage display latency
+ private static final String EXTRA_LATENCY = "latency";
+
+ // log type
+ private static final String EXTRA_CONTEXTUALCARD_ACTION_TYPE = "type";
+
+
+ // Contextual card tap target
+ private static final int TARGET_DEFAULT = 0;
+
+ // Click title area
+ private static final int TARGET_TITLE = 1;
+
+ // Click toggle
+ private static final int TARGET_TOGGLE = 2;
+
+ // Click slider
+ private static final int TARGET_SLIDER = 3;
+
+ @Override
+ public void logHomepageDisplay(Context context, Long latency) {
+ }
+
+ @Override
+ public void logContextualCardDismiss(Context context, ContextualCard card) {
+ final Intent intent = new Intent();
+ intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_DISMISS);
+ intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
+ intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
+ sendBroadcast(context, intent);
+ }
+
+ @Override
+ public void logContextualCardDisplay(Context context, List<ContextualCard> showCards,
+ List<ContextualCard> hiddenCards) {
+ }
+
+ @Override
+ public void logContextualCardClick(Context context, ContextualCard card, int row,
+ int actionType) {
+ final Intent intent = new Intent();
+ intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_CLICK);
+ intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
+ intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
+ intent.putExtra(EXTRA_CONTEXTUALCARD_ROW, row);
+ intent.putExtra(EXTRA_CONTEXTUALCARD_TAP_TARGET, actionTypeToTapTarget(actionType));
+ sendBroadcast(context, intent);
+ }
+
+ @VisibleForTesting
+ void sendBroadcast(final Context context, final Intent intent) {
+ intent.setPackage(context.getString(R.string.config_settingsintelligence_package_name));
+ final String action = context.getString(R.string.config_settingsintelligence_log_action);
+ if (!TextUtils.isEmpty(action)) {
+ intent.setAction(action);
+ context.sendBroadcast(intent);
+ }
+ }
+
+ private int actionTypeToTapTarget(int actionType) {
+ switch (actionType) {
+ case EventInfo.ACTION_TYPE_CONTENT:
+ return TARGET_TITLE;
+ case EventInfo.ACTION_TYPE_TOGGLE:
+ return TARGET_TOGGLE;
+ case EventInfo.ACTION_TYPE_SLIDER:
+ return TARGET_SLIDER;
+ default:
+ Log.w(TAG, "unknown type " + actionType);
+ return TARGET_DEFAULT;
+ }
+ }
+}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeedbackDialog.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeedbackDialog.java
new file mode 100644
index 0000000..0d5b275
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeedbackDialog.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.homepage.contextualcards;
+
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+import com.android.settings.R;
+
+public class ContextualCardFeedbackDialog extends AlertActivity implements
+ DialogInterface.OnClickListener {
+
+ public static final String EXTRA_CARD_NAME = "card_name";
+ public static final String EXTRA_FEEDBACK_EMAIL = "feedback_email";
+
+ private static final String TAG = "CardFeedbackDialog";
+ private static final String SUBJECT = "Settings Contextual Card Feedback - ";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final AlertController.AlertParams alertParams = mAlertParams;
+ alertParams.mMessage = getText(R.string.contextual_card_feedback_confirm_message);
+ alertParams.mPositiveButtonText = getText(R.string.contextual_card_feedback_send);
+ alertParams.mPositiveButtonListener = this;
+ alertParams.mNegativeButtonText = getText(R.string.skip_label);
+
+ setupAlert();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final String cardName = getIntent().getStringExtra(EXTRA_CARD_NAME);
+ final String email = getIntent().getStringExtra(EXTRA_FEEDBACK_EMAIL);
+ final Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + email));
+ intent.putExtra(Intent.EXTRA_SUBJECT, SUBJECT + cardName);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ try {
+ startActivity(intent);
+ } catch (Exception e) {
+ Log.e(TAG, "Send feedback failed.", e);
+ }
+ finish();
+ }
+}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 4c06601..3ef4653 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -34,8 +34,7 @@
import androidx.annotation.VisibleForTesting;
import androidx.slice.Slice;
-import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
-import com.android.settings.wifi.WifiSlice;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settingslib.utils.AsyncLoaderCompat;
import java.util.ArrayList;
@@ -170,8 +169,8 @@
private int getNumberOfLargeCard(List<ContextualCard> cards) {
return (int) cards.stream()
- .filter(card -> card.getSliceUri().equals(WifiSlice.WIFI_URI)
- || card.getSliceUri().equals(ConnectedDeviceSlice.CONNECTED_DEVICE_URI))
+ .filter(card -> card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI)
+ || card.getSliceUri().equals(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI))
.count();
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 30eae29..5f397d7 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -40,6 +40,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
import java.util.stream.Collectors;
/**
@@ -132,8 +133,13 @@
// except Conditional cards, all other cards are from the database. So when the map sent
// here is empty, we only keep Conditional cards.
if (cardTypes.isEmpty()) {
+ final Set<Integer> conditionalCardTypes = new TreeSet() {{
+ add(ContextualCard.CardType.CONDITIONAL);
+ add(ContextualCard.CardType.CONDITIONAL_HEADER);
+ add(ContextualCard.CardType.CONDITIONAL_FOOTER);
+ }};
cardsToKeep = mContextualCards.stream()
- .filter(card -> card.getCardType() == ContextualCard.CardType.CONDITIONAL)
+ .filter(card -> conditionalCardTypes.contains(card.getCardType()))
.collect(Collectors.toList());
} else {
cardsToKeep = mContextualCards.stream()
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index 5ff3e90..376bb83 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -16,16 +16,11 @@
package com.android.settings.homepage.contextualcards;
-import static android.provider.SettingsSlicesContract.KEY_WIFI;
-
import android.annotation.Nullable;
-import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
-import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
-import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
import com.android.settings.intelligence.ContextualCardProto.ContextualCard;
import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
-import com.android.settings.wifi.WifiSlice;
+import com.android.settings.slices.CustomSliceRegistry;
import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
@@ -39,26 +34,26 @@
public ContextualCardList getContextualCards() {
final ContextualCard wifiCard =
ContextualCard.newBuilder()
- .setSliceUri(WifiSlice.WIFI_URI.toString())
- .setCardName(KEY_WIFI)
+ .setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI.toString())
+ .setCardName(CustomSliceRegistry.WIFI_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard connectedDeviceCard =
ContextualCard.newBuilder()
- .setSliceUri(ConnectedDeviceSlice.CONNECTED_DEVICE_URI.toString())
- .setCardName(ConnectedDeviceSlice.PATH_CONNECTED_DEVICE)
+ .setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
+ .setCardName(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard lowStorageCard =
ContextualCard.newBuilder()
- .setSliceUri(LowStorageSlice.LOW_STORAGE_URI.toString())
- .setCardName(LowStorageSlice.PATH_LOW_STORAGE)
+ .setSliceUri(CustomSliceRegistry.LOW_STORAGE_SLICE_URI.toString())
+ .setCardName(CustomSliceRegistry.LOW_STORAGE_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard batteryFixCard =
ContextualCard.newBuilder()
- .setSliceUri(BatteryFixSlice.BATTERY_FIX_URI.toString())
- .setCardName(BatteryFixSlice.PATH_BATTERY_FIX)
+ .setSliceUri(CustomSliceRegistry.BATTERY_FIX_SLICE_URI.toString())
+ .setCardName(CustomSliceRegistry.BATTERY_FIX_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCardList cards = ContextualCardList.newBuilder()
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java b/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
index 706b50e..cf91157 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
@@ -98,25 +98,12 @@
.setName(mAppContext.getPackageName() + "/"
+ mAppContext.getText(R.string.condition_zen_title))
.setTitleText(mAppContext.getText(R.string.condition_zen_title).toString())
- .setSummaryText(getSummary().toString())
+ .setSummaryText(mAppContext.getText(R.string.condition_zen_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp))
.setIsHalfWidth(true)
.build();
}
- public CharSequence getSummary() {
- final int zen = mNotificationManager.getZenMode();
- final ZenModeConfig config;
- boolean zenModeEnabled = zen != Settings.Global.ZEN_MODE_OFF;
- if (zenModeEnabled) {
- config = mNotificationManager.getZenModeConfig();
- } else {
- config = null;
- }
- return ZenModeConfig.getDescription(mAppContext, zen != Settings.Global.ZEN_MODE_OFF,
- config, true);
- }
-
public class Receiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
index 873b942..b0d6963 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
@@ -16,8 +16,9 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
+import static com.android.settings.slices.CustomSliceRegistry.BATTERY_INFO_SLICE_URI;
+
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -37,7 +38,6 @@
import com.android.settings.fuelgauge.BatteryInfo;
import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
/**
@@ -46,20 +46,6 @@
public class BatterySlice implements CustomSliceable {
private static final String TAG = "BatterySlice";
- /**
- * The path denotes the unique name of battery slice.
- */
- public static final String PATH_BATTERY_INFO = "battery_card";
-
- /**
- * Backing Uri for the Battery Slice.
- */
- public static final Uri BATTERY_CARD_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_BATTERY_INFO)
- .build();
-
private final Context mContext;
private BatteryInfo mBatteryInfo;
@@ -69,9 +55,6 @@
mContext = context;
}
- /**
- * Return a {@link BatterySlice} bound to {@link #BATTERY_CARD_URI}
- */
@Override
public Slice getSlice() {
if (mBatteryInfo == null) {
@@ -81,8 +64,9 @@
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_settings_battery);
final CharSequence title = mContext.getText(R.string.power_usage_summary_title);
- final SliceAction primarySliceAction = new SliceAction(getPrimaryAction(), icon, title);
- final Slice slice = new ListBuilder(mContext, BATTERY_CARD_URI, ListBuilder.INFINITY)
+ final SliceAction primarySliceAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+ ListBuilder.ICON_IMAGE, title);
+ final Slice slice = new ListBuilder(mContext, BATTERY_INFO_SLICE_URI, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
.addRow(new ListBuilder.RowBuilder()
@@ -97,7 +81,7 @@
@Override
public Uri getUri() {
- return BATTERY_CARD_URI;
+ return BATTERY_INFO_SLICE_URI;
}
@Override
@@ -108,12 +92,10 @@
@Override
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.power_usage_summary_title).toString();
- final Uri contentUri = new Uri.Builder().appendPath(PATH_BATTERY_INFO).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
- PowerUsageSummary.class.getName(), PATH_BATTERY_INFO, screenTitle,
+ PowerUsageSummary.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName())
- .setData(contentUri);
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
@Override
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
index 6296b1e..bb78586 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
@@ -17,7 +17,6 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -39,8 +38,8 @@
import com.android.settings.Utils;
import com.android.settings.datausage.DataUsageSummary;
import com.android.settings.datausage.DataUsageUtils;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.net.DataUsageController;
@@ -50,19 +49,6 @@
private static final String TAG = "DataUsageSlice";
private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);
- /**
- * The path denotes the unique name of data usage slice.
- */
- public static final String PATH_DATA_USAGE = "data_usage_card";
-
- /**
- * Backing Uri for the Data usage Slice.
- */
- public static final Uri DATA_USAGE_CARD_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_DATA_USAGE)
- .build();
private final Context mContext;
@@ -72,22 +58,21 @@
@Override
public Uri getUri() {
- return DATA_USAGE_CARD_URI;
+ return CustomSliceRegistry.DATA_USAGE_SLICE_URI;
}
- /**
- * Return a Data usage Slice bound to {@link #DATA_USAGE_CARD_URI}
- */
@Override
public Slice getSlice() {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_settings_data_usage);
final String title = mContext.getString(R.string.data_usage_summary_title);
- final SliceAction primaryAction = new SliceAction(getPrimaryAction(), icon, title);
+ final SliceAction primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+ ListBuilder.ICON_IMAGE, title);
final DataUsageController dataUsageController = new DataUsageController(mContext);
final DataUsageController.DataUsageInfo info = dataUsageController.getDataUsageInfo();
final ListBuilder listBuilder =
- new ListBuilder(mContext, DATA_USAGE_CARD_URI, ListBuilder.INFINITY)
+ new ListBuilder(mContext, CustomSliceRegistry.DATA_USAGE_SLICE_URI,
+ ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.setHeader(new ListBuilder.HeaderBuilder().setTitle(title));
if (DataUsageUtils.hasSim(mContext)) {
@@ -106,12 +91,10 @@
@Override
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.data_usage_wifi_title).toString();
- final Uri contentUri = new Uri.Builder().appendPath(PATH_DATA_USAGE).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
- DataUsageSummary.class.getName(), PATH_DATA_USAGE, screenTitle,
+ DataUsageSummary.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName())
- .setData(contentUri);
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
index b8751f8..694336d 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
@@ -17,7 +17,6 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -39,8 +38,8 @@
import com.android.settings.Utils;
import com.android.settings.deviceinfo.DeviceModelPreferenceController;
import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.DeviceInfoUtils;
@@ -49,20 +48,6 @@
public class DeviceInfoSlice implements CustomSliceable {
private static final String TAG = "DeviceInfoSlice";
- /**
- * The path denotes the unique name of device info slice
- */
- public static final String PATH_DEVICE_INFO = "device_info_card";
-
- /**
- * Backing Uri for the Device info Slice.
- */
- public static final Uri DEVICE_INFO_CARD_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_DEVICE_INFO)
- .build();
-
private final Context mContext;
private final SubscriptionManager mSubscriptionManager;
@@ -71,16 +56,15 @@
mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
}
- /**
- * Return a device info slice bound to {@Link #DEVICE_INFO_CARD_URI}
- */
@Override
public Slice getSlice() {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_info_outline_24dp);
final String title = mContext.getString(R.string.device_info_label);
- final SliceAction primaryAction = new SliceAction(getPrimaryAction(), icon, title);
- return new ListBuilder(mContext, DEVICE_INFO_CARD_URI, ListBuilder.INFINITY)
+ final SliceAction primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+ ListBuilder.ICON_IMAGE, title);
+ return new ListBuilder(mContext, CustomSliceRegistry.DEVICE_INFO_SLICE_URI,
+ ListBuilder.INFINITY)
.setAccentColor((Utils.getColorAccentDefaultColor(mContext)))
.setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
.addRow(new ListBuilder.RowBuilder()
@@ -92,18 +76,16 @@
@Override
public Uri getUri() {
- return DEVICE_INFO_CARD_URI;
+ return CustomSliceRegistry.DEVICE_INFO_SLICE_URI;
}
@Override
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.device_info_label).toString();
- final Uri contentUri = new Uri.Builder().appendPath(PATH_DEVICE_INFO).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
- MyDeviceInfoFragment.class.getName(), PATH_DEVICE_INFO, screenTitle,
+ MyDeviceInfoFragment.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName())
- .setData(contentUri);
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
index aff34f4..2484e53 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
@@ -17,10 +17,8 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.net.Uri;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
@@ -28,39 +26,27 @@
import androidx.slice.builders.SliceAction;
import com.android.settings.R;
-import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.CustomSliceRegistry;
// This is a slice helper class for EmergencyInfo
public class EmergencyInfoSlice {
- /**
- * The path denotes the unique name of emergency info slice.
- */
- public static final String PATH_EMERGENCY_INFO_CARD = "emergency_info_card";
-
- /**
- * Backing Uri for the Emergency Info Slice.
- */
- public static final Uri EMERGENCY_INFO_CARD_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_EMERGENCY_INFO_CARD)
- .build();
private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
public static Slice getSlice(Context context) {
- final ListBuilder listBuilder = new ListBuilder(context, EMERGENCY_INFO_CARD_URI,
+ final ListBuilder listBuilder = new ListBuilder(context,
+ CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI,
ListBuilder.INFINITY);
listBuilder.addRow(
new ListBuilder.RowBuilder()
.setTitle(context.getText(R.string.emergency_info_title))
.setSubtitle(
context.getText(R.string.emergency_info_contextual_card_summary))
- .setPrimaryAction(generatePrimaryAction(context)));
+ .setPrimaryAction(createPrimaryAction(context)));
return listBuilder.build();
}
- private static SliceAction generatePrimaryAction(Context context) {
+ private static SliceAction createPrimaryAction(Context context) {
PendingIntent pendingIntent =
PendingIntent.getActivity(
context,
@@ -68,10 +54,10 @@
new Intent(ACTION_EDIT_EMERGENCY_INFO),
PendingIntent.FLAG_UPDATE_CURRENT);
- return SliceAction.create(
+ return SliceAction.createDeeplink(
pendingIntent,
IconCompat.createWithResource(context, R.drawable.empty_icon),
- ListBuilder.SMALL_IMAGE,
+ ListBuilder.ICON_IMAGE,
context.getText(R.string.emergency_info_title));
}
}
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
index c61a8a0..eba831a 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
@@ -17,7 +17,6 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -36,8 +35,8 @@
import com.android.settings.Utils;
import com.android.settings.deviceinfo.StorageDashboardFragment;
import com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
@@ -45,20 +44,6 @@
public class StorageSlice implements CustomSliceable {
private static final String TAG = "StorageSlice";
- /**
- * The path denotes the unique name of storage slicel
- */
- public static final String PATH_STORAGE_INFO = "storage_card";
-
- /**
- * Backing Uri for the storage slice.
- */
- public static final Uri STORAGE_CARD_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_STORAGE_INFO)
- .build();
-
private final Context mContext;
public StorageSlice(Context context) {
@@ -67,20 +52,19 @@
@Override
public Uri getUri() {
- return STORAGE_CARD_URI;
+ return CustomSliceRegistry.STORAGE_SLICE_URI;
}
- /**
- * Return a storage slice bound to {@link #STORAGE_CARD_URI}
- */
@Override
public Slice getSlice() {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_homepage_storage);
final String title = mContext.getString(R.string.storage_label);
- final SliceAction primaryAction = new SliceAction(getPrimaryAction(), icon, title);
+ final SliceAction primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+ ListBuilder.ICON_IMAGE, title);
final PrivateStorageInfo info = getPrivateStorageInfo();
- return new ListBuilder(mContext, STORAGE_CARD_URI, ListBuilder.INFINITY)
+ return new ListBuilder(mContext, CustomSliceRegistry.STORAGE_SLICE_URI,
+ ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
.addRow(new ListBuilder.RowBuilder()
@@ -93,12 +77,10 @@
@Override
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.storage_label).toString();
- final Uri contentUri = new Uri.Builder().appendPath(PATH_STORAGE_INFO).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
- StorageDashboardFragment.class.getName(), PATH_STORAGE_INFO, screenTitle,
+ StorageDashboardFragment.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName())
- .setData(contentUri);
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
index 23ff172..403178c 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
@@ -19,7 +19,6 @@
import static android.content.Context.MODE_PRIVATE;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -34,7 +33,6 @@
import androidx.slice.builders.SliceAction;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.SubSettings;
@@ -42,9 +40,10 @@
import com.android.settings.fuelgauge.BatteryStatsHelperLoader;
import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.fuelgauge.batterytip.BatteryTipLoader;
+import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.utils.ThreadUtils;
@@ -53,20 +52,6 @@
public class BatteryFixSlice implements CustomSliceable {
- /**
- * Unique name of Battery Fix Slice.
- */
- public static final String PATH_BATTERY_FIX = "battery_fix";
-
- /**
- * Uri for Battery Fix Slice.
- */
- public static final Uri BATTERY_FIX_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_BATTERY_FIX)
- .build();
-
@VisibleForTesting
static final String PREFS = "battery_fix_prefs";
@VisibleForTesting
@@ -82,12 +67,9 @@
@Override
public Uri getUri() {
- return BATTERY_FIX_URI;
+ return CustomSliceRegistry.BATTERY_FIX_SLICE_URI;
}
- /**
- * Return a Slice bound to {@link #BATTERY_FIX_URI}.
- */
@Override
public Slice getSlice() {
IconCompat icon;
@@ -106,10 +88,12 @@
for (BatteryTip batteryTip : batteryTips) {
if (batteryTip.getState() != BatteryTip.StateType.INVISIBLE) {
icon = IconCompat.createWithResource(mContext, batteryTip.getIconId());
- primaryAction = new SliceAction(getPrimaryAction(),
+ primaryAction = SliceAction.createDeeplink(getPrimaryAction(),
icon,
+ ListBuilder.ICON_IMAGE,
batteryTip.getTitle(mContext));
- slice = new ListBuilder(mContext, BATTERY_FIX_URI, ListBuilder.INFINITY)
+ slice = new ListBuilder(mContext, CustomSliceRegistry.BATTERY_FIX_SLICE_URI,
+ ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(new RowBuilder()
.setTitle(batteryTip.getTitle(mContext))
@@ -124,8 +108,10 @@
icon = IconCompat.createWithResource(mContext,
R.drawable.ic_battery_status_good_24dp);
final String title = mContext.getString(R.string.power_usage_summary_title);
- primaryAction = new SliceAction(getPrimaryAction(), icon, title);
- slice = new ListBuilder(mContext, BATTERY_FIX_URI, ListBuilder.INFINITY)
+ primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
+ ListBuilder.ICON_IMAGE, title);
+ slice = new ListBuilder(mContext, CustomSliceRegistry.BATTERY_FIX_SLICE_URI,
+ ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(new RowBuilder()
.setTitle(title)
@@ -140,10 +126,11 @@
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.power_usage_summary_title)
.toString();
- final Uri contentUri = new Uri.Builder().appendPath(PATH_BATTERY_FIX).build();
+ final Uri contentUri = new Uri.Builder()
+ .appendPath(BatteryTipPreferenceController.PREF_NAME).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
- PowerUsageSummary.class.getName(), PATH_BATTERY_FIX,
+ PowerUsageSummary.class.getName(), BatteryTipPreferenceController.PREF_NAME,
screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
diff --git a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java b/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
index ef7c1bd..0c79b6b 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
@@ -18,7 +18,6 @@
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -43,8 +42,8 @@
import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -68,20 +67,6 @@
public class ConnectedDeviceSlice implements CustomSliceable {
/**
- * The path denotes the unique name of Connected device Slice.
- */
- public static final String PATH_CONNECTED_DEVICE = "connected_device";
-
- /**
- * Backing Uri for Connected device Slice.
- */
- public static final Uri CONNECTED_DEVICE_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_CONNECTED_DEVICE)
- .build();
-
- /**
* To sort the Bluetooth devices by {@link CachedBluetoothDevice}.
* Refer compareTo method from {@link com.android.settings.bluetooth.BluetoothDevicePreference}.
*/
@@ -109,25 +94,23 @@
@Override
public Uri getUri() {
- return CONNECTED_DEVICE_URI;
+ return CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI;
}
- /**
- * Return a Connected Device Slice bound to {@link #CONNECTED_DEVICE_URI}.
- */
@Override
public Slice getSlice() {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_homepage_connected_device);
- final CharSequence title = mContext.getText(R.string.connected_devices_dashboard_title);
+ final CharSequence title = mContext.getText(R.string.bluetooth_connected_devices);
final CharSequence titleNoConnectedDevices = mContext.getText(
R.string.no_connected_devices);
final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext, 0,
getIntent(), 0);
- final SliceAction primarySliceAction = new SliceAction(primaryActionIntent, icon,
- title);
+ final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryActionIntent, icon,
+ ListBuilder.ICON_IMAGE, title);
final ListBuilder listBuilder =
- new ListBuilder(mContext, CONNECTED_DEVICE_URI, ListBuilder.INFINITY)
+ new ListBuilder(mContext, CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI,
+ ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
// Get row builders by connected devices, e.g. Bluetooth.
@@ -159,14 +142,12 @@
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.connected_devices_dashboard_title)
.toString();
- final Uri contentUri = new Uri.Builder().appendPath(PATH_CONNECTED_DEVICE).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
- ConnectedDeviceDashboardFragment.class.getName(), PATH_CONNECTED_DEVICE,
+ ConnectedDeviceDashboardFragment.class.getName(), "" /* key */,
screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName())
- .setData(contentUri);
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName());
}
@Override
@@ -251,9 +232,10 @@
}
private SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
- return new SliceAction(
+ return SliceAction.createDeeplink(
getBluetoothDetailIntent(bluetoothDevice),
IconCompat.createWithResource(mContext, R.drawable.ic_settings),
+ ListBuilder.ICON_IMAGE,
bluetoothDevice.getName());
}
diff --git a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
index 7f6efcc..3cbbb0c 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
@@ -17,13 +17,11 @@
package com.android.settings.homepage.contextualcards.slices;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.storage.StorageManager;
import android.text.format.Formatter;
-import android.util.Log;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
@@ -36,8 +34,8 @@
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.deviceinfo.StorageSettings;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
-import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
@@ -47,23 +45,7 @@
public class LowStorageSlice implements CustomSliceable {
/**
- * The path denotes the unique name of Low storage Slice.
- */
- public static final String PATH_LOW_STORAGE = "low_storage";
-
- /**
- * Backing Uri for Low storage Slice.
- */
- public static final Uri LOW_STORAGE_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_LOW_STORAGE)
- .build();
-
- private static final String TAG = "LowStorageSlice";
-
- /**
- * If user used >= 85% storage.
+ * If used storage >= 85%, it would be low storage.
*/
private static final double LOW_STORAGE_THRESHOLD = 0.85;
@@ -73,54 +55,45 @@
mContext = context;
}
- /**
- * Return a Low storage Slice bound to {@link #LOW_STORAGE_URI}
- */
@Override
public Slice getSlice() {
- // Get current storage percentage from StorageManager.
+ // Get used storage percentage from StorageManager.
final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
new StorageManagerVolumeProvider(mContext.getSystemService(StorageManager.class)));
- final double currentStoragePercentage =
- (double) (info.totalBytes - info.freeBytes) / info.totalBytes;
+ final double usedPercentage = (double) (info.totalBytes - info.freeBytes) / info.totalBytes;
- // Used storage < 85%. NOT show Low storage Slice.
- if (currentStoragePercentage < LOW_STORAGE_THRESHOLD) {
- /**
- * TODO(b/114808204): Contextual Home Page - "Low Storage"
- * The behavior is under decision making, will update new behavior or remove TODO later.
- */
- Log.i(TAG, "Not show low storage slice, not match condition.");
- return null;
+ // Generate Low storage Slice.
+ final String percentageString = NumberFormat.getPercentInstance().format(usedPercentage);
+ final String freeSizeString = Formatter.formatFileSize(mContext, info.freeBytes);
+ final ListBuilder listBuilder = new ListBuilder(mContext,
+ CustomSliceRegistry.LOW_STORAGE_SLICE_URI, ListBuilder.INFINITY).setAccentColor(
+ Utils.getColorAccentDefaultColor(mContext));
+ final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
+
+ if (usedPercentage < LOW_STORAGE_THRESHOLD) {
+ // For clients that ignore error checking, a generic storage slice will be given.
+ final CharSequence titleStorage = mContext.getText(R.string.storage_settings);
+ final String summaryStorage = mContext.getString(R.string.storage_summary,
+ percentageString, freeSizeString);
+
+ return listBuilder
+ .addRow(buildRowBuilder(titleStorage, summaryStorage, icon))
+ .setIsError(true)
+ .build();
}
- // Show Low storage Slice.
- final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_storage);
- final CharSequence title = mContext.getText(R.string.storage_menu_free);
- final SliceAction primarySliceAction = new SliceAction(
- PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon, title);
- final String lowStorageSummary = mContext.getString(R.string.low_storage_summary,
- NumberFormat.getPercentInstance().format(currentStoragePercentage),
- Formatter.formatFileSize(mContext, info.freeBytes));
+ final CharSequence titleLowStorage = mContext.getText(R.string.storage_menu_free);
+ final String summaryLowStorage = mContext.getString(R.string.low_storage_summary,
+ percentageString, freeSizeString);
- /**
- * TODO(b/114808204): Contextual Home Page - "Low Storage"
- * Slices doesn't support "Icon on the left" in header. Now we intend to start with Icon
- * right aligned. Will update the icon to left until Slices support it.
- */
- return new ListBuilder(mContext, LOW_STORAGE_URI, ListBuilder.INFINITY)
- .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
- .addRow(new RowBuilder()
- .setTitle(title)
- .setSubtitle(lowStorageSummary)
- .addEndItem(icon, ListBuilder.ICON_IMAGE)
- .setPrimaryAction(primarySliceAction))
+ return listBuilder
+ .addRow(buildRowBuilder(titleLowStorage, summaryLowStorage, icon))
.build();
}
@Override
public Uri getUri() {
- return LOW_STORAGE_URI;
+ return CustomSliceRegistry.LOW_STORAGE_SLICE_URI;
}
@Override
@@ -132,13 +105,28 @@
public Intent getIntent() {
final String screenTitle = mContext.getText(R.string.storage_label)
.toString();
- final Uri contentUri = new Uri.Builder().appendPath(PATH_LOW_STORAGE).build();
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
- StorageSettings.class.getName(), PATH_LOW_STORAGE,
+ StorageSettings.class.getName(), "" /* key */,
screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName())
- .setData(contentUri);
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+ }
+
+ private RowBuilder buildRowBuilder(CharSequence title, String summary, IconCompat icon) {
+ final SliceAction primarySliceAction = SliceAction.createDeeplink(
+ PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon,
+ ListBuilder.ICON_IMAGE, title);
+
+ /**
+ * TODO(b/114808204): Contextual Home Page - "Low Storage"
+ * Slices doesn't support "Icon on the left" in header. Now we intend to start with Icon
+ * right aligned. Will update the icon to left until Slices support it.
+ */
+ return new RowBuilder()
+ .setTitle(title)
+ .setSubtitle(summary)
+ .addEndItem(icon, ListBuilder.ICON_IMAGE)
+ .setPrimaryAction(primarySliceAction);
}
}
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
index f1fbc9c..4378be3 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
@@ -17,12 +17,19 @@
package com.android.settings.homepage.contextualcards.slices;
import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
-import com.android.settings.homepage.contextualcards.CardContentProvider;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
import com.android.settings.homepage.contextualcards.ContextualCard;
import com.android.settings.homepage.contextualcards.ContextualCardController;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
+import com.android.settings.homepage.contextualcards.ContextualCardFeedbackDialog;
import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.utils.ThreadUtils;
/**
@@ -32,7 +39,8 @@
private static final String TAG = "SliceCardController";
- private Context mContext;
+ private final Context mContext;
+
private ContextualCardUpdateListener mCardUpdateListener;
public SliceContextualCardController(Context context) {
@@ -51,7 +59,7 @@
@Override
public void onActionClick(ContextualCard card) {
- //TODO(b/113783548): Implement feedback mechanism
+
}
@Override
@@ -60,10 +68,33 @@
final CardDatabaseHelper dbHelper = CardDatabaseHelper.getInstance(mContext);
dbHelper.markContextualCardAsDismissed(mContext, card.getName());
});
+ showFeedbackDialog(card);
+ final ContextualCardFeatureProvider contexualCardFeatureProvider =
+ FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
+ contexualCardFeatureProvider.logContextualCardDismiss(mContext, card);
}
@Override
public void setCardUpdateListener(ContextualCardUpdateListener listener) {
mCardUpdateListener = listener;
}
+
+ @VisibleForTesting
+ void showFeedbackDialog(ContextualCard card) {
+ final String email = mContext.getString(R.string.config_contextual_card_feedback_email);
+ if (TextUtils.isEmpty(email)) {
+ return;
+ }
+ final Intent feedbackIntent = new Intent(mContext, ContextualCardFeedbackDialog.class);
+ feedbackIntent.putExtra(ContextualCardFeedbackDialog.EXTRA_CARD_NAME,
+ getSimpleCardName(card));
+ feedbackIntent.putExtra(ContextualCardFeedbackDialog.EXTRA_FEEDBACK_EMAIL, email);
+ feedbackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(feedbackIntent);
+ }
+
+ private String getSimpleCardName(ContextualCard card) {
+ final String[] split = card.getName().split("/");
+ return split[split.length - 1];
+ }
}
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
index 74f25eb..a2d6e2b 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.net.Uri;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -38,10 +39,13 @@
import com.android.settings.R;
import com.android.settings.homepage.contextualcards.ContextualCard;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.homepage.contextualcards.ContextualCardRenderer;
import com.android.settings.homepage.contextualcards.ControllerRendererPool;
+import com.android.settings.overlay.FeatureFactory;
import java.util.Map;
+import java.util.Set;
/**
* Card renderer for {@link ContextualCard} built as slices.
@@ -58,6 +62,7 @@
private final Context mContext;
private final LifecycleOwner mLifecycleOwner;
private final ControllerRendererPool mControllerRendererPool;
+ private final Set<ContextualCard> mCardSet;
public SliceContextualCardRenderer(Context context, LifecycleOwner lifecycleOwner,
ControllerRendererPool controllerRendererPool) {
@@ -65,6 +70,7 @@
mLifecycleOwner = lifecycleOwner;
mSliceLiveDataMap = new ArrayMap<>();
mControllerRendererPool = controllerRendererPool;
+ mCardSet = new ArraySet<>();
}
@Override
@@ -99,6 +105,7 @@
sliceLiveData = SliceLiveData.fromUri(mContext, uri);
mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
}
+ mCardSet.add(card);
sliceLiveData.removeObservers(mLifecycleOwner);
sliceLiveData.observe(mLifecycleOwner, slice -> {
@@ -128,14 +135,27 @@
final Button btnRemove = cardHolder.itemView.findViewById(R.id.remove);
btnRemove.setOnClickListener(v -> {
- mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(
- card);
+ mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(card);
});
}
@Override
public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) {
//TODO(b/79698338): Log user interaction
+
+ // sliceItem.getSlice().getUri() is like
+ // content://android.settings.slices/action/wifi/_gen/0/_gen/0
+ // contextualCard.getSliceUri() is prefix of sliceItem.getSlice().getUri()
+ for (ContextualCard card : mCardSet) {
+ if (sliceItem.getSlice().getUri().toString().startsWith(
+ card.getSliceUri().toString())) {
+ ContextualCardFeatureProvider contexualCardFeatureProvider =
+ FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
+ contexualCardFeatureProvider.logContextualCardClick(mContext, card,
+ eventInfo.rowIndex, eventInfo.actionType);
+ break;
+ }
+ }
}
public static class SliceViewHolder extends RecyclerView.ViewHolder {
diff --git a/src/com/android/settings/location/LocationSliceBuilder.java b/src/com/android/settings/location/LocationSliceBuilder.java
index 56cf676..f70d09b 100644
--- a/src/com/android/settings/location/LocationSliceBuilder.java
+++ b/src/com/android/settings/location/LocationSliceBuilder.java
@@ -23,11 +23,9 @@
import android.annotation.ColorInt;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
-import android.provider.SettingsSlicesContract;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
@@ -39,6 +37,7 @@
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBuilderUtils;
/**
@@ -46,21 +45,11 @@
*/
public class LocationSliceBuilder {
- /**
- * Backing Uri for the Location Slice.
- */
- public static final Uri LOCATION_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSlicesContract.AUTHORITY)
- .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
- .appendPath(KEY_LOCATION)
- .build();
-
private LocationSliceBuilder() {
}
/**
- * Return a Location Slice bound to {@link #LOCATION_URI}.
+ * Return a Location Slice bound to {@link CustomSliceRegistry#LOCATION_SLICE_URI}.
*/
public static Slice getSlice(Context context) {
final IconCompat icon = IconCompat.createWithResource(context,
@@ -68,9 +57,11 @@
final String title = context.getString(R.string.location_settings_title);
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final PendingIntent primaryAction = getPrimaryAction(context);
- final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
+ final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
+ ListBuilder.ICON_IMAGE, title);
- return new ListBuilder(context, LOCATION_URI, ListBuilder.INFINITY)
+ return new ListBuilder(context, CustomSliceRegistry.LOCATION_SLICE_URI,
+ ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)
diff --git a/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelper.java b/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelper.java
index b198f92..be5d948 100644
--- a/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelper.java
+++ b/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelper.java
@@ -19,7 +19,6 @@
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -40,9 +39,8 @@
import com.android.ims.ImsManager;
import com.android.settings.R;
import com.android.settings.Utils;
-import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBroadcastReceiver;
-import com.android.settings.slices.SliceBuilderUtils;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
@@ -57,12 +55,7 @@
*/
public class Enhanced4gLteSliceHelper {
- private static final String TAG = "Enhanced4gLteSliceHelper";
-
- /**
- * Settings slice path to enhanced 4g LTE setting.
- */
- public static final String PATH_ENHANCED_4G_LTE = "enhanced_4g_lte";
+ private static final String TAG = "Enhanced4gLteSlice";
/**
* Action passed for changes to enhanced 4g LTE slice (toggle).
@@ -71,14 +64,6 @@
"com.android.settings.mobilenetwork.action.ENHANCED_4G_LTE_CHANGED";
/**
- * Slice Uri for Enhanced 4G slice
- */
- public static final Uri SLICE_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_ENHANCED_4G_LTE)
- .build();
- /**
* Action for mobile network settings activity which
* allows setting configuration for Enhanced 4G LTE
* related settings
@@ -107,7 +92,7 @@
* Enhanced 4g lte mode title variant resource name
*/
private static final String RESOURCE_ENHANCED_4G_LTE_MODE_TITLE_VARIANT =
- "enhanced_4g_lte_mode_title_variant";
+ "enhanced_4g_lte_mode_title_variant";
@VisibleForTesting
public Enhanced4gLteSliceHelper(Context context) {
@@ -187,13 +172,15 @@
.addRow(new RowBuilder()
.setTitle(getEnhanced4glteModeTitle(subId))
.addEndItem(
- new SliceAction(
+ SliceAction.createToggle(
getBroadcastIntent(ACTION_ENHANCED_4G_LTE_CHANGED),
null /* actionTitle */, isEnhanced4gLteEnabled))
- .setPrimaryAction(new SliceAction(
- getActivityIntent(ACTION_MOBILE_NETWORK_SETTINGS_ACTIVITY),
- icon,
- getEnhanced4glteModeTitle(subId))))
+ .setPrimaryAction(
+ SliceAction.createDeeplink(
+ getActivityIntent(ACTION_MOBILE_NETWORK_SETTINGS_ACTIVITY),
+ icon,
+ ListBuilder.ICON_IMAGE,
+ getEnhanced4glteModeTitle(subId))))
.build();
}
@@ -225,8 +212,7 @@
}
// notify change in slice in any case to get re-queried. This would result in displaying
// appropriate message with the updated setting.
- final Uri uri = SliceBuilderUtils.getUri(PATH_ENHANCED_4G_LTE, false /*isPlatformSlice*/);
- mContext.getContentResolver().notifyChange(uri, null);
+ mContext.getContentResolver().notifyChange(CustomSliceRegistry.ENHANCED_4G_SLICE_URI, null);
}
private CharSequence getEnhanced4glteModeTitle(int subId) {
diff --git a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
index 5b4c245..d0f1ee6 100644
--- a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
+++ b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java
@@ -25,7 +25,6 @@
import android.content.pm.ServiceInfo;
import android.provider.Settings;
import android.service.notification.ConditionProviderService;
-import android.service.notification.ZenModeConfig;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
@@ -34,20 +33,15 @@
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
import java.util.Map;
-import java.util.Set;
abstract public class AbstractZenModeAutomaticRulePreferenceController extends
AbstractZenModePreferenceController implements PreferenceControllerMixin {
protected ZenModeBackend mBackend;
protected Fragment mParent;
- protected Set<Map.Entry<String, AutomaticZenRule>> mRules;
+ protected Map.Entry<String, AutomaticZenRule>[] mRules;
protected PackageManager mPm;
- private static List<String> mDefaultRuleIds;
public AbstractZenModeAutomaticRulePreferenceController(Context context, String key, Fragment
parent, Lifecycle lifecycle) {
@@ -60,20 +54,14 @@
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- mRules = getZenModeRules();
+ mRules = mBackend.getAutomaticZenRules();
}
- private static List<String> getDefaultRuleIds() {
- if (mDefaultRuleIds == null) {
- mDefaultRuleIds = ZenModeConfig.DEFAULT_RULE_IDS;
+ protected Map.Entry<String, AutomaticZenRule>[] getRules() {
+ if (mRules == null) {
+ mRules = mBackend.getAutomaticZenRules();
}
- return mDefaultRuleIds;
- }
-
- private Set<Map.Entry<String, AutomaticZenRule>> getZenModeRules() {
- Map<String, AutomaticZenRule> ruleMap =
- NotificationManager.from(mContext).getAutomaticZenRules();
- return ruleMap.entrySet();
+ return mRules;
}
protected void showNameRuleDialog(final ZenRuleInfo ri, Fragment parent) {
@@ -81,16 +69,6 @@
RuleNameChangeListener(ri));
}
- protected Map.Entry<String, AutomaticZenRule>[] sortedRules() {
- if (mRules == null) {
- mRules = getZenModeRules();
- }
- final Map.Entry<String, AutomaticZenRule>[] rt =
- mRules.toArray(new Map.Entry[mRules.size()]);
- Arrays.sort(rt, RULE_COMPARATOR);
- return rt;
- }
-
protected static Intent getRuleIntent(String settingsAction,
ComponentName configurationActivity, String ruleId) {
final Intent intent = new Intent()
@@ -104,35 +82,6 @@
return intent;
}
- private static final Comparator<Map.Entry<String, AutomaticZenRule>> RULE_COMPARATOR =
- new Comparator<Map.Entry<String, AutomaticZenRule>>() {
- @Override
- public int compare(Map.Entry<String, AutomaticZenRule> lhs,
- Map.Entry<String, AutomaticZenRule> rhs) {
- // if it's a default rule, should be at the top of automatic rules
- boolean lhsIsDefaultRule = getDefaultRuleIds().contains(lhs.getKey());
- boolean rhsIsDefaultRule = getDefaultRuleIds().contains(rhs.getKey());
- if (lhsIsDefaultRule != rhsIsDefaultRule) {
- return lhsIsDefaultRule ? -1 : 1;
- }
-
- int byDate = Long.compare(lhs.getValue().getCreationTime(),
- rhs.getValue().getCreationTime());
- if (byDate != 0) {
- return byDate;
- } else {
- return key(lhs.getValue()).compareTo(key(rhs.getValue()));
- }
- }
-
- private String key(AutomaticZenRule rule) {
- final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
- ? 1 : ZenModeConfig.isValidEventConditionId(rule.getConditionId())
- ? 2 : 3;
- return type + rule.getName().toString();
- }
- };
-
public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
if (si == null || si.metaData == null) {
return null;
diff --git a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
index 72bb0e3..c2db773 100644
--- a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
+++ b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
@@ -136,7 +136,7 @@
MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
mRule.setName(ruleName);
mRule.setModified(true);
- mBackend.setZenRule(mId, mRule);
+ mBackend.updateZenRule(mId, mRule);
}
}
}
diff --git a/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java
index f38deb3..e5ca754 100644
--- a/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java
+++ b/src/com/android/settings/notification/ZenAutomaticRuleSwitchPreferenceController.java
@@ -88,6 +88,6 @@
final boolean enabled = isChecked;
if (enabled == mRule.isEnabled()) return;
mRule.setEnabled(enabled);
- mBackend.setZenRule(mId, mRule);
+ mBackend.updateZenRule(mId, mRule);
}
}
diff --git a/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java b/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java
index 67d9e93..b877668 100644
--- a/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeAlarmsPreferenceController.java
@@ -21,12 +21,12 @@
import android.provider.Settings;
import android.util.Log;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
public class ZenModeAlarmsPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener {
@@ -78,6 +78,7 @@
mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_ALARMS,
allowAlarms);
mBackend.saveSoundPolicy(Policy.PRIORITY_CATEGORY_ALARMS, allowAlarms);
+
return true;
}
}
diff --git a/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java b/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
index 7679b0b..615b26c 100644
--- a/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
@@ -28,6 +28,7 @@
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Map;
+import java.util.Objects;
public class ZenModeAutomaticRulesPreferenceController extends
AbstractZenModeAutomaticRulePreferenceController {
@@ -62,16 +63,40 @@
@Override
public void updateState(Preference preference) {
super.updateState(preference);
+ Map.Entry<String, AutomaticZenRule>[] sortedRules = getRules();
+ final int currNumPreferences = mPreferenceCategory.getPreferenceCount();
+ if (currNumPreferences == sortedRules.length) {
+ for (int i = 0; i < sortedRules.length; i++) {
+ ZenRulePreference pref = (ZenRulePreference) mPreferenceCategory.getPreference(i);
+ // we are either:
+ // 1. updating the enabled state or name of the rule
+ // 2. rule was added or deleted, so reload the entire list
+ if (Objects.equals(pref.mId, sortedRules[i].getKey())) {
+ AutomaticZenRule rule = sortedRules[i].getValue();
+ pref.setName(rule.getName());
+ pref.setChecked(rule.isEnabled());
+ } else {
+ reloadAllRules(sortedRules);
+ break;
+ }
+ }
+ } else {
+ reloadAllRules(sortedRules);
+ }
+ }
+ @VisibleForTesting
+ void reloadAllRules(Map.Entry<String, AutomaticZenRule>[] rules) {
mPreferenceCategory.removeAll();
- Map.Entry<String, AutomaticZenRule>[] sortedRules = sortedRules();
- for (Map.Entry<String, AutomaticZenRule> sortedRule : sortedRules) {
- ZenRulePreference pref = new ZenRulePreference(mPreferenceCategory.getContext(),
- sortedRule, mParent, mMetricsFeatureProvider);
+ for (Map.Entry<String, AutomaticZenRule> rule : rules) {
+ ZenRulePreference pref = createZenRulePreference(rule);
mPreferenceCategory.addPreference(pref);
}
}
+
+ @VisibleForTesting
+ ZenRulePreference createZenRulePreference(Map.Entry<String, AutomaticZenRule> rule) {
+ return new ZenRulePreference(mPreferenceCategory.getContext(),
+ rule, mParent, mMetricsFeatureProvider);
+ }
}
-
-
-
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index 44bc5f1..c559a28 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -16,9 +16,15 @@
package com.android.settings.notification;
+import android.app.AlertDialog;
+import android.app.AutomaticZenRule;
import android.content.Context;
+import android.content.DialogInterface;
import android.provider.SearchIndexableResource;
import android.service.notification.ConditionProviderService;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import androidx.fragment.app.Fragment;
@@ -34,10 +40,14 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
@SearchIndexable
public class ZenModeAutomationSettings extends ZenModeSettingsBase {
protected final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
+ private CharSequence[] mDeleteDialogRuleNames;
+ private String[] mDeleteDialogRuleIds;
+ private boolean[] mDeleteDialogChecked;
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
@@ -74,6 +84,52 @@
.setNoun("condition provider")
.build();
}
+ private final int DELETE_RULES = 1;
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ menu.add(Menu.NONE, DELETE_RULES, Menu.NONE, R.string.zen_mode_delete_automatic_rules);
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case DELETE_RULES:
+ Map.Entry<String, AutomaticZenRule>[] rules = mBackend.getAutomaticZenRules();
+ mDeleteDialogRuleNames = new CharSequence[rules.length];
+ mDeleteDialogRuleIds = new String[rules.length];
+ mDeleteDialogChecked = new boolean[rules.length];
+ for (int i = 0; i < rules.length; i++) {
+ mDeleteDialogRuleNames[i] = rules[i].getValue().getName();
+ mDeleteDialogRuleIds[i] = rules[i].getKey();
+ }
+ new AlertDialog.Builder(mContext)
+ .setTitle(R.string.zen_mode_delete_automatic_rules)
+ .setMultiChoiceItems(mDeleteDialogRuleNames, null,
+ new DialogInterface.OnMultiChoiceClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which,
+ boolean isChecked) {
+ mDeleteDialogChecked[which] = isChecked;
+ }
+ })
+ .setPositiveButton(R.string.zen_mode_schedule_delete,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ for (int i = 0; i < rules.length; i++) {
+ if (mDeleteDialogChecked[i]) {
+ mBackend.removeZenRule(mDeleteDialogRuleIds[i]);
+ }
+ }
+ }
+ }).show();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
/**
* For Search.
diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java
index de30e5d..4824825 100644
--- a/src/com/android/settings/notification/ZenModeBackend.java
+++ b/src/com/android/settings/notification/ZenModeBackend.java
@@ -32,6 +32,11 @@
import com.android.settings.R;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
public class ZenModeBackend {
@VisibleForTesting
protected static final String ZEN_MODE_FROM_ANYONE = "zen_mode_from_anyone";
@@ -42,6 +47,7 @@
@VisibleForTesting
protected static final String ZEN_MODE_FROM_NONE = "zen_mode_from_none";
protected static final int SOURCE_NONE = -1;
+ private static List<String> mDefaultRuleIds;
private static ZenModeBackend sInstance;
@@ -79,7 +85,7 @@
Settings.Global.ZEN_MODE, mZenMode);
}
- protected boolean setZenRule(String id, AutomaticZenRule rule) {
+ protected boolean updateZenRule(String id, AutomaticZenRule rule) {
return NotificationManager.from(mContext).updateAutomaticZenRule(id, rule);
}
@@ -294,13 +300,65 @@
return NotificationManager.from(mContext).removeAutomaticZenRule(ruleId);
}
+ public NotificationManager.Policy getConsolidatedPolicy() {
+ return NotificationManager.from(mContext).getConsolidatedNotificationPolicy();
+ }
+
protected String addZenRule(AutomaticZenRule rule) {
try {
- String id = NotificationManager.from(mContext).addAutomaticZenRule(rule);
- NotificationManager.from(mContext).getAutomaticZenRule(id);
- return id;
+ return NotificationManager.from(mContext).addAutomaticZenRule(rule);
} catch (Exception e) {
return null;
}
}
+
+ protected Map.Entry<String, AutomaticZenRule>[] getAutomaticZenRules() {
+ Map<String, AutomaticZenRule> ruleMap =
+ NotificationManager.from(mContext).getAutomaticZenRules();
+ final Map.Entry<String, AutomaticZenRule>[] rt = ruleMap.entrySet().toArray(
+ new Map.Entry[ruleMap.size()]);
+ Arrays.sort(rt, RULE_COMPARATOR);
+ return rt;
+ }
+
+ protected AutomaticZenRule getAutomaticZenRule(String id) {
+ return NotificationManager.from(mContext).getAutomaticZenRule(id);
+ }
+
+ private static List<String> getDefaultRuleIds() {
+ if (mDefaultRuleIds == null) {
+ mDefaultRuleIds = ZenModeConfig.DEFAULT_RULE_IDS;
+ }
+ return mDefaultRuleIds;
+ }
+
+ @VisibleForTesting
+ public static final Comparator<Map.Entry<String, AutomaticZenRule>> RULE_COMPARATOR =
+ new Comparator<Map.Entry<String, AutomaticZenRule>>() {
+ @Override
+ public int compare(Map.Entry<String, AutomaticZenRule> lhs,
+ Map.Entry<String, AutomaticZenRule> rhs) {
+ // if it's a default rule, should be at the top of automatic rules
+ boolean lhsIsDefaultRule = getDefaultRuleIds().contains(lhs.getKey());
+ boolean rhsIsDefaultRule = getDefaultRuleIds().contains(rhs.getKey());
+ if (lhsIsDefaultRule != rhsIsDefaultRule) {
+ return lhsIsDefaultRule ? -1 : 1;
+ }
+
+ int byDate = Long.compare(lhs.getValue().getCreationTime(),
+ rhs.getValue().getCreationTime());
+ if (byDate != 0) {
+ return byDate;
+ } else {
+ return key(lhs.getValue()).compareTo(key(rhs.getValue()));
+ }
+ }
+
+ private String key(AutomaticZenRule rule) {
+ final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
+ ? 1 : ZenModeConfig.isValidEventConditionId(rule.getConditionId())
+ ? 2 : 3;
+ return type + rule.getName().toString();
+ }
+ };
}
diff --git a/src/com/android/settings/notification/ZenModePreferenceController.java b/src/com/android/settings/notification/ZenModePreferenceController.java
index 44ad2ff..22eb0c0 100644
--- a/src/com/android/settings/notification/ZenModePreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePreferenceController.java
@@ -35,6 +35,9 @@
public class ZenModePreferenceController extends BasePreferenceController
implements LifecycleObserver, OnResume, OnPause {
+
+ public static final String ZEN_MODE_KEY = "zen_mode";
+
private SettingObserver mSettingObserver;
private ZenModeSettings.SummaryBuilder mSummaryBuilder;
diff --git a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
index 9e5dbc3..11b8084 100644
--- a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
@@ -124,7 +124,7 @@
protected void updateRule(Uri newConditionId) {
mRule.setConditionId(newConditionId);
- mBackend.setZenRule(mId, mRule);
+ mBackend.updateZenRule(mId, mRule);
}
@Override
diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
index f65a8b0..0b2e1bc 100644
--- a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
+++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
@@ -64,7 +64,6 @@
private TimePickerPreference mEnd;
private SwitchPreference mExitAtAlarm;
private AlertDialog mDayDialog;
-
private ScheduleInfo mSchedule;
@Override
@@ -186,7 +185,6 @@
final int summaryFormat = nextDay ? R.string.zen_mode_end_time_next_day_summary_format : 0;
mEnd.setSummaryFormat(summaryFormat);
}
-
@Override
protected void updateControlsInternal() {
updateDays();
diff --git a/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java b/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
index 6d5aac9..f69eac7 100644
--- a/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
@@ -16,16 +16,23 @@
package com.android.settings.notification;
+import android.app.NotificationManager;
import android.content.Context;
+import android.icu.text.ListFormatter;
import android.net.Uri;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
+import android.util.Log;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePreferenceController {
protected static final String KEY = "footer_preference";
@@ -65,6 +72,31 @@
protected String getFooterText() {
ZenModeConfig config = getZenModeConfig();
+
+ NotificationManager.Policy appliedPolicy = mBackend.getConsolidatedPolicy();
+ NotificationManager.Policy defaultPolicy = config.toNotificationPolicy();
+ final boolean usingCustomPolicy = !Objects.equals(appliedPolicy, defaultPolicy);
+
+ if (usingCustomPolicy) {
+ final List<ZenModeConfig.ZenRule> activeRules = getActiveRules(config);
+ final List<String> rulesNames = new ArrayList<>();
+ for (ZenModeConfig.ZenRule rule : activeRules) {
+ if (rule.name != null) {
+ rulesNames.add(rule.name);
+ }
+ }
+ if (rulesNames.size() > 0) {
+ String rules = ListFormatter.getInstance().format(rulesNames);
+ if (!rules.isEmpty()) {
+ return mContext.getString(R.string.zen_mode_settings_dnd_custom_settings_footer,
+ rules);
+ }
+ }
+ }
+ return getFooterUsingDefaultPolicy(config);
+ }
+
+ private String getFooterUsingDefaultPolicy(ZenModeConfig config) {
String footerText = "";
long latestEndTime = -1;
@@ -116,4 +148,18 @@
}
return footerText;
}
+
+ private List<ZenModeConfig.ZenRule> getActiveRules(ZenModeConfig config) {
+ List<ZenModeConfig.ZenRule> zenRules = new ArrayList<>();
+ if (config.manualRule != null) {
+ zenRules.add(config.manualRule);
+ }
+
+ for (ZenModeConfig.ZenRule automaticRule : config.automaticRules.values()) {
+ if (automaticRule.isAutomaticActive()) {
+ zenRules.add(automaticRule);
+ }
+ }
+ return zenRules;
+ }
}
diff --git a/src/com/android/settings/notification/ZenModeSliceBuilder.java b/src/com/android/settings/notification/ZenModeSliceBuilder.java
index bd6ad0b..5c88fb6 100644
--- a/src/com/android/settings/notification/ZenModeSliceBuilder.java
+++ b/src/com/android/settings/notification/ZenModeSliceBuilder.java
@@ -18,16 +18,16 @@
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
+import static com.android.settings.notification.ZenModePreferenceController.ZEN_MODE_KEY;
+
import android.annotation.ColorInt;
import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.provider.Settings;
-import android.provider.SettingsSlicesContract;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
@@ -39,7 +39,7 @@
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
-import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
@@ -47,18 +47,6 @@
private static final String TAG = "ZenModeSliceBuilder";
- private static final String ZEN_MODE_KEY = "zen_mode";
-
- /**
- * Backing Uri for the Zen Mode Slice.
- */
- public static final Uri ZEN_MODE_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
- .appendPath(ZEN_MODE_KEY)
- .build();
-
/**
* Action notifying a change on the Zen Mode Slice.
*/
@@ -77,7 +65,7 @@
}
/**
- * Return a ZenMode Slice bound to {@link #ZEN_MODE_URI}.
+ * Return a ZenMode Slice bound to {@link CustomSliceRegistry#ZEN_MODE_URI}.
* <p>
* Note that you should register a listener for {@link #INTENT_FILTER} to get changes for
* ZenMode.
@@ -88,12 +76,13 @@
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final PendingIntent toggleAction = getBroadcastIntent(context);
final PendingIntent primaryAction = getPrimaryAction(context);
- final SliceAction primarySliceAction = new SliceAction(primaryAction,
- (IconCompat) null /* icon */, title);
- final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
+ final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction,
+ (IconCompat) null /* icon */, ListBuilder.ICON_IMAGE, title);
+ final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction, null /* actionTitle */,
isZenModeEnabled);
- return new ListBuilder(context, ZEN_MODE_URI, ListBuilder.INFINITY)
+ return new ListBuilder(context, CustomSliceRegistry.ZEN_MODE_SLICE_URI,
+ ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)
diff --git a/src/com/android/settings/notification/ZenRulePreference.java b/src/com/android/settings/notification/ZenRulePreference.java
index 8058e6c..48a879b 100644
--- a/src/com/android/settings/notification/ZenRulePreference.java
+++ b/src/com/android/settings/notification/ZenRulePreference.java
@@ -19,17 +19,18 @@
import android.app.AutomaticZenRule;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.service.notification.ZenModeConfig;
import android.view.View;
+import android.widget.CheckBox;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
-import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.utils.ManagedServiceSettings;
import com.android.settings.utils.ZenServiceListing;
@@ -37,11 +38,11 @@
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import java.util.Map;
+import java.util.Objects;
public class ZenRulePreference extends TwoTargetPreference {
private static final ManagedServiceSettings.Config CONFIG =
ZenModeAutomationSettings.getConditionProviderConfig();
- final CharSequence mName;
final String mId;
boolean appExists;
final Fragment mParent;
@@ -51,16 +52,23 @@
final ZenServiceListing mServiceListing;
final PackageManager mPm;
final MetricsFeatureProvider mMetricsFeatureProvider;
+ final AutomaticZenRule mRule;
+ CharSequence mName;
+
+ private boolean mIsSystemRule;
+ private Intent mIntent;
+ private boolean mChecked;
+ private CheckBox mCheckBox;
public ZenRulePreference(Context context,
final Map.Entry<String, AutomaticZenRule> ruleEntry,
Fragment parent, MetricsFeatureProvider metricsProvider) {
super(context);
-
+ setLayoutResource(R.layout.preference_checkable_two_target);
mBackend = ZenModeBackend.getInstance(context);
mContext = context;
- final AutomaticZenRule rule = ruleEntry.getValue();
- mName = rule.getName();
+ mRule = ruleEntry.getValue();
+ mName = mRule.getName();
mId = ruleEntry.getKey();
mParent = parent;
mPm = mContext.getPackageManager();
@@ -68,65 +76,97 @@
mServiceListing.reloadApprovedServices();
mPref = this;
mMetricsFeatureProvider = metricsProvider;
-
- setAttributes(rule);
+ mChecked = mRule.isEnabled();
+ setAttributes(mRule);
+ setWidgetLayoutResource(getSecondTargetResId());
}
- @Override
protected int getSecondTargetResId() {
- if (mId != null && ZenModeConfig.DEFAULT_RULE_IDS.contains(mId)) {
- return 0;
+ if (mIntent != null) {
+ return R.layout.zen_rule_widget;
}
-
- return R.layout.zen_rule_widget;
+ return 0;
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
+ View settingsWidget = view.findViewById(android.R.id.widget_frame);
+ View divider = view.findViewById(R.id.two_target_divider);
+ if (mIntent != null) {
+ divider.setVisibility(View.VISIBLE);
+ settingsWidget.setVisibility(View.VISIBLE);
+ settingsWidget.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mContext.startActivity(mIntent);
+ }
+ });
+ } else {
+ divider.setVisibility(View.GONE);
+ settingsWidget.setVisibility(View.GONE);
+ settingsWidget.setOnClickListener(null);
+ }
- View v = view.findViewById(R.id.delete_zen_rule);
- if (v != null) {
- v.setOnClickListener(mDeleteListener);
+ View checkboxContainer = view.findViewById(R.id.checkbox_container);
+ if (checkboxContainer != null) {
+ checkboxContainer.setOnClickListener(mOnCheckBoxClickListener);
+ }
+ mCheckBox = (CheckBox) view.findViewById(com.android.internal.R.id.checkbox);
+ if (mCheckBox != null) {
+ mCheckBox.setChecked(mChecked);
}
}
- private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
+ public boolean isChecked() {
+ return mChecked;
+ }
+
+ public void setChecked(boolean checked) {
+ mChecked = checked;
+ if (mCheckBox != null) {
+ mCheckBox.setChecked(checked);
+ }
+ }
+
+ public void setName(String name) {
+ if (!Objects.equals(mName, name)) {
+ mName = name;
+ setTitle(mName);
+ }
+ }
+
+ @Override
+ public void onClick() {
+ mOnCheckBoxClickListener.onClick(null);
+ }
+
+ private View.OnClickListener mOnCheckBoxClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
- showDeleteRuleDialog(mParent, mId, mName.toString());
+ mRule.setEnabled(!mChecked);
+ mBackend.updateZenRule(mId, mRule);
+ setChecked(mRule.isEnabled());
+ setAttributes(mRule);
}
};
- private void showDeleteRuleDialog(final Fragment parent, final String ruleId,
- final String ruleName) {
- ZenDeleteRuleDialog.show(parent, ruleName, ruleId,
- new ZenDeleteRuleDialog.PositiveClickListener() {
- @Override
- public void onOk(String id) {
- mMetricsFeatureProvider.action(mContext,
- MetricsProto.MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
- mBackend.removeZenRule(id);
- }
- });
- }
-
protected void setAttributes(AutomaticZenRule rule) {
final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
rule.getConditionId(), true);
final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
- final boolean isSystemRule = isSchedule || isEvent;
+ mIsSystemRule = isSchedule || isEvent;
try {
ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
- setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
+ setSummary(computeRuleSummary(rule, mIsSystemRule, info.loadLabel(mPm)));
} catch (PackageManager.NameNotFoundException e) {
appExists = false;
return;
}
appExists = true;
- setTitle(rule.getName());
+ setTitle(mName);
setPersistent(false);
final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
@@ -134,9 +174,8 @@
ServiceInfo si = mServiceListing.findService(rule.getOwner());
ComponentName settingsActivity = AbstractZenModeAutomaticRulePreferenceController.
getSettingsActivity(si);
- setIntent(AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
- settingsActivity, mId));
- setSelectable(settingsActivity != null || isSystemRule);
+ mIntent = AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
+ settingsActivity, mId);
setKey(mId);
}
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 02468b8..a52619b 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -28,6 +28,7 @@
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.gestures.AssistGestureFeatureProvider;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.localepicker.LocaleFeatureProvider;
import com.android.settings.panel.PanelFeatureProvider;
import com.android.settings.search.SearchFeatureProvider;
@@ -108,6 +109,8 @@
public abstract PanelFeatureProvider getPanelFeatureProvider();
+ public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider();
+
public static final class FactoryNotFoundException extends RuntimeException {
public FactoryNotFoundException(Throwable throwable) {
super("Unable to create factory. Did you misconfigure Proguard?", throwable);
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 8d6d4b6..3515ac0 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -40,6 +40,8 @@
import com.android.settings.fuelgauge.PowerUsageFeatureProviderImpl;
import com.android.settings.gestures.AssistGestureFeatureProvider;
import com.android.settings.gestures.AssistGestureFeatureProviderImpl;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProviderImpl;
import com.android.settings.localepicker.LocaleFeatureProvider;
import com.android.settings.localepicker.LocaleFeatureProviderImpl;
import com.android.settings.panel.PanelFeatureProvider;
@@ -75,6 +77,7 @@
private SlicesFeatureProvider mSlicesFeatureProvider;
private AccountFeatureProvider mAccountFeatureProvider;
private PanelFeatureProvider mPanelFeatureProvider;
+ private ContextualCardFeatureProvider mContextualCardFeatureProvider;
@Override
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -220,4 +223,11 @@
}
return mPanelFeatureProvider;
}
+
+ public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
+ if (mContextualCardFeatureProvider == null) {
+ mContextualCardFeatureProvider = new ContextualCardFeatureProviderImpl();
+ }
+ return mContextualCardFeatureProvider;
+ }
}
diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java
index b6fe53b..aae42f8 100644
--- a/src/com/android/settings/panel/InternetConnectivityPanel.java
+++ b/src/com/android/settings/panel/InternetConnectivityPanel.java
@@ -16,16 +16,13 @@
package com.android.settings.panel;
-import androidx.annotation.VisibleForTesting;
-
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
-import android.provider.SettingsSlicesContract;
+import android.provider.Settings;
import com.android.settings.R;
-import com.android.settings.wifi.WifiSlice;
+import com.android.settings.slices.CustomSliceRegistry;
import java.util.ArrayList;
import java.util.List;
@@ -34,19 +31,11 @@
* Represents the Internet Connectivity Panel.
*
* <p>
- * Displays Wifi (full Slice) and Airplane mode.
+ * Displays Wifi (full Slice) and Airplane mode.
* </p>
*/
public class InternetConnectivityPanel implements PanelContent {
- @VisibleForTesting
- static final Uri AIRPLANE_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSlicesContract.AUTHORITY)
- .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
- .appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
- .build();
-
private final Context mContext;
public static InternetConnectivityPanel create(Context context) {
@@ -58,20 +47,20 @@
}
@Override
- public String getTitle() {
- return (String) mContext.getText(R.string.internet_connectivity_panel_title);
+ public CharSequence getTitle() {
+ return mContext.getText(R.string.internet_connectivity_panel_title);
}
@Override
public List<Uri> getSlices() {
final List<Uri> uris = new ArrayList<>();
- uris.add(WifiSlice.WIFI_URI);
- uris.add(AIRPLANE_URI);
+ uris.add(CustomSliceRegistry.WIFI_SLICE_URI);
+ uris.add(CustomSliceRegistry.AIRPLANE_URI);
return uris;
}
@Override
public Intent getSeeMoreIntent() {
- return null;
+ return new Intent(Settings.ACTION_WIRELESS_SETTINGS);
}
}
diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
index 2e84078..503a5c3 100644
--- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java
+++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
@@ -25,6 +25,8 @@
switch (panelType) {
case SettingsPanelActivity.PANEL_TYPE_WIFI:
return InternetConnectivityPanel.create(context);
+ case SettingsPanelActivity.PANEL_TYPE_VOLUME:
+ return VolumePanel.create(context);
}
throw new IllegalStateException("No matching panel for: " + panelType);
diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java
index bbdaec3..e61b8f8 100644
--- a/src/com/android/settings/panel/PanelFragment.java
+++ b/src/com/android/settings/panel/PanelFragment.java
@@ -16,19 +16,20 @@
package com.android.settings.panel;
-import android.net.Uri;
+import android.content.Intent;
import android.os.Bundle;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.LinearLayout;
+import android.widget.Button;
+import android.widget.TextView;
-import androidx.lifecycle.LiveData;
-import androidx.slice.Slice;
-import androidx.slice.widget.SliceLiveData;
-import androidx.slice.widget.SliceView;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import androidx.annotation.NonNull;
@@ -38,20 +39,24 @@
import com.android.settings.overlay.FeatureFactory;
-import java.util.ArrayList;
-import java.util.List;
-
public class PanelFragment extends Fragment {
private static final String TAG = "PanelFragment";
- private List<SliceView> mSliceViewList;
- private List<LiveData<Slice>> mSliceDataList;
- private LinearLayout mPanelLayout;
+ private TextView mTitleView;
+ private Button mSeeMoreButton;
+ private Button mDoneButton;
+ private RecyclerView mPanelSlices;
+
+ @VisibleForTesting
+ PanelSlicesAdapter mAdapter;
+
+ private View.OnClickListener mDoneButtonListener = (v) -> {
+ Log.d(TAG, "Closing dialog");
+ getActivity().finish();
+ };
public PanelFragment() {
- mSliceViewList = new ArrayList<>();
- mSliceDataList = new ArrayList<>();
}
@Nullable
@@ -61,28 +66,37 @@
final FragmentActivity activity = getActivity();
final View view = inflater.inflate(R.layout.panel_layout, container, false);
- mPanelLayout = view.findViewById(R.id.panel_parent_layout);
- final Bundle arguments = getArguments();
+ mPanelSlices = view.findViewById(R.id.panel_parent_layout);
+ mSeeMoreButton = view.findViewById(R.id.see_more);
+ mDoneButton = view.findViewById(R.id.done);
+ mTitleView = view.findViewById(R.id.title);
+ final Bundle arguments = getArguments();
final String panelType = arguments.getString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT);
final PanelContent panel = FeatureFactory.getFactory(activity)
.getPanelFeatureProvider()
.getPanel(activity, panelType);
- activity.setTitle(panel.getTitle());
+ mAdapter = new PanelSlicesAdapter(this, panel.getSlices());
+ mPanelSlices.setHasFixedSize(true);
+ mPanelSlices.setLayoutManager(new LinearLayoutManager((activity)));
+ mPanelSlices.setAdapter(mAdapter);
- for (Uri uri : panel.getSlices()) {
- final SliceView sliceView = new SliceView(activity);
- mPanelLayout.addView(sliceView);
- final LiveData<Slice> liveData = SliceLiveData.fromUri(activity, uri);
- liveData.observe(this /* lifecycleOwner */, sliceView);
+ mTitleView.setText(panel.getTitle());
- mSliceDataList.add(liveData);
- mSliceViewList.add(sliceView);
- }
+ mSeeMoreButton.setOnClickListener(getSeeMoreListener(panel.getSeeMoreIntent()));
+ mDoneButton.setOnClickListener(mDoneButtonListener);
return view;
}
+
+ private View.OnClickListener getSeeMoreListener(final Intent intent) {
+ return (v) -> {
+ final FragmentActivity activity = getActivity();
+ activity.startActivity(intent);
+ activity.finish();
+ };
+ }
}
diff --git a/src/com/android/settings/panel/PanelSlicesAdapter.java b/src/com/android/settings/panel/PanelSlicesAdapter.java
new file mode 100644
index 0000000..f688512
--- /dev/null
+++ b/src/com/android/settings/panel/PanelSlicesAdapter.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.panel;
+
+import android.content.Context;
+import android.net.Uri;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.slice.Slice;
+import androidx.slice.widget.SliceLiveData;
+import androidx.slice.widget.SliceView;
+
+import com.android.settings.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * RecyclerView adapter for Slices in Settings Panels.
+ */
+public class PanelSlicesAdapter
+ extends RecyclerView.Adapter<PanelSlicesAdapter.SliceRowViewHolder> {
+
+ private final List<Uri> mSliceUris;
+ private final PanelFragment mPanelFragment;
+
+ public PanelSlicesAdapter(PanelFragment fragment, List<Uri> sliceUris) {
+ mPanelFragment = fragment;
+ mSliceUris = new ArrayList<>(sliceUris);
+ }
+
+ @NonNull
+ @Override
+ public SliceRowViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
+ final Context context = viewGroup.getContext();
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ final View view = inflater.inflate(R.layout.panel_slice_row, viewGroup, false);
+
+ return new SliceRowViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull SliceRowViewHolder sliceRowViewHolder, int position) {
+ sliceRowViewHolder.onBind(mPanelFragment, mSliceUris.get(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return mSliceUris.size();
+ }
+
+ @VisibleForTesting
+ List<Uri> getData() {
+ return mSliceUris;
+ }
+
+ /**
+ * ViewHolder for binding Slices to SliceViews.
+ */
+ public static class SliceRowViewHolder extends RecyclerView.ViewHolder {
+
+ @VisibleForTesting
+ LiveData<Slice> sliceLiveData;
+
+ @VisibleForTesting
+ final SliceView sliceView;
+
+ public SliceRowViewHolder(View view) {
+ super(view);
+ sliceView = view.findViewById(R.id.slice_view);
+ sliceView.setMode(SliceView.MODE_LARGE);
+ }
+
+ public void onBind(PanelFragment fragment, Uri sliceUri) {
+ final Context context = sliceView.getContext();
+ sliceLiveData = SliceLiveData.fromUri(context, sliceUri);
+ sliceLiveData.observe(fragment.getViewLifecycleOwner(), sliceView);
+ }
+ }
+}
diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java
index db1f60d..09bead4 100644
--- a/src/com/android/settings/panel/SettingsPanelActivity.java
+++ b/src/com/android/settings/panel/SettingsPanelActivity.java
@@ -54,6 +54,9 @@
// TODO (b/117804442) move to framework
public static final String PANEL_TYPE_WIFI = "wifi_panel";
+ // TODO (b/117804442) move to framework
+ public static final String PANEL_TYPE_VOLUME = "volume_panel";
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java
new file mode 100644
index 0000000..c0118d7
--- /dev/null
+++ b/src/com/android/settings/panel/VolumePanel.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.panel;
+
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_ALARM_URI;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_CALL_URI;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_MEDIA_URI;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_RINGER_URI;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import java.util.ArrayList;
+import java.util.List;
+
+public class VolumePanel implements PanelContent {
+
+ private final Context mContext;
+
+ public static VolumePanel create(Context context) {
+ return new VolumePanel(context);
+ }
+
+ private VolumePanel(Context context) {
+ mContext = context.getApplicationContext();
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mContext.getText(R.string.volume_connectivity_panel_title);
+ }
+
+ @Override
+ public List<Uri> getSlices() {
+ final List<Uri> uris = new ArrayList<>();
+ uris.add(VOLUME_MEDIA_URI);
+ uris.add(VOLUME_CALL_URI);
+ uris.add(VOLUME_RINGER_URI);
+ uris.add(VOLUME_ALARM_URI);
+ return uris;
+ }
+
+ @Override
+ public Intent getSeeMoreIntent() {
+ return new Intent(Settings.ACTION_SOUND_SETTINGS);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index 3c1c62b..34f8629 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -68,8 +68,10 @@
if (activity == null || toolbar == null) {
return;
}
- if (!Utils.isPackageEnabled(activity, getSettingsIntelligencePkgName(activity))) {
- final ViewGroup parent = (ViewGroup)toolbar.getParent();
+
+ if (!Utils.isDeviceProvisioned(activity) ||
+ !Utils.isPackageEnabled(activity, getSettingsIntelligencePkgName(activity))) {
+ final ViewGroup parent = (ViewGroup) toolbar.getParent();
if (parent != null) {
parent.setVisibility(View.GONE);
}
diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java
index 99e22a1..bef72b7 100644
--- a/src/com/android/settings/slices/CustomSliceManager.java
+++ b/src/com/android/settings/slices/CustomSliceManager.java
@@ -101,13 +101,13 @@
}
private void addSlices() {
- mUriMap.put(WifiSlice.WIFI_URI, WifiSlice.class);
- mUriMap.put(DataUsageSlice.DATA_USAGE_CARD_URI, DataUsageSlice.class);
- mUriMap.put(DeviceInfoSlice.DEVICE_INFO_CARD_URI, DeviceInfoSlice.class);
- mUriMap.put(StorageSlice.STORAGE_CARD_URI, StorageSlice.class);
- mUriMap.put(BatterySlice.BATTERY_CARD_URI, BatterySlice.class);
- mUriMap.put(ConnectedDeviceSlice.CONNECTED_DEVICE_URI, ConnectedDeviceSlice.class);
- mUriMap.put(LowStorageSlice.LOW_STORAGE_URI, LowStorageSlice.class);
- mUriMap.put(BatteryFixSlice.BATTERY_FIX_URI, BatteryFixSlice.class);
+ mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
+ mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatterySlice.class);
+ mUriMap.put(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI, ConnectedDeviceSlice.class);
+ mUriMap.put(CustomSliceRegistry.DATA_USAGE_SLICE_URI, DataUsageSlice.class);
+ mUriMap.put(CustomSliceRegistry.DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
+ mUriMap.put(CustomSliceRegistry.LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
+ mUriMap.put(CustomSliceRegistry.STORAGE_SLICE_URI, StorageSlice.class);
+ mUriMap.put(CustomSliceRegistry.WIFI_SLICE_URI, WifiSlice.class);
}
}
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
new file mode 100644
index 0000000..7ca92a9
--- /dev/null
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.slices;
+
+import static android.provider.SettingsSlicesContract.KEY_LOCATION;
+import static android.provider.SettingsSlicesContract.KEY_WIFI;
+
+import static com.android.settings.notification.ZenModePreferenceController.ZEN_MODE_KEY;
+
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.provider.SettingsSlicesContract;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
+import com.android.settings.wifi.calling.WifiCallingSliceHelper;
+
+/**
+ * A registry of custom slice Uris.
+ */
+public class CustomSliceRegistry {
+
+ /**
+ * Uri for Airplane mode Slice.
+ */
+ public static final Uri AIRPLANE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
+ .build();
+
+ /**
+ * Uri for Battery Fix Slice.
+ */
+ public static final Uri BATTERY_FIX_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
+ .appendPath(BatteryTipPreferenceController.PREF_NAME)
+ .build();
+ /**
+ * Backing Uri for the Battery info Slice.
+ */
+ public static final Uri BATTERY_INFO_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
+ .appendPath("battery_card")
+ .build();
+ /**
+ * Backing Uri for the Bluetooth Slice.
+ */
+ public static final Uri BLUETOOTH_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(SettingsSlicesContract.KEY_BLUETOOTH)
+ .build();
+
+ /**
+ * Backing Uri for Connected device Slice.
+ */
+ public static final Uri CONNECTED_DEVICE_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("connected_device")
+ .build();
+ /**
+ * Backing Uri for the Data usage Slice.
+ */
+ public static final Uri DATA_USAGE_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath("data_usage_card")
+ .build();
+ /**
+ * Backing Uri for the Device info Slice.
+ */
+ public static final Uri DEVICE_INFO_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath("device_info_card")
+ .build();
+ /**
+ * Backing Uri for the Emergency Info Slice.
+ */
+ public static final Uri EMERGENCY_INFO_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath("emergency_info_card")
+ .build();
+ /**
+ * Slice Uri for Enhanced 4G slice
+ */
+ public static final Uri ENHANCED_4G_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath("enhanced_4g_lte")
+ .build();
+ /**
+ * Backing Uri for the Flashlight Slice.
+ */
+ public static final Uri FLASHLIGHT_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("flashlight")
+ .build();
+ /**
+ * Backing Uri for the Location Slice.
+ */
+ public static final Uri LOCATION_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(KEY_LOCATION)
+ .build();
+ /**
+ * Backing Uri for Low storage Slice.
+ */
+ public static final Uri LOW_STORAGE_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendEncodedPath(SettingsSlicesContract.PATH_SETTING_INTENT)
+ .appendPath("low_storage")
+ .build();
+ /**
+ * Backing Uri for the storage slice.
+ */
+ public static final Uri STORAGE_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath("storage_card")
+ .build();
+ /**
+ * Full {@link Uri} for the Alarm volume Slice.
+ */
+ public static final Uri VOLUME_ALARM_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("alarm_volume")
+ .build();
+ /**
+ * Full {@link Uri} for the Call Volume Slice.
+ */
+ public static final Uri VOLUME_CALL_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("call_volume")
+ .build();
+ /**
+ * Full {@link Uri} for the Media Volume Slice.
+ */
+ public static final Uri VOLUME_MEDIA_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("media_volume")
+ .build();
+ /**
+ * Full {@link Uri} for the Ringer volume Slice.
+ */
+ public static final Uri VOLUME_RINGER_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("ring_volume")
+ .build();
+
+ /**
+ * Full {@link Uri} for the Wifi Calling Slice.
+ */
+ public static final Uri WIFI_CALLING_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(WifiCallingSliceHelper.PATH_WIFI_CALLING)
+ .build();
+ /**
+ * Full {@link Uri} for the Wifi Calling Preference Slice.
+ */
+ public static final Uri WIFI_CALLING_PREFERENCE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(WifiCallingSliceHelper.PATH_WIFI_CALLING_PREFERENCE)
+ .build();
+ /**
+ * Backing Uri for the Wifi Slice.
+ */
+ public static final Uri WIFI_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(KEY_WIFI)
+ .build();
+ /**
+ * Backing Uri for the Zen Mode Slice.
+ */
+ public static final Uri ZEN_MODE_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(ZEN_MODE_KEY)
+ .build();
+}
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 952fc8b..109f02e 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -44,11 +44,8 @@
import com.android.settings.flashlight.FlashlightSliceBuilder;
import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSlice;
import com.android.settings.location.LocationSliceBuilder;
-import com.android.settings.network.telephony.Enhanced4gLteSliceHelper;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.wifi.WifiSlice;
-import com.android.settings.wifi.calling.WifiCallingSliceHelper;
import com.android.settingslib.SliceBroadcastRelay;
import com.android.settingslib.utils.ThreadUtils;
@@ -175,23 +172,21 @@
if (filter != null) {
registerIntentToUri(filter, sliceUri);
}
- ThreadUtils.postOnMainThread(() -> {
- startBackgroundWorker(sliceable);
- });
+ ThreadUtils.postOnMainThread(() -> startBackgroundWorker(sliceable));
return;
}
- if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
+ if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
registerIntentToUri(ZenModeSliceBuilder.INTENT_FILTER, sliceUri);
return;
- } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
registerIntentToUri(BluetoothSliceBuilder.INTENT_FILTER, sliceUri);
return;
- } else if (FlashlightSliceBuilder.FLASHLIGHT_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.FLASHLIGHT_SLICE_URI.equals(sliceUri)) {
registerIntentToUri(FlashlightSliceBuilder.INTENT_FILTER, sliceUri);
mRegisteredUris.add(sliceUri);
return;
- } else if (EmergencyInfoSlice.EMERGENCY_INFO_CARD_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI.equals(sliceUri)) {
return;
}
@@ -236,30 +231,30 @@
return sliceable.getSlice();
}
- if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) {
+ if (CustomSliceRegistry.WIFI_CALLING_URI.equals(sliceUri)) {
return FeatureFactory.getFactory(getContext())
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(getContext())
.createWifiCallingSlice(sliceUri);
- } else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
return ZenModeSliceBuilder.getSlice(getContext());
- } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
return BluetoothSliceBuilder.getSlice(getContext());
- } else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.LOCATION_SLICE_URI.equals(sliceUri)) {
return LocationSliceBuilder.getSlice(getContext());
- } else if (Enhanced4gLteSliceHelper.SLICE_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.ENHANCED_4G_SLICE_URI.equals(sliceUri)) {
return FeatureFactory.getFactory(getContext())
.getSlicesFeatureProvider()
.getNewEnhanced4gLteSliceHelper(getContext())
.createEnhanced4gLteSlice(sliceUri);
- } else if (WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI.equals(sliceUri)) {
return FeatureFactory.getFactory(getContext())
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(getContext())
.createWifiCallingPreferenceSlice(sliceUri);
- } else if (FlashlightSliceBuilder.FLASHLIGHT_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.FLASHLIGHT_SLICE_URI.equals(sliceUri)) {
return FlashlightSliceBuilder.getSlice(getContext());
- } else if (EmergencyInfoSlice.EMERGENCY_INFO_CARD_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI.equals(sliceUri)) {
return EmergencyInfoSlice.getSlice(getContext());
}
@@ -476,16 +471,16 @@
private List<Uri> getSpecialCasePlatformUris() {
return Arrays.asList(
- WifiSlice.WIFI_URI,
- BluetoothSliceBuilder.BLUETOOTH_URI,
- LocationSliceBuilder.LOCATION_URI
+ CustomSliceRegistry.WIFI_SLICE_URI,
+ CustomSliceRegistry.BLUETOOTH_URI,
+ CustomSliceRegistry.LOCATION_SLICE_URI
);
}
private List<Uri> getSpecialCaseOemUris() {
return Arrays.asList(
- ZenModeSliceBuilder.ZEN_MODE_URI,
- FlashlightSliceBuilder.FLASHLIGHT_URI
+ CustomSliceRegistry.ZEN_MODE_SLICE_URI,
+ CustomSliceRegistry.FLASHLIGHT_SLICE_URI
);
}
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index f18225a..c16a8ba 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -168,10 +168,11 @@
* @return {@link PendingIntent} for a non-primary {@link SliceAction}.
*/
public static PendingIntent getActionIntent(Context context, String action, SliceData data) {
- final Intent intent = new Intent(action);
- intent.setClass(context, SliceBroadcastReceiver.class);
- intent.putExtra(EXTRA_SLICE_KEY, data.getKey());
- intent.putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined());
+ final Intent intent = new Intent(action)
+ .setData(data.getUri())
+ .setClass(context, SliceBroadcastReceiver.class)
+ .putExtra(EXTRA_SLICE_KEY, data.getKey())
+ .putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined());
return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
}
@@ -193,8 +194,9 @@
CharSequence summaryText = controller.getSummary();
// Priority 1 : User prefers showing the dynamic summary in slice view rather than static
- // summary.
- if (isDynamicSummaryAllowed && isValidSummary(context, summaryText)) {
+ // summary. Note it doesn't require a valid summary - so we can force some slices to have
+ // empty summaries (ex: volume).
+ if (isDynamicSummaryAllowed) {
return summaryText;
}
@@ -279,7 +281,8 @@
.setTitle(sliceData.getTitle())
.setSubtitle(subtitleText)
.setPrimaryAction(
- new SliceAction(contentIntent, icon, sliceData.getTitle()))
+ SliceAction.createDeeplink(contentIntent, icon,
+ ListBuilder.ICON_IMAGE, sliceData.getTitle()))
.addEndItem(sliceAction))
.setKeywords(keywords)
.build();
@@ -299,7 +302,9 @@
.setTitle(sliceData.getTitle())
.setSubtitle(subtitleText)
.setPrimaryAction(
- new SliceAction(contentIntent, icon, sliceData.getTitle())))
+ SliceAction.createDeeplink(contentIntent, icon,
+ ListBuilder.ICON_IMAGE,
+ sliceData.getTitle())))
.setKeywords(keywords)
.build();
}
@@ -312,8 +317,8 @@
final IconCompat icon = getSafeIcon(context, sliceData);
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
- final SliceAction primaryAction = new SliceAction(contentIntent, icon,
- sliceData.getTitle());
+ final SliceAction primaryAction = SliceAction.createDeeplink(contentIntent, icon,
+ ListBuilder.ICON_IMAGE, sliceData.getTitle());
final Set<String> keywords = buildSliceKeywords(sliceData);
return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
@@ -334,7 +339,8 @@
final SliceAction copyableAction = getCopyableAction(context, sliceData);
final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
final IconCompat icon = getSafeIcon(context, sliceData);
- final SliceAction primaryAction = new SliceAction(contentIntent, icon,
+ final SliceAction primaryAction = SliceAction.createDeeplink(contentIntent, icon,
+ ListBuilder.ICON_IMAGE,
sliceData.getTitle());
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
@@ -366,7 +372,7 @@
boolean isChecked) {
PendingIntent actionIntent = getActionIntent(context,
SettingsSliceProvider.ACTION_TOGGLE_CHANGED, sliceData);
- return new SliceAction(actionIntent, null, isChecked);
+ return SliceAction.createToggle(actionIntent, null, isChecked);
}
private static PendingIntent getSliderAction(Context context, SliceData sliceData) {
@@ -378,7 +384,7 @@
SettingsSliceProvider.ACTION_COPY, sliceData);
final IconCompat icon = IconCompat.createWithResource(context,
R.drawable.ic_content_copy_grey600_24dp);
- return new SliceAction(intent, icon, sliceData.getTitle());
+ return SliceAction.create(intent, icon, ListBuilder.ICON_IMAGE, sliceData.getTitle());
}
private static boolean isValidSummary(Context context, CharSequence summary) {
@@ -421,14 +427,15 @@
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final CharSequence summary = context.getText(R.string.disabled_dependent_setting_summary);
final IconCompat icon = getSafeIcon(context, data);
- final SliceAction primaryAction = new SliceAction(getContentPendingIntent(context, data),
- icon, title);
+ final SliceAction primaryAction = SliceAction.createDeeplink(
+ getContentPendingIntent(context, data),
+ icon, ListBuilder.ICON_IMAGE, title);
return new ListBuilder(context, data.getUri(), ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)
- .setTitleItem(icon, ListBuilder.SMALL_IMAGE)
+ .setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setSubtitle(summary)
.setPrimaryAction(primaryAction))
.setKeywords(keywords)
diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
index 7531778..01708af 100644
--- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
+++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
@@ -62,11 +62,11 @@
final CustomSliceable sliceable =
customSliceManager.getSliceableFromUri(sliceUri);
launchIntent = sliceable.getIntent();
- } else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
launchIntent = ZenModeSliceBuilder.getIntent(this /* context */);
- } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
launchIntent = BluetoothSliceBuilder.getIntent(this /* context */);
- } else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
+ } else if (CustomSliceRegistry.LOCATION_SLICE_URI.equals(sliceUri)) {
launchIntent = LocationSliceBuilder.getIntent(this /* context */);
} else {
final SlicesDatabaseAccessor slicesDatabaseAccessor =
diff --git a/src/com/android/settings/slices/SlicesDatabaseAccessor.java b/src/com/android/settings/slices/SlicesDatabaseAccessor.java
index 35a0a5d..c75f3ef 100644
--- a/src/com/android/settings/slices/SlicesDatabaseAccessor.java
+++ b/src/com/android/settings/slices/SlicesDatabaseAccessor.java
@@ -71,6 +71,9 @@
*/
public SliceData getSliceDataFromUri(Uri uri) {
Pair<Boolean, String> pathData = SliceBuilderUtils.getPathData(uri);
+ if (pathData == null) {
+ throw new IllegalStateException("Invalid Slices uri: " + uri);
+ }
Cursor cursor = getIndexedSliceData(pathData.second /* key */);
return buildSliceData(cursor, uri, pathData.first /* isIntentOnly */);
}
diff --git a/src/com/android/settings/tts/TextToSpeechSettings.java b/src/com/android/settings/tts/TextToSpeechSettings.java
index b1a1f8f..bd85ef3 100644
--- a/src/com/android/settings/tts/TextToSpeechSettings.java
+++ b/src/com/android/settings/tts/TextToSpeechSettings.java
@@ -44,15 +44,14 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
-import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.GearPreference;
import com.android.settings.widget.SeekBarPreference;
import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.ActionButtonsPreference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -113,7 +112,7 @@
private SeekBarPreference mDefaultPitchPref;
private SeekBarPreference mDefaultRatePref;
- private ActionButtonPreference mActionButtons;
+ private ActionButtonsPreference mActionButtons;
private int mDefaultPitch = TextToSpeech.Engine.DEFAULT_PITCH;
private int mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
@@ -169,7 +168,7 @@
mDefaultPitchPref = (SeekBarPreference) findPreference(KEY_DEFAULT_PITCH);
mDefaultRatePref = (SeekBarPreference) findPreference(KEY_DEFAULT_RATE);
- mActionButtons = ((ActionButtonPreference) findPreference(KEY_ACTION_BUTTONS))
+ mActionButtons = ((ActionButtonsPreference) findPreference(KEY_ACTION_BUTTONS))
.setButton1Text(R.string.tts_play)
.setButton1OnClickListener(v -> speakSampleText())
.setButton1Enabled(false)
diff --git a/src/com/android/settings/widget/ActionButtonPreference.java b/src/com/android/settings/widget/ActionButtonPreference.java
deleted file mode 100644
index a34d735..0000000
--- a/src/com/android/settings/widget/ActionButtonPreference.java
+++ /dev/null
@@ -1,333 +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.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.StringRes;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-/**
- * This preference provides a four buttons layout with Settings style.
- * It looks like below
- *
- * --------------------------------------------------
- * button1 | button2 | button3 | button4 |
- * --------------------------------------------------
- *
- * User can set title / icon / click listener for each button.
- *
- * By default, four buttons are visible.
- * However, there are two cases which button should be invisible(View.GONE).
- *
- * 1. User sets invisible for button. ex: ActionButtonPreference.setButton1Visible(false)
- * 2. User doesn't set any title or icon for button.
- *
- */
-public class ActionButtonPreference extends Preference {
-
- private final String TAG = "ActionButtonPreference";
- private final ButtonInfo mButton1Info = new ButtonInfo();
- private final ButtonInfo mButton2Info = new ButtonInfo();
- private final ButtonInfo mButton3Info = new ButtonInfo();
- private final ButtonInfo mButton4Info = new ButtonInfo();
-
- public ActionButtonPreference(Context context, AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- init();
- }
-
- public ActionButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init();
- }
-
- public ActionButtonPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public ActionButtonPreference(Context context) {
- super(context);
- init();
- }
-
- private void init() {
- setLayoutResource(R.layout.settings_action_buttons);
- setSelectable(false);
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
- super.onBindViewHolder(holder);
- holder.setDividerAllowedAbove(true);
- holder.setDividerAllowedBelow(true);
-
- mButton1Info.mButton = (Button) holder.findViewById(R.id.button1);
- mButton2Info.mButton = (Button) holder.findViewById(R.id.button2);
- mButton3Info.mButton = (Button) holder.findViewById(R.id.button3);
- mButton4Info.mButton = (Button) holder.findViewById(R.id.button4);
-
- mButton1Info.setUpButton();
- mButton2Info.setUpButton();
- mButton3Info.setUpButton();
- mButton4Info.setUpButton();
- }
-
- public ActionButtonPreference setButton1Visible(boolean isVisible) {
- if (isVisible != mButton1Info.mIsVisible) {
- mButton1Info.mIsVisible = isVisible;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton1Text(@StringRes int textResId) {
- final String newText = getContext().getString(textResId);
- if (!TextUtils.equals(newText, mButton1Info.mText)) {
- mButton1Info.mText = newText;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton1Icon(@DrawableRes int iconResId) {
- if (iconResId == 0) {
- return this;
- }
-
- final Drawable icon;
- try {
- icon = getContext().getDrawable(iconResId);
- mButton1Info.mIcon = icon;
- notifyChanged();
- } catch (Resources.NotFoundException exception) {
- Log.e(TAG, "Resource does not exist: " + iconResId);
- }
- return this;
- }
-
- public ActionButtonPreference setButton1Enabled(boolean isEnabled) {
- if (isEnabled != mButton1Info.mIsEnabled) {
- mButton1Info.mIsEnabled = isEnabled;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton1OnClickListener(View.OnClickListener listener) {
- if (listener != mButton1Info.mListener) {
- mButton1Info.mListener = listener;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton2Visible(boolean isVisible) {
- if (isVisible != mButton2Info.mIsVisible) {
- mButton2Info.mIsVisible = isVisible;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton2Text(@StringRes int textResId) {
- final String newText = getContext().getString(textResId);
- if (!TextUtils.equals(newText, mButton2Info.mText)) {
- mButton2Info.mText = newText;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton2Icon(@DrawableRes int iconResId) {
- if (iconResId == 0) {
- return this;
- }
-
- final Drawable icon;
- try {
- icon = getContext().getDrawable(iconResId);
- mButton2Info.mIcon = icon;
- notifyChanged();
- } catch (Resources.NotFoundException exception) {
- Log.e(TAG, "Resource does not exist: " + iconResId);
- }
- return this;
- }
-
- public ActionButtonPreference setButton2Enabled(boolean isEnabled) {
- if (isEnabled != mButton2Info.mIsEnabled) {
- mButton2Info.mIsEnabled = isEnabled;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton2OnClickListener(View.OnClickListener listener) {
- if (listener != mButton2Info.mListener) {
- mButton2Info.mListener = listener;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton3Visible(boolean isVisible) {
- if (isVisible != mButton3Info.mIsVisible) {
- mButton3Info.mIsVisible = isVisible;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton3Text(@StringRes int textResId) {
- final String newText = getContext().getString(textResId);
- if (!TextUtils.equals(newText, mButton3Info.mText)) {
- mButton3Info.mText = newText;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton3Icon(@DrawableRes int iconResId) {
- if (iconResId == 0) {
- return this;
- }
-
- final Drawable icon;
- try {
- icon = getContext().getDrawable(iconResId);
- mButton3Info.mIcon = icon;
- notifyChanged();
- } catch (Resources.NotFoundException exception) {
- Log.e(TAG, "Resource does not exist: " + iconResId);
- }
- return this;
- }
-
- public ActionButtonPreference setButton3Enabled(boolean isEnabled) {
- if (isEnabled != mButton3Info.mIsEnabled) {
- mButton3Info.mIsEnabled = isEnabled;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton3OnClickListener(View.OnClickListener listener) {
- if (listener != mButton3Info.mListener) {
- mButton3Info.mListener = listener;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton4Visible(boolean isVisible) {
- if (isVisible != mButton4Info.mIsVisible) {
- mButton4Info.mIsVisible = isVisible;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton4Text(@StringRes int textResId) {
- final String newText = getContext().getString(textResId);
- if (!TextUtils.equals(newText, mButton4Info.mText)) {
- mButton4Info.mText = newText;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton4Icon(@DrawableRes int iconResId) {
- if (iconResId == 0) {
- return this;
- }
-
- final Drawable icon;
- try {
- icon = getContext().getDrawable(iconResId);
- mButton4Info.mIcon = icon;
- notifyChanged();
- } catch (Resources.NotFoundException exception) {
- Log.e(TAG, "Resource does not exist: " + iconResId);
- }
- return this;
- }
-
- public ActionButtonPreference setButton4Enabled(boolean isEnabled) {
- if (isEnabled != mButton4Info.mIsEnabled) {
- mButton4Info.mIsEnabled = isEnabled;
- notifyChanged();
- }
- return this;
- }
-
- public ActionButtonPreference setButton4OnClickListener(View.OnClickListener listener) {
- if (listener != mButton4Info.mListener) {
- mButton4Info.mListener = listener;
- notifyChanged();
- }
- return this;
- }
-
- static class ButtonInfo {
- private Button mButton;
- private CharSequence mText;
- private Drawable mIcon;
- private View.OnClickListener mListener;
- private boolean mIsEnabled = true;
- private boolean mIsVisible = true;
-
- void setUpButton() {
- mButton.setText(mText);
- mButton.setOnClickListener(mListener);
- mButton.setEnabled(mIsEnabled);
- mButton.setCompoundDrawablesWithIntrinsicBounds(
- null /* left */, mIcon /* top */, null /* right */, null /* bottom */);
-
- if (shouldBeVisible()) {
- mButton.setVisibility(View.VISIBLE);
- } else {
- mButton.setVisibility(View.GONE);
- }
- }
-
- /**
- * By default, four buttons are visible.
- * However, there are two cases which button should be invisible.
- *
- * 1. User set invisible for this button. ex: mIsVisible = false.
- * 2. User didn't set any title or icon.
- *
- */
- private boolean shouldBeVisible() {
- return mIsVisible && (!TextUtils.isEmpty(mText) || mIcon != null);
- }
- }
-}
\ No newline at end of file
diff --git a/src/com/android/settings/wifi/WifiDetailPreference.java b/src/com/android/settings/wifi/WifiDetailPreference.java
deleted file mode 100644
index 2567a42..0000000
--- a/src/com/android/settings/wifi/WifiDetailPreference.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.wifi;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-/**
- * A Preference to be used with the Wifi Network Detail Fragment that allows a summary text to be
- * set inside the widget resource
- */
-public class WifiDetailPreference extends Preference {
- private String mDetailText;
-
- public WifiDetailPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- setWidgetLayoutResource(R.layout.preference_widget_summary);
- }
-
- public void setDetailText(String text) {
- if (TextUtils.equals(mDetailText, text)) return;
- mDetailText = text;
- notifyChanged();
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder view) {
- super.onBindViewHolder(view);
- TextView textView = ((TextView) view.findViewById(R.id.widget_summary));
- textView.setText(mDetailText);
- textView.setPadding(0, 0, 10, 0);
- }
-}
diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/WifiSlice.java
index d06d830..2382abb 100644
--- a/src/com/android/settings/wifi/WifiSlice.java
+++ b/src/com/android/settings/wifi/WifiSlice.java
@@ -19,9 +19,10 @@
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static android.provider.SettingsSlicesContract.KEY_WIFI;
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
+
import android.annotation.ColorInt;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -30,7 +31,6 @@
import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid;
import android.os.Bundle;
-import android.provider.SettingsSlicesContract;
import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
@@ -60,16 +60,6 @@
*/
public class WifiSlice implements CustomSliceable {
- /**
- * Backing Uri for the Wifi Slice.
- */
- public static final Uri WIFI_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSlicesContract.AUTHORITY)
- .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
- .appendPath(KEY_WIFI)
- .build();
-
@VisibleForTesting
static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
@@ -81,7 +71,7 @@
@Override
public Uri getUri() {
- return WIFI_URI;
+ return WIFI_SLICE_URI;
}
@Override
@@ -92,9 +82,6 @@
return filter;
}
- /**
- * Return a Wifi Slice bound to {@link #WIFI_URI}.
- */
@Override
public Slice getSlice() {
final boolean isWifiEnabled = isWifiEnabled();
@@ -105,11 +92,13 @@
@ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
final PendingIntent toggleAction = getBroadcastIntent(mContext);
final PendingIntent primaryAction = getPrimaryAction();
- final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
- final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
- isWifiEnabled);
+ final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
+ ListBuilder.ICON_IMAGE, title);
+ final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
+ null /* actionTitle */, isWifiEnabled);
- final ListBuilder listBuilder = new ListBuilder(mContext, WIFI_URI, ListBuilder.INFINITY)
+ final ListBuilder listBuilder = new ListBuilder(mContext, WIFI_SLICE_URI,
+ ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
.setTitle(title)
@@ -151,8 +140,9 @@
.setSubtitle(!TextUtils.isEmpty(apSummary)
? apSummary
: mContext.getText(R.string.summary_placeholder))
- .setPrimaryAction(new SliceAction(
- getAccessPointAction(accessPoint), levelIcon, title));
+ .setPrimaryAction(SliceAction.create(
+ getAccessPointAction(accessPoint), levelIcon, ListBuilder.ICON_IMAGE,
+ title));
final IconCompat endIcon = getEndIcon(accessPoint);
if (endIcon != null) {
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
index 0629ad3..70eef2c 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java
@@ -18,9 +18,11 @@
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_CALLING_URI;
+
import android.app.PendingIntent;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -42,9 +44,7 @@
import com.android.ims.ImsManager;
import com.android.settings.R;
import com.android.settings.Utils;
-import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
-import com.android.settings.slices.SliceBuilderUtils;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
@@ -104,24 +104,6 @@
"android.settings.WIFI_CALLING_SETTINGS";
/**
- * Full {@link Uri} for the Wifi Calling Slice.
- */
- public static final Uri WIFI_CALLING_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_WIFI_CALLING)
- .build();
-
- /**
- * Full {@link Uri} for the Wifi Calling Preference Slice.
- */
- public static final Uri WIFI_CALLING_PREFERENCE_URI = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsSliceProvider.SLICE_AUTHORITY)
- .appendPath(PATH_WIFI_CALLING_PREFERENCE)
- .build();
-
- /**
* Timeout for querying wifi calling setting from ims manager.
*/
private static final int TIMEOUT_MILLIS = 2000;
@@ -212,12 +194,13 @@
.addRow(new RowBuilder()
.setTitle(mContext.getText(R.string.wifi_calling_settings_title))
.addEndItem(
- new SliceAction(
+ SliceAction.createToggle(
getBroadcastIntent(ACTION_WIFI_CALLING_CHANGED),
null /* actionTitle */, isWifiCallingEnabled))
- .setPrimaryAction(new SliceAction(
+ .setPrimaryAction(SliceAction.createDeeplink(
getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
icon,
+ ListBuilder.ICON_IMAGE,
mContext.getText(R.string.wifi_calling_settings_title))))
.build();
}
@@ -246,7 +229,7 @@
}
final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled(
- CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId,false);
+ CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false);
final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true);
final ImsManager imsManager = getImsManager(subId);
@@ -287,8 +270,8 @@
* Returns actionable wifi calling preference slice.
*
* @param isWifiOnlySupported adds row for wifi only if this is true
- * @param currentWfcPref current Preference {@link ImsConfig}
- * @param sliceUri sliceUri
+ * @param currentWfcPref current Preference {@link ImsConfig}
+ * @param sliceUri sliceUri
* @return Slice for actionable wifi calling preference settings
*/
private Slice getWifiCallingPreferenceSlice(boolean isWifiOnlySupported,
@@ -299,12 +282,13 @@
ListBuilder listBuilder = new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
listBuilder.setHeader(new ListBuilder.HeaderBuilder()
- .setTitle(mContext.getText(R.string.wifi_calling_mode_title))
- .setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref))
- .setPrimaryAction(new SliceAction(
- getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
- icon,
- mContext.getText(R.string.wifi_calling_mode_title))));
+ .setTitle(mContext.getText(R.string.wifi_calling_mode_title))
+ .setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref))
+ .setPrimaryAction(SliceAction.createDeeplink(
+ getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
+ icon,
+ ListBuilder.ICON_IMAGE,
+ mContext.getText(R.string.wifi_calling_mode_title))));
if (isWifiOnlySupported) {
listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder,
@@ -329,9 +313,9 @@
/**
* Returns RowBuilder for a new row containing specific wifi calling preference.
*
- * @param listBuilder ListBuilder that will be the parent for this RowBuilder
+ * @param listBuilder ListBuilder that will be the parent for this RowBuilder
* @param preferenceTitleResId resource Id for the preference row title
- * @param action action to be added for the row
+ * @param action action to be added for the row
* @return RowBuilder for the row
*/
private RowBuilder wifiPreferenceRowBuilder(ListBuilder listBuilder,
@@ -340,7 +324,7 @@
IconCompat.createWithResource(mContext, R.drawable.radio_button_check);
return new RowBuilder()
.setTitle(mContext.getText(preferenceTitleResId))
- .setTitleItem(new SliceAction(getBroadcastIntent(action),
+ .setTitleItem(SliceAction.createToggle(getBroadcastIntent(action),
icon, mContext.getText(preferenceTitleResId), checked));
}
@@ -414,8 +398,7 @@
}
// notify change in slice in any case to get re-queried. This would result in displaying
// appropriate message with the updated setting.
- final Uri uri = SliceBuilderUtils.getUri(PATH_WIFI_CALLING, false /*isPlatformSlice*/);
- mContext.getContentResolver().notifyChange(uri, null);
+ mContext.getContentResolver().notifyChange(WIFI_CALLING_URI, null);
}
/**
@@ -433,7 +416,7 @@
if (subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
final boolean isWifiCallingPrefEditable = isCarrierConfigManagerKeyEnabled(
- CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId,false);
+ CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, subId, false);
final boolean isWifiOnlySupported = isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, subId, true);
@@ -470,15 +453,13 @@
// notify change in slice in any case to get re-queried. This would result in displaying
// appropriate message.
- final Uri uri = SliceBuilderUtils.getUri(PATH_WIFI_CALLING_PREFERENCE,
- false /*isPlatformSlice*/);
- mContext.getContentResolver().notifyChange(uri, null);
+ mContext.getContentResolver().notifyChange(WIFI_CALLING_PREFERENCE_URI, null);
}
/**
* Returns Slice with the title and subtitle provided as arguments with wifi signal Icon.
*
- * @param title Title of the slice
+ * @param title Title of the slice
* @param subtitle Subtitle of the slice
* @param sliceUri slice uri
* @return Slice with title and subtitle
@@ -491,8 +472,8 @@
.addRow(new RowBuilder()
.setTitle(title)
.setSubtitle(subtitle)
- .setPrimaryAction(new SliceAction(
- primaryActionIntent, icon,
+ .setPrimaryAction(SliceAction.createDeeplink(
+ primaryActionIntent, icon, ListBuilder.SMALL_IMAGE,
title)))
.build();
}
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 9a3398a..a676bfa 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -55,9 +55,7 @@
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.EntityHeaderController;
-import com.android.settings.wifi.WifiDetailPreference;
import com.android.settings.wifi.WifiDialog;
import com.android.settings.wifi.WifiDialog.WifiDialogListener;
import com.android.settings.wifi.WifiUtils;
@@ -67,6 +65,7 @@
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.widget.ActionButtonsPreference;
import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.wifi.AccessPoint;
@@ -131,17 +130,17 @@
private final MetricsFeatureProvider mMetricsFeatureProvider;
// UI elements - in order of appearance
- private ActionButtonPreference mButtonsPref;
+ private ActionButtonsPreference mButtonsPref;
private EntityHeaderController mEntityHeaderController;
- private WifiDetailPreference mSignalStrengthPref;
- private WifiDetailPreference mLinkSpeedPref;
- private WifiDetailPreference mFrequencyPref;
- private WifiDetailPreference mSecurityPref;
- private WifiDetailPreference mMacAddressPref;
- private WifiDetailPreference mIpAddressPref;
- private WifiDetailPreference mGatewayPref;
- private WifiDetailPreference mSubnetPref;
- private WifiDetailPreference mDnsPref;
+ private Preference mSignalStrengthPref;
+ private Preference mLinkSpeedPref;
+ private Preference mFrequencyPref;
+ private Preference mSecurityPref;
+ private Preference mMacAddressPref;
+ private Preference mIpAddressPref;
+ private Preference mGatewayPref;
+ private Preference mSubnetPref;
+ private Preference mDnsPref;
private PreferenceCategory mIpv6Category;
private Preference mIpv6AddressPref;
@@ -276,29 +275,28 @@
setupEntityHeader(screen);
- mButtonsPref = ((ActionButtonPreference) screen.findPreference(KEY_BUTTONS_PREF))
+ mButtonsPref = ((ActionButtonsPreference) screen.findPreference(KEY_BUTTONS_PREF))
.setButton1Text(R.string.forget)
.setButton1Icon(R.drawable.ic_settings_delete)
.setButton1OnClickListener(view -> forgetNetwork())
.setButton2Text(R.string.wifi_sign_in_button_text)
.setButton2OnClickListener(view -> signIntoNetwork());
- mSignalStrengthPref =
- (WifiDetailPreference) screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
- mLinkSpeedPref = (WifiDetailPreference) screen.findPreference(KEY_LINK_SPEED);
- mFrequencyPref = (WifiDetailPreference) screen.findPreference(KEY_FREQUENCY_PREF);
- mSecurityPref = (WifiDetailPreference) screen.findPreference(KEY_SECURITY_PREF);
+ mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
+ mLinkSpeedPref = screen.findPreference(KEY_LINK_SPEED);
+ mFrequencyPref = screen.findPreference(KEY_FREQUENCY_PREF);
+ mSecurityPref = screen.findPreference(KEY_SECURITY_PREF);
- mMacAddressPref = (WifiDetailPreference) screen.findPreference(KEY_MAC_ADDRESS_PREF);
- mIpAddressPref = (WifiDetailPreference) screen.findPreference(KEY_IP_ADDRESS_PREF);
- mGatewayPref = (WifiDetailPreference) screen.findPreference(KEY_GATEWAY_PREF);
- mSubnetPref = (WifiDetailPreference) screen.findPreference(KEY_SUBNET_MASK_PREF);
- mDnsPref = (WifiDetailPreference) screen.findPreference(KEY_DNS_PREF);
+ mMacAddressPref = screen.findPreference(KEY_MAC_ADDRESS_PREF);
+ mIpAddressPref = screen.findPreference(KEY_IP_ADDRESS_PREF);
+ mGatewayPref = screen.findPreference(KEY_GATEWAY_PREF);
+ mSubnetPref = screen.findPreference(KEY_SUBNET_MASK_PREF);
+ mDnsPref = screen.findPreference(KEY_DNS_PREF);
mIpv6Category = (PreferenceCategory) screen.findPreference(KEY_IPV6_CATEGORY);
mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
- mSecurityPref.setDetailText(mAccessPoint.getSecurityString(false /* concise */));
+ mSecurityPref.setSummary(mAccessPoint.getSecurityString(false /* concise */));
}
private void setupEntityHeader(PreferenceScreen screen) {
@@ -359,12 +357,12 @@
refreshRssiViews();
// MAC Address Pref
- mMacAddressPref.setDetailText(mWifiInfo.getMacAddress());
+ mMacAddressPref.setSummary(mWifiInfo.getMacAddress());
// Link Speed Pref
int linkSpeedMbps = mWifiInfo.getLinkSpeed();
mLinkSpeedPref.setVisible(linkSpeedMbps >= 0);
- mLinkSpeedPref.setDetailText(mContext.getString(
+ mLinkSpeedPref.setSummary(mContext.getString(
R.string.link_speed, mWifiInfo.getLinkSpeed()));
// Frequency Pref
@@ -379,7 +377,7 @@
} else {
Log.e(TAG, "Unexpected frequency " + frequency);
}
- mFrequencyPref.setDetailText(band);
+ mFrequencyPref.setSummary(band);
updateIpLayerInfo();
}
@@ -410,16 +408,15 @@
mEntityHeaderController.setIcon(wifiIcon).done(mFragment.getActivity(), true /* rebind */);
Drawable wifiIconDark = wifiIcon.getConstantState().newDrawable().mutate();
- wifiIconDark.setTint(mContext.getResources().getColor(
- R.color.wifi_details_icon_color, mContext.getTheme()));
+ wifiIconDark.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal));
mSignalStrengthPref.setIcon(wifiIconDark);
- mSignalStrengthPref.setDetailText(mSignalStr[mRssiSignalLevel]);
+ mSignalStrengthPref.setSummary(mSignalStr[mRssiSignalLevel]);
}
- private void updatePreference(WifiDetailPreference pref, String detailText) {
+ private void updatePreference(Preference pref, String detailText) {
if (!TextUtils.isEmpty(detailText)) {
- pref.setDetailText(detailText);
+ pref.setSummary(detailText);
pref.setVisible(true);
} else {
pref.setVisible(false);
diff --git a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
new file mode 100644
index 0000000..177e79d
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import android.os.Bundle;
+
+import com.android.settings.R;
+
+/**
+ * After getting Wi-Fi network information and(or) QR code, this fragment config a device to connect
+ * to the Wi-Fi network.
+ */
+public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
+ @Override
+ protected int getLayout() {
+ return R.layout.wifi_dpp_add_device_fragment;
+ }
+
+ @Override
+ public void onActivityCreated (Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ }
+}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
new file mode 100644
index 0000000..7d031c1
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import android.os.Bundle;
+
+import com.android.settings.R;
+
+/**
+ * After a camera APP scanned a Wi-Fi DPP QR code, it can trigger
+ * {@code WifiDppConfiguratorActivity} to start with this fragment to choose a saved Wi-Fi network.
+ */
+public class WifiDppChooseSavedWifiNetworkFragment extends WifiDppQrCodeBaseFragment {
+ @Override
+ protected int getLayout() {
+ return R.layout.wifi_dpp_choose_saved_wifi_network_fragment;
+ }
+
+ @Override
+ public void onActivityCreated (Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ }
+}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
index bccb53a..d81c19b 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
@@ -18,9 +18,11 @@
import android.app.ActionBar;
import android.app.Activity;
+import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
+import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
@@ -29,32 +31,22 @@
import com.android.settings.core.InstrumentedActivity;
import com.android.settings.R;
-public class WifiDppConfiguratorActivity extends InstrumentedActivity {
+public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
+ WifiNetworkConfig.Retriever {
private static final String TAG = "WifiDppConfiguratorActivity";
+ public static final String ACTION_CONFIGURATOR_QR_CODE_SCANNER =
+ "android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER";
+ public static final String ACTION_CONFIGURATOR_QR_CODE_GENERATOR =
+ "android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR";
+ public static final String ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK =
+ "android.settings.WIFI_DPP_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK";
+
private FragmentManager mFragmentManager;
private FragmentTransaction mFragmentTransaction;
- public static final String EXTRA_LAUNCH_MODE =
- "com.android.settings.wifi.dpp.EXTRA_LAUNCH_MODE";
- public static final String EXTRA_SSID = "com.android.settings.wifi.dpp.EXTRA_SSID";
-
- public enum LaunchMode {
- LAUNCH_MODE_QR_CODE_SCANNER(1),
- LAUNCH_MODE_QR_CODE_GENERATOR(2),
- LAUNCH_MODE_CHOOSE_SAVED_WIFI_NETWORK(3),
- LAUNCH_MODE_NOT_DEFINED(-1);
-
- private int mMode;
-
- LaunchMode(int mode) {
- this.mMode = mode;
- }
-
- public int getMode() {
- return mMode;
- }
- }
+ /** The Wi-Fi network which will be configured */
+ private WifiNetworkConfig mWifiNetworkConfig;
@Override
public int getMetricsCategory() {
@@ -67,25 +59,98 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.wifi_dpp_activity);
- // Hide action bar
+ mFragmentManager = getSupportFragmentManager();
+ mFragmentTransaction = getSupportFragmentManager().beginTransaction();
+
+ Intent intent = getIntent();
+ boolean cancelActivity = false;
+ WifiNetworkConfig config;
+ switch (intent.getAction()) {
+ case ACTION_CONFIGURATOR_QR_CODE_SCANNER:
+ config = WifiNetworkConfig.getValidConfigOrNull(intent);
+ if (config == null) {
+ cancelActivity = true;
+ } else {
+ mWifiNetworkConfig = config;
+ addQrCodeScannerFragment(/* addToBackStack= */ false);
+ }
+ break;
+ case ACTION_CONFIGURATOR_QR_CODE_GENERATOR:
+ config = WifiNetworkConfig.getValidConfigOrNull(intent);
+ if (config == null) {
+ cancelActivity = true;
+ } else {
+ mWifiNetworkConfig = config;
+ addQrCodeGeneratorFragment();
+ }
+ break;
+ case ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK:
+ addChooseSavedWifiNetworkFragment(/* addToBackStack */ false);
+ break;
+ default:
+ cancelActivity = true;
+ Log.e(TAG, "Launch with an invalid action");
+ }
+
+ if (cancelActivity) {
+ setResult(Activity.RESULT_CANCELED);
+ finish();
+ }
+ }
+
+ private void addQrCodeScannerFragment(boolean addToBackStack) {
+ WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment();
+ mFragmentTransaction.add(R.id.fragment_container, fragment);
+ if (addToBackStack) {
+ mFragmentTransaction.addToBackStack(/* name */ null);
+ }
+ mFragmentTransaction.commit();
+ }
+
+ private void addQrCodeGeneratorFragment() {
+ WifiDppQrCodeGeneratorFragment fragment = new WifiDppQrCodeGeneratorFragment();
+ mFragmentTransaction.add(R.id.fragment_container, fragment);
+ mFragmentTransaction.commit();
+ }
+
+ private void addChooseSavedWifiNetworkFragment(boolean addToBackStack) {
ActionBar action = getActionBar();
if (action != null) {
action.hide();
}
- mFragmentManager = getSupportFragmentManager();
- mFragmentTransaction = getSupportFragmentManager().beginTransaction();
+ WifiDppChooseSavedWifiNetworkFragment fragment =
+ new WifiDppChooseSavedWifiNetworkFragment();
+ mFragmentTransaction.add(R.id.fragment_container, fragment);
+ if (addToBackStack) {
+ mFragmentTransaction.addToBackStack(/* name */ null);
+ }
+ mFragmentTransaction.commit();
+ }
- final int launchMode = getIntent().getIntExtra(EXTRA_LAUNCH_MODE,
- LaunchMode.LAUNCH_MODE_NOT_DEFINED.getMode());
- if (launchMode == LaunchMode.LAUNCH_MODE_QR_CODE_SCANNER.getMode()) {
- WifiDppQrCodeScannerFragment scanFragment = new WifiDppQrCodeScannerFragment();
- mFragmentTransaction.add(R.id.fragment_container, scanFragment);
- mFragmentTransaction.commit();
+ @Override
+ protected void onStop() {
+ Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
+ if (fragment != null) {
+ // Remove it to prevent stacking multiple fragments after screen rotated.
+ mFragmentManager.beginTransaction().remove(fragment).commit();
+ }
+
+ super.onStop();
+ }
+
+ @Override
+ public WifiNetworkConfig getWifiNetworkConfig() {
+ return mWifiNetworkConfig;
+ }
+
+ @Override
+ public boolean setWifiNetworkConfig(WifiNetworkConfig config) {
+ if(!WifiNetworkConfig.isValidConfig(config)) {
+ return false;
} else {
- Log.e(TAG, "Launch with an invalid mode extra");
- setResult(Activity.RESULT_CANCELED);
- finish();
+ mWifiNetworkConfig = new WifiNetworkConfig(config);
+ return true;
}
}
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
index 004cb18..c86fc98 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
@@ -22,20 +22,48 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.ProgressBar;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.wifi.qrcode.QrDecorateView;
import com.android.settings.R;
+/**
+ * There are below 4 fragments for Wi-Fi DPP UI flow, to reduce redundant code of UI components,
+ * this parent fragment instantiates all UI components and provides setting APIs for them.
+ *
+ * {@code WifiDppQrCodeScannerFragment}
+ * {@code WifiDppQrCodeGeneratorFragment}
+ * {@code WifiDppChooseSavedWifiNetworkFragment}
+ * {@code WifiDppAddDeviceFragment}
+ */
public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
private TextView mTitle;
private TextView mDescription;
- private SurfaceView mPreviewView;
- private TextView mErrorMessage; //optional, view used to surface connectivity errors to the user
- private Button mButtonLeft;
- private Button mButtonRight;
+
+ private SurfaceView mPreviewView; //optional, for WifiDppQrCodeScannerFragment
+ private QrDecorateView mDecorateViiew; //optional, for WifiDppQrCodeScannerFragment
+ private TextView mErrorMessage; //optional, for WifiDppQrCodeScannerFragment
+
+ private ImageView mBarcodeView; //optional, for WifiDppQrCodeGeneratorFragment
+
+ private ListView mSavedWifiNetworkList; //optional, for WifiDppChooseSavedWifiNetworkFragment
+
+ private ProgressBar mProgressBar; //optional, for WifiDppAddDeviceFragment
+ private ImageView mWifiApPictureView; //optional, for WifiDppAddDeviceFragment
+ private TextView mChooseDifferentNetwork;//optional, for WifiDppAddDeviceFragment
+
+ private Button mButtonLeft; //optional, for WifiDppQrCodeScannerFragment,
+ // WifiDppChooseSavedWifiNetworkFragment,
+ // WifiDppAddDeviceFragment
+ private Button mButtonRight; //optional, for WifiDppQrCodeScannerFragment,
+ // WifiDppChooseSavedWifiNetworkFragment,
+ // WifiDppAddDeviceFragment
abstract protected int getLayout();
@@ -61,8 +89,19 @@
private void initView(View view) {
mTitle = view.findViewById(R.id.title);
mDescription = view.findViewById(R.id.description);
+
mPreviewView = view.findViewById(R.id.preview_view);
+ mDecorateViiew = view.findViewById(R.id.decorate_view);
mErrorMessage = view.findViewById(R.id.error_message);
+
+ mBarcodeView = view.findViewById(R.id.barcode_view);
+
+ mSavedWifiNetworkList = view.findViewById(R.id.saved_wifi_network_list);
+
+ mProgressBar = view.findViewById(R.id.progress_bar);
+ mWifiApPictureView = view.findViewById(R.id.wifi_ap_picture_view);
+ mChooseDifferentNetwork = view.findViewById(R.id.choose_different_network);
+
mButtonLeft = view.findViewById(R.id.button_left);
mButtonRight = view.findViewById(R.id.button_right);
}
@@ -75,33 +114,76 @@
mDescription.setText(description);
}
+ /** optional, for WifiDppQrCodeScannerFragment */
protected void setErrorMessage(String errorMessage) {
if (mErrorMessage != null) {
mErrorMessage.setText(errorMessage);
}
}
+ /**
+ * optional, for WifiDppQrCodeScannerFragment,
+ * WifiDppChooseSavedWifiNetworkFragment,
+ * WifiDppAddDeviceFragment
+ */
protected void setLeftButtonText(String text) {
- mButtonLeft.setText(text);
+ if (mButtonLeft != null) {
+ mButtonLeft.setText(text);
+ }
}
+ /**
+ * optional, for WifiDppQrCodeScannerFragment,
+ * WifiDppChooseSavedWifiNetworkFragment,
+ * WifiDppAddDeviceFragment
+ */
protected void setRightButtonText(String text) {
- mButtonRight.setText(text);
+ if (mButtonRight != null) {
+ mButtonRight.setText(text);
+ }
}
+ /**
+ * optional, for WifiDppQrCodeScannerFragment,
+ * WifiDppChooseSavedWifiNetworkFragment,
+ * WifiDppAddDeviceFragment
+ */
protected void hideLeftButton() {
- mButtonLeft.setVisibility(View.INVISIBLE);
+ if (mButtonLeft != null) {
+ mButtonLeft.setVisibility(View.INVISIBLE);
+ }
}
+ /**
+ * optional, for WifiDppQrCodeScannerFragment,
+ * WifiDppChooseSavedWifiNetworkFragment,
+ * WifiDppAddDeviceFragment
+ */
protected void hideRightButton() {
- mButtonRight.setVisibility(View.INVISIBLE);
+ if (mButtonRight != null) {
+ mButtonRight.setVisibility(View.INVISIBLE);
+ }
}
+ /**
+ * optional, for WifiDppQrCodeScannerFragment,
+ * WifiDppChooseSavedWifiNetworkFragment,
+ * WifiDppAddDeviceFragment
+ */
protected void setLeftButtonOnClickListener(View.OnClickListener listener) {
- mButtonLeft.setOnClickListener(listener);
+ if (mButtonLeft != null) {
+ mButtonLeft.setOnClickListener(listener);
+ }
}
+ /**
+ * optional, for WifiDppQrCodeScannerFragment,
+ * WifiDppChooseSavedWifiNetworkFragment,
+ * WifiDppAddDeviceFragment
+ */
protected void setRightButtonOnClickListener(View.OnClickListener listener) {
- mButtonRight.setOnClickListener(listener);
+ if (mButtonRight != null) {
+ mButtonRight.setOnClickListener(listener);
+ }
}
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
new file mode 100644
index 0000000..9935bf2
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import android.os.Bundle;
+
+import com.android.settings.R;
+
+/**
+ * After sharing a saved Wi-Fi network, {@code WifiDppConfiguratorActivity} start with this fragment
+ * to generate a Wi-Fi DPP QR code for other device to initiate as an enrollee.
+ */
+public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
+ @Override
+ protected int getLayout() {
+ return R.layout.wifi_dpp_qrcode_generator_fragment;
+ }
+
+ @Override
+ public void onActivityCreated (Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ }
+}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index 0ee8434..70dade5 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -16,40 +16,117 @@
package com.android.settings.wifi.dpp;
+import android.annotation.Nullable;
import android.app.Activity;
import android.content.Intent;
+import android.graphics.Rect;
import android.os.Bundle;
-import android.view.LayoutInflater;
+import android.text.TextUtils;
+import android.util.Size;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
import android.view.View;
-import android.view.ViewGroup;
import com.android.settings.R;
+import com.android.settings.wifi.qrcode.QrCamera;
+import com.android.settings.wifi.qrcode.QrDecorateView;
-public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment {
+public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
+ SurfaceHolder.Callback,
+ QrCamera.ScannerCallback {
+ private QrCamera mCamera;
+ private SurfaceView mSurfaceView;
+ private QrDecorateView mDecorateView;
+
@Override
protected int getLayout() {
return R.layout.wifi_dpp_qrcode_scanner_fragment;
}
@Override
- public void onActivityCreated (Bundle savedInstanceState) {
- super.onActivityCreated (savedInstanceState);
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
setTitle(getString(R.string.wifi_dpp_add_device_to_network));
- String ssid = "";
- Intent intent = getActivity().getIntent();
- if (intent != null)
- ssid = intent.getStringExtra(WifiDppConfiguratorActivity.EXTRA_SSID);
- String description = getString(R.string.wifi_dpp_center_qr_code, ssid);
- setDescription(description);
+ WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
+ .getWifiNetworkConfig();
+ if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
+ throw new IllegalArgumentException("Invalid Wi-Fi network for configuring");
+ }
+ setDescription(getString(R.string.wifi_dpp_center_qr_code, wifiNetworkConfig.getSsid()));
hideRightButton();
setLeftButtonText(getString(android.R.string.cancel));
setLeftButtonOnClickListener((view) -> {
- getActivity().setResult(Activity.RESULT_CANCELED);
- getActivity().finish();});
+ getActivity().setResult(Activity.RESULT_CANCELED);
+ getActivity().finish();
+ });
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ mSurfaceView = (SurfaceView) view.findViewById(R.id.preview_view);
+ final SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
+ surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+ surfaceHolder.addCallback(this);
+
+ mDecorateView = (QrDecorateView) view.findViewById(R.id.decorate_view);
+ }
+
+ @Override
+ public void surfaceCreated(final SurfaceHolder holder) {
+ initCamera(holder);
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ destroyCamera();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ // Do nothing
+ }
+
+ @Override
+ public Size getViewSize() {
+ return new Size(mSurfaceView.getWidth(), mSurfaceView.getHeight());
+ }
+
+ @Override
+ public Rect getFramePosition(Size previewSize, int cameraOrientation) {
+ return new Rect(0, 0, previewSize.getHeight(), previewSize.getHeight());
+ }
+
+ @Override
+ public void handleSuccessfulResult(String qrCode) {
+ destroyCamera();
+ mDecorateView.setFocused(true);
+ // TODO(b/120243131): Add a network by Wi-Fi Network config shared via QR code.
+ }
+
+ @Override
+ public void handleCameraFailure() {
+ destroyCamera();
+ }
+
+ private void initCamera(SurfaceHolder holder) {
+ // Check if the camera has already created.
+ if (mCamera == null) {
+ mCamera = new QrCamera(getContext(), this);
+ mCamera.start(holder);
+ }
+ }
+
+ private void destroyCamera() {
+ if (mCamera != null) {
+ mCamera.stop();
+ mCamera = null;
+ }
}
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
new file mode 100644
index 0000000..70ef3a8
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import android.content.Intent;
+
+/**
+ * Here are the items shared by both WifiDppConfiguratorActivity & WifiDppEnrolleeActivity
+ */
+public class WifiDppUtils {
+ /** The data is from {@code com.android.settingslib.wifi.AccessPoint.securityToString} */
+ public static final String EXTRA_WIFI_SECURITY = "security";
+
+ /** The data corresponding to {@code WifiConfiguration} SSID */
+ public static final String EXTRA_WIFI_SSID = "ssid";
+
+ /** The data corresponding to {@code WifiConfiguration} preSharedKey */
+ public static final String EXTRA_WIFI_PRE_SHARED_KEY = "preSharedKey";
+
+ /** The data corresponding to {@code WifiConfiguration} hiddenSSID */
+ public static final String EXTRA_WIFI_HIDDEN_SSID = "hiddenSsid";
+
+ /**
+ * Acceptable QR code string may be a standard W-Fi DPP bootstrapping information or the Wi-Fi
+ * Network config format described in
+ * https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
+ *
+ * Wi-Fi Network config format example:
+ *
+ * WIFI:T:WPA;S:mynetwork;P:mypass;;
+ *
+ * parameter Example Description
+ * T WPA Authentication type; can be WEP or WPA, or 'nopass' for no password. Or,
+ * omit for no password.
+ * S mynetwork Network SSID. Required. Enclose in double quotes if it is an ASCII name,
+ * but could be interpreted as hex (i.e. "ABCD")
+ * P mypass Password, ignored if T is "nopass" (in which case it may be omitted).
+ * Enclose in double quotes if it is an ASCII name, but could be interpreted as
+ * hex (i.e. "ABCD")
+ * H true Optional. True if the network SSID is hidden.
+ */
+ public static final String EXTRA_QR_CODE = "qrCode";
+}
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
new file mode 100644
index 0000000..439de98
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import android.content.Intent;
+import android.text.TextUtils;
+
+/**
+ * Contains the Wi-Fi Network config parameters described in
+ * https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
+ *
+ * Checks below members of {@code WifiDppUtils} for more information.
+ * EXTRA_WIFI_SECURITY / EXTRA_WIFI_SSID / EXTRA_WIFI_PRE_SHARED_KEY / EXTRA_WIFI_HIDDEN_SSID /
+ * EXTRA_QR_CODE
+ */
+public class WifiNetworkConfig {
+ private String mSecurity;
+ private String mSsid;
+ private String mPreSharedKey;
+ private boolean mHiddenSsid;
+
+ private WifiNetworkConfig(String security, String ssid, String preSharedKey,
+ boolean hiddenSsid) {
+ mSecurity = security;
+ mSsid = ssid;
+ mPreSharedKey = preSharedKey;
+ mHiddenSsid = hiddenSsid;
+ }
+
+ public WifiNetworkConfig(WifiNetworkConfig config) {
+ mSecurity = new String(config.mSecurity);
+ mSsid = new String(config.mSsid);
+ mPreSharedKey = new String(config.mPreSharedKey);
+ mHiddenSsid = config.mHiddenSsid;
+ }
+
+ /**
+ * Wi-Fi DPP activities should implement this interface for fragments to retrieve the
+ * WifiNetworkConfig for configuration
+ */
+ public interface Retriever {
+ public WifiNetworkConfig getWifiNetworkConfig();
+ public boolean setWifiNetworkConfig(WifiNetworkConfig config);
+ }
+
+ /**
+ * Retrieve WifiNetworkConfig from below 2 intents
+ *
+ * android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR
+ * android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER
+ */
+ public static WifiNetworkConfig getValidConfigOrNull(Intent intent) {
+ String security = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SECURITY);
+ String ssid = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SSID);
+ String preSharedKey = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY);
+ boolean hiddenSsid = intent.getBooleanExtra(WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID, false);
+
+ if (!isValidConfig(security, ssid, hiddenSsid)) {
+ return null;
+ }
+
+ if (ssid == null) {
+ ssid = "";
+ }
+
+ return new WifiNetworkConfig(security, ssid, preSharedKey, hiddenSsid);
+ }
+
+ public static boolean isValidConfig(WifiNetworkConfig config) {
+ if (config == null) {
+ return false;
+ } else {
+ return isValidConfig(config.mSecurity, config.mSsid, config.mHiddenSsid);
+ }
+ }
+
+ public static boolean isValidConfig(String security, String ssid, boolean hiddenSsid) {
+ if (TextUtils.isEmpty(security)) {
+ return false;
+ }
+
+ if (!hiddenSsid && TextUtils.isEmpty(ssid)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public String getSecurity() {
+ return new String(mSecurity);
+ }
+
+ public String getSsid() {
+ return new String(mSsid);
+ }
+
+ public String getPreSharedKey() {
+ return new String(mPreSharedKey);
+ }
+
+ public boolean getHiddenSsid() {
+ return mHiddenSsid;
+ }
+}
diff --git a/src/com/android/settings/wifi/qrcode/QrCamera.java b/src/com/android/settings/wifi/qrcode/QrCamera.java
index c29236c..dc650b9 100644
--- a/src/com/android/settings/wifi/qrcode/QrCamera.java
+++ b/src/com/android/settings/wifi/qrcode/QrCamera.java
@@ -43,6 +43,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import androidx.annotation.VisibleForTesting;
@@ -85,14 +86,26 @@
mReader.setHints(HINTS);
}
- void start(SurfaceHolder surfaceHolder) {
+ /**
+ * The function start camera preview and capture pictures to decode QR code continuously in a
+ * background task.
+ *
+ * @param surfaceHolder the Surface to be used for live preview, must already contain a surface
+ * when this method is called.
+ */
+ public void start(SurfaceHolder surfaceHolder) {
if (mDecodeTask == null) {
mDecodeTask = new DecodingTask(surfaceHolder);
- mDecodeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ // Execute in the separate thread pool to prevent block other AsyncTask.
+ mDecodeTask.executeOnExecutor(Executors.newSingleThreadExecutor());
}
}
- void stop() {
+ /**
+ * The function stop camera preview and background decode task. Caller call this function when
+ * the surface is being destroyed.
+ */
+ public void stop() {
removeMessages(MSG_AUTO_FOCUS);
if (mDecodeTask != null) {
mDecodeTask.cancel(true);
@@ -104,7 +117,7 @@
}
/** The scanner which includes this QrCamera class should implement this */
- interface ScannerCallback {
+ public interface ScannerCallback {
/**
* The function used to handle the decoding result of the QR code.
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 479ffee..e105dfc 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -27,9 +27,7 @@
com.android.settings.bluetooth.BluetoothPairingDetail
com.android.settings.bluetooth.DevicePickerFragment
com.android.settings.datausage.AppDataUsage
-com.android.settings.datausage.AppDataUsageV2
com.android.settings.datausage.DataUsageList
-com.android.settings.datausage.DataUsageListV2
com.android.settings.datetime.timezone.TimeZoneSettings
com.android.settings.deviceinfo.PrivateVolumeSettings
com.android.settings.deviceinfo.PublicVolumeSettings
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index 73d2264..c5c552e 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -73,8 +73,16 @@
<item>fake_package/fake_service</item>
</string-array>
+ <!-- Settings intelligence interaction log intent action -->
+ <string name="config_settingsintelligence_log_action" translatable="false">
+ aaa.bbb.ccc
+ </string>
+
<!-- List of packages that should be whitelisted for slice uri access. Do not translate -->
<string-array name="slice_whitelist_package_names" translatable="false">
<item>com.android.settings.slice_whitelist_package</item>
</string-array>
+
+ <!-- Email address for the homepage contextual cards feedback -->
+ <string name="config_contextual_card_feedback_email" translatable="false">test@test.test</string>
</resources>
diff --git a/tests/robotests/res/values/themes.xml b/tests/robotests/res/values/themes.xml
index 7bfbe10..41ace18 100644
--- a/tests/robotests/res/values/themes.xml
+++ b/tests/robotests/res/values/themes.xml
@@ -15,6 +15,8 @@
<item name="colorAccent">#ffffff</item>
<item name="preferenceTheme">@style/PreferenceTheme</item>
<item name="android:windowLightStatusBar">true</item>
+ <!-- Define this color for material design -->
+ <item name="colorPrimaryVariant">@android:color/white</item>
</style>
<style name="ThemeOverlay.SwitchBar.Settings" parent="@android:style/ThemeOverlay.Material.ActionBar">
diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
index 2c98f70..aa41464 100644
--- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
@@ -28,9 +28,6 @@
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
-import android.os.Bundle;
-import android.provider.Settings.Global;
-import android.view.View;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@@ -38,16 +35,13 @@
import com.android.settings.core.OnActivityResultListener;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
@@ -71,29 +65,6 @@
}
@Test
- @Config(shadows = ShadowUtils.class)
- public void onCreate_deviceNotProvisioned_shouldDisableSearch() {
- Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 0);
- final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class)
- .create(Bundle.EMPTY)
- .get();
-
- assertThat(activity.findViewById(R.id.search_bar).getVisibility())
- .isEqualTo(View.INVISIBLE);
- }
-
- @Test
- @Config(shadows = ShadowUtils.class)
- public void onCreate_deviceProvisioned_shouldEnableSearch() {
- Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
- final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class)
- .create(Bundle.EMPTY)
- .get();
-
- assertThat(activity.findViewById(R.id.search_bar).getVisibility()).isEqualTo(View.VISIBLE);
- }
-
- @Test
public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash() {
when(mActivity.getSupportFragmentManager()).thenReturn(mFragmentManager);
doReturn(mContext.getContentResolver()).when(mActivity).getContentResolver();
@@ -101,7 +72,7 @@
doReturn(RuntimeEnvironment.application.getClassLoader()).when(mActivity).getClassLoader();
- mActivity.launchSettingFragment(null, true, mock(Intent.class));
+ mActivity.launchSettingFragment(null, mock(Intent.class));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java b/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
index 87eb6a6..114000c 100644
--- a/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
@@ -16,6 +16,8 @@
package com.android.settings.applications;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doNothing;
@@ -30,9 +32,8 @@
import android.widget.Button;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
+import com.android.settingslib.widget.ActionButtonsPreference;
import org.junit.Before;
import org.junit.Test;
@@ -46,7 +47,7 @@
@Mock
private AppStorageSizesController mSizesController;
- private ActionButtonPreference mButtonsPref;
+ private ActionButtonsPreference mButtonsPref;
private AppStorageSettings mSettings;
private Button mLeftButton;
private Button mRightButton;
@@ -58,7 +59,7 @@
mRightButton = new Button(RuntimeEnvironment.application);
mSettings = spy(new AppStorageSettings());
mSettings.mSizeController = mSizesController;
- mButtonsPref = ActionButtonPreferenceTest.createMock();
+ mButtonsPref = createMock();
mSettings.mButtonsPref = mButtonsPref;
when(mButtonsPref.setButton1OnClickListener(any(View.OnClickListener.class)))
@@ -103,5 +104,22 @@
verify(mSettings).handleClearDataClick();
verify(mSettings).handleClearCacheClick();
}
+
+ private ActionButtonsPreference createMock() {
+ final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+ when(pref.setButton1Text(anyInt())).thenReturn(pref);
+ when(pref.setButton1Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+ when(pref.setButton2Text(anyInt())).thenReturn(pref);
+ when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+ return pref;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
index 6ff0dba..3d3a05a 100644
--- a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java
@@ -51,7 +51,6 @@
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowPowerManager;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
@@ -93,6 +92,8 @@
private ApplicationsState.AppEntry mAppEntry;
@Mock
private ApplicationInfo mApplicationInfo;
+ @Mock
+ private PowerManager mPowerManager;
private Context mContext;
private RecentAppsPreferenceController mController;
@@ -104,6 +105,7 @@
doReturn(mUsageStatsManager).when(mContext).getSystemService(Context.USAGE_STATS_SERVICE);
doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
mController = new RecentAppsPreferenceController(mContext, mAppState, null);
when(mScreen.findPreference(anyString())).thenReturn(mCategory);
@@ -174,15 +176,15 @@
// stat1, stat2 are valid apps. stat3 is invalid.
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
- .thenReturn(mAppEntry);
+ .thenReturn(mAppEntry);
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
- .thenReturn(mAppEntry);
+ .thenReturn(mAppEntry);
when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId()))
- .thenReturn(null);
+ .thenReturn(null);
when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
- .thenReturn(new ResolveInfo());
+ .thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
- .thenReturn(stats);
+ .thenReturn(stats);
mAppEntry.info = mApplicationInfo;
mController.displayPreference(mScreen);
@@ -199,7 +201,7 @@
@Test
public void display_powerSaverMode_showNoRecents() {
- mContext.getSystemService(PowerManager.class).setPowerSaveMode(true);
+ when(mPowerManager.isPowerSaveMode()).thenReturn(true);
final List<UsageStats> stats = new ArrayList<>();
final UsageStats stat1 = new UsageStats();
@@ -251,7 +253,7 @@
// Only the regular app stat1 should have its intent resolve.
when(mPackageManager.resolveActivity(argThat(intentMatcher(stat1.mPackageName)), anyInt()))
- .thenReturn(new ResolveInfo());
+ .thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
@@ -311,13 +313,13 @@
// stat1, stat2 are not displayable
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
- .thenReturn(mock(ApplicationsState.AppEntry.class));
+ .thenReturn(mock(ApplicationsState.AppEntry.class));
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
- .thenReturn(mock(ApplicationsState.AppEntry.class));
+ .thenReturn(mock(ApplicationsState.AppEntry.class));
when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
- .thenReturn(new ResolveInfo());
+ .thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
- .thenReturn(stats);
+ .thenReturn(stats);
mController.displayPreference(mScreen);
@@ -336,11 +338,11 @@
stats.add(stat1);
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
- .thenReturn(mAppEntry);
+ .thenReturn(mAppEntry);
when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
- .thenReturn(new ResolveInfo());
+ .thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
- .thenReturn(stats);
+ .thenReturn(stats);
mAppEntry.info = mApplicationInfo;
mController.displayPreference(mScreen);
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
index 815c76b..f8dd11b 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
@@ -42,18 +43,18 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.UserManager;
+import android.view.View;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.ActionButtonsPreference;
import org.junit.Before;
import org.junit.Test;
@@ -99,9 +100,8 @@
@Mock
private PackageInfo mPackageInfo;
- private ActionButtonPreference mButtonPrefs;
-
private Intent mUninstallIntent;
+ private ActionButtonsPreference mButtonPrefs;
private AppButtonsPreferenceController mController;
@Before
@@ -127,7 +127,7 @@
mPackageInfo.packageName = PACKAGE_NAME;
mPackageInfo.applicationInfo = mAppInfo;
- mButtonPrefs = ActionButtonPreferenceTest.createMock();
+ mButtonPrefs = createMock();
mController.mButtonsPref = mButtonPrefs;
mController.mPackageInfo = mPackageInfo;
@@ -175,6 +175,22 @@
}
@Test
+ public void updateOpenButton_noLaunchIntent_buttonShouldBeDisable() {
+ mController.updateOpenButton();
+
+ verify(mButtonPrefs).setButton1Visible(false);
+ }
+
+ @Test
+ public void updateOpenButton_haveLaunchIntent_buttonShouldBeEnable() {
+ doReturn(new Intent()).when(mPackageManger).getLaunchIntentForPackage(anyString());
+
+ mController.updateOpenButton();
+
+ verify(mButtonPrefs).setButton1Visible(true);
+ }
+
+ @Test
public void updateUninstallButton_isSystemApp_handleAsDisableableButton() {
doReturn(false).when(mController).handleDisableable();
mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
@@ -182,7 +198,7 @@
mController.updateUninstallButton();
verify(mController).handleDisableable();
- verify(mButtonPrefs).setButton1Enabled(false);
+ verify(mButtonPrefs).setButton2Enabled(false);
}
@Test
@@ -220,7 +236,7 @@
mController.updateUninstallButton();
verify(mController).handleDisableable();
- verify(mButtonPrefs).setButton1Enabled(false);
+ verify(mButtonPrefs).setButton2Enabled(false);
}
@Test
@@ -229,7 +245,7 @@
mController.updateUninstallButton();
- verify(mButtonPrefs).setButton1Enabled(false);
+ verify(mButtonPrefs).setButton2Enabled(false);
}
@Test
@@ -239,7 +255,7 @@
mController.updateUninstallButton();
- verify(mButtonPrefs).setButton1Enabled(false);
+ verify(mButtonPrefs).setButton2Enabled(false);
}
@Test
@@ -248,7 +264,7 @@
mController.updateUninstallButton();
- verify(mButtonPrefs).setButton1Enabled(false);
+ verify(mButtonPrefs).setButton2Enabled(false);
}
@Test
@@ -258,7 +274,7 @@
mController.updateUninstallButton();
- verify(mButtonPrefs).setButton1Enabled(false);
+ verify(mButtonPrefs).setButton2Enabled(false);
}
@Test
@@ -308,7 +324,7 @@
final boolean controllable = mController.handleDisableable();
- verify(mButtonPrefs).setButton1Text(R.string.uninstall_text);
+ verify(mButtonPrefs).setButton2Text(R.string.uninstall_text);
assertThat(controllable).isFalse();
}
@@ -320,7 +336,7 @@
final boolean controllable = mController.handleDisableable();
- verify(mButtonPrefs).setButton1Text(R.string.uninstall_text);
+ verify(mButtonPrefs).setButton2Text(R.string.uninstall_text);
assertThat(controllable).isTrue();
}
@@ -332,7 +348,7 @@
final boolean controllable = mController.handleDisableable();
- verify(mButtonPrefs).setButton1Text(R.string.install_text);
+ verify(mButtonPrefs).setButton2Text(R.string.install_text);
assertThat(controllable).isTrue();
}
@@ -390,4 +406,15 @@
return SettingsEnums.PAGE_UNKNOWN;
}
}
+
+ private ActionButtonsPreference createMock() {
+ final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+ when(pref.setButton2Text(anyInt())).thenReturn(pref);
+ when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+ return pref;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
index 1adc678..fe70c7e 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -16,13 +16,12 @@
package com.android.settings.applications.appinfo;
-import static com.android.settings.core.FeatureFlags.DATA_USAGE_V2;
-
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -33,12 +32,7 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.net.ConnectivityManager;
-import android.net.INetworkStatsSession;
import android.os.Bundle;
-import android.util.FeatureFlagUtils;
-
-import androidx.loader.app.LoaderManager;
-import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.datausage.AppDataUsage;
@@ -49,9 +43,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.util.ReflectionHelpers;
+
+import androidx.loader.app.LoaderManager;
+import androidx.preference.Preference;
@RunWith(SettingsRobolectricTestRunner.class)
public class AppDataUsagePreferenceControllerTest {
@@ -68,7 +65,6 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application.getApplicationContext());
- FeatureFlagUtils.setEnabled(mContext, DATA_USAGE_V2, false);
mController = spy(new AppDataUsagePreferenceController(mContext, "test_key"));
mController.setParentFragment(mFragment);
}
@@ -90,8 +86,9 @@
}
@Test
- public void onResume_noSession_shouldNotRestartDataLoader() {
+ public void onResume_notAvailable_shouldNotRestartDataLoader() {
doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+ doReturn(BasePreferenceController.CONDITIONALLY_UNAVAILABLE).when(mController).getAvailabilityStatus();
mController.onResume();
@@ -100,26 +97,26 @@
}
@Test
- public void onResume_hasSession_shouldRestartDataLoader() {
+ public void onResume_isAvailable_shouldRestartDataLoader() {
final ConnectivityManager connectivityManager = mock(ConnectivityManager.class);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(connectivityManager);
when(connectivityManager.isNetworkSupported(anyInt())).thenReturn(true);
doReturn(mLoaderManager).when(mFragment).getLoaderManager();
- ReflectionHelpers.setField(mController, "mStatsSession", mock(INetworkStatsSession.class));
+ doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
final AppEntry appEntry = mock(AppEntry.class);
appEntry.info = new ApplicationInfo();
when(mFragment.getAppEntry()).thenReturn(appEntry);
mController.onResume();
- verify(mLoaderManager).restartLoader(
- eq(AppInfoDashboardFragment.LOADER_CHART_DATA), any(Bundle.class), eq(mController));
+ verify(mLoaderManager).restartLoader(eq(AppInfoDashboardFragment.LOADER_CHART_DATA),
+ nullable(Bundle.class), eq(mController));
}
@Test
public void onPause_shouldDestroyDataLoader() {
- ReflectionHelpers.setField(mController, "mStatsSession", mock(INetworkStatsSession.class));
+ doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
doReturn(mLoaderManager).when(mFragment).getLoaderManager();
mController.onPause();
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
deleted file mode 100644
index 708222e..0000000
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppDataUsagePreferenceControllerV2Test.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications.appinfo;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.net.ConnectivityManager;
-import android.os.Bundle;
-
-import com.android.settings.core.BasePreferenceController;
-import com.android.settings.core.FeatureFlags;
-import com.android.settings.datausage.AppDataUsageV2;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settingslib.applications.ApplicationsState.AppEntry;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import android.util.FeatureFlagUtils;
-
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-
-import androidx.loader.app.LoaderManager;
-import androidx.preference.Preference;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class AppDataUsagePreferenceControllerV2Test {
-
- @Mock
- private LoaderManager mLoaderManager;
- @Mock
- private AppInfoDashboardFragment mFragment;
-
- private Context mContext;
- private AppDataUsagePreferenceControllerV2 mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = spy(RuntimeEnvironment.application.getApplicationContext());
- mController = spy(new AppDataUsagePreferenceControllerV2(mContext, "test_key"));
- mController.setParentFragment(mFragment);
- FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, true);
- }
-
- @Test
- public void getAvailabilityStatus_bandwidthControlEnabled_shouldReturnAvailable() {
- doReturn(true).when(mController).isBandwidthControlEnabled();
-
- assertThat(mController.getAvailabilityStatus())
- .isEqualTo(BasePreferenceController.AVAILABLE);
- }
-
- @Test
- public void getAvailabilityStatus_bandwidthControlDisabled_shouldReturnDisabled() {
- doReturn(false).when(mController).isBandwidthControlEnabled();
-
- assertThat(mController.getAvailabilityStatus())
- .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
- }
-
- @Test
- public void onResume_notAvailable_shouldNotRestartDataLoader() {
- FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, false);
- doReturn(mLoaderManager).when(mFragment).getLoaderManager();
-
- mController.onResume();
-
- verify(mLoaderManager, never()).restartLoader(
- AppInfoDashboardFragment.LOADER_CHART_DATA, Bundle.EMPTY, mController);
- }
-
- @Test
- public void onResume_isAvailable_shouldRestartDataLoader() {
- final ConnectivityManager connectivityManager = mock(ConnectivityManager.class);
- when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
- .thenReturn(connectivityManager);
- when(connectivityManager.isNetworkSupported(anyInt())).thenReturn(true);
- doReturn(mLoaderManager).when(mFragment).getLoaderManager();
- doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
- final AppEntry appEntry = mock(AppEntry.class);
- appEntry.info = new ApplicationInfo();
- when(mFragment.getAppEntry()).thenReturn(appEntry);
-
- mController.onResume();
-
- verify(mLoaderManager).restartLoader(eq(AppInfoDashboardFragment.LOADER_CHART_DATA),
- nullable(Bundle.class), eq(mController));
- }
-
- @Test
- public void onPause_shouldDestroyDataLoader() {
- doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
- doReturn(mLoaderManager).when(mFragment).getLoaderManager();
-
- mController.onPause();
-
- verify(mLoaderManager).destroyLoader(AppInfoDashboardFragment.LOADER_CHART_DATA);
- }
-
- @Test
- public void getDetailFragmentClass_shouldReturnAppDataUsage() {
- assertThat(mController.getDetailFragmentClass()).isEqualTo(AppDataUsageV2.class);
- }
-
- @Test
- public void updateState_shouldUpdatePreferenceSummary() {
- final Preference preference = mock(Preference.class);
-
- mController.updateState(preference);
-
- verify(preference).setSummary(any());
- }
-}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java
index 094ec80..d8be01f 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsButtonsControllerTest.java
@@ -18,6 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
@@ -34,8 +36,7 @@
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowBluetoothDevice;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
+import com.android.settingslib.widget.ActionButtonsPreference;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -47,7 +48,7 @@
@Config(shadows = SettingsShadowBluetoothDevice.class)
public class BluetoothDetailsButtonsControllerTest extends BluetoothDetailsControllerTestBase {
private BluetoothDetailsButtonsController mController;
- private ActionButtonPreference mButtonsPref;
+ private ActionButtonsPreference mButtonsPref;
private Button mConnectButton;
private Button mForgetButton;
@@ -60,8 +61,9 @@
mConnectButton = buttons.findViewById(R.id.button2);
mForgetButton = buttons.findViewById(R.id.button1);
mController =
- new BluetoothDetailsButtonsController(mContext, mFragment, mCachedDevice, mLifecycle);
- mButtonsPref = ActionButtonPreferenceTest.createMock();
+ new BluetoothDetailsButtonsController(mContext, mFragment, mCachedDevice,
+ mLifecycle);
+ mButtonsPref = createMock();
when(mButtonsPref.getKey()).thenReturn(mController.getPreferenceKey());
when(mButtonsPref.setButton2OnClickListener(any(View.OnClickListener.class)))
.thenAnswer(invocation -> {
@@ -186,4 +188,21 @@
verify(mButtonsPref).setButton2Enabled(false);
}
+
+ private ActionButtonsPreference createMock() {
+ final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+ when(pref.setButton1Text(anyInt())).thenReturn(pref);
+ when(pref.setButton1Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+ when(pref.setButton2Text(anyInt())).thenReturn(pref);
+ when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+ return pref;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
index 01fa32f..333c706 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
@@ -19,6 +19,7 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.doNothing;
@@ -28,12 +29,14 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.net.NetworkPolicyManager;
import android.os.Bundle;
import android.util.ArraySet;
import android.view.View;
+import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@@ -45,6 +48,7 @@
import com.android.settingslib.AppItem;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.net.NetworkCycleDataForUid;
import org.junit.After;
import org.junit.Before;
@@ -57,6 +61,9 @@
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
public class AppDataUsageTest {
@@ -172,4 +179,49 @@
verify(restrictBackgroundPref).setDisabledByAdmin(any(EnforcedAdmin.class));
verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class));
}
+
+ @Test
+ public void bindData_noAppUsageData_shouldHideCycleSpinner() {
+ mFragment = spy(new AppDataUsage());
+ final SpinnerPreference cycle = mock(SpinnerPreference.class);
+ ReflectionHelpers.setField(mFragment, "mCycle", cycle);
+ final Preference preference = mock(Preference.class);
+ ReflectionHelpers.setField(mFragment, "mBackgroundUsage", preference);
+ ReflectionHelpers.setField(mFragment, "mForegroundUsage", preference);
+ ReflectionHelpers.setField(mFragment, "mTotalUsage", preference);
+ doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
+
+ mFragment.bindData(0 /* position */);
+
+ verify(cycle).setVisible(false);
+ }
+
+ @Test
+ public void bindData_hasAppUsageData_shouldShowCycleSpinnerAndUpdateUsageSummary() {
+ mFragment = spy(new AppDataUsage());
+ final Context context = RuntimeEnvironment.application;
+ doReturn(context).when(mFragment).getContext();
+ final long backgroundBytes = 1234L;
+ final long foregroundBytes = 5678L;
+ final List<NetworkCycleDataForUid> appUsage = new ArrayList<>();
+ appUsage.add(new NetworkCycleDataForUid.Builder()
+ .setBackgroundUsage(backgroundBytes).setForegroundUsage(foregroundBytes).build());
+ ReflectionHelpers.setField(mFragment, "mUsageData", appUsage);
+ final Preference backgroundPref = mock(Preference.class);
+ ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref);
+ final Preference foregroundPref = mock(Preference.class);
+ ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref);
+ final Preference totalPref = mock(Preference.class);
+ ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref);
+ final SpinnerPreference cycle = mock(SpinnerPreference.class);
+ ReflectionHelpers.setField(mFragment, "mCycle", cycle);
+
+ mFragment.bindData(0 /* position */);
+
+ verify(cycle).setVisible(true);
+ verify(totalPref).setSummary(
+ DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes));
+ verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
+ verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
deleted file mode 100644
index 8796a39..0000000
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
+++ /dev/null
@@ -1,227 +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.datausage;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.NetworkPolicyManager;
-import android.os.Bundle;
-import android.util.ArraySet;
-import android.view.View;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
-import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
-import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.net.NetworkCycleDataForUid;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
-public class AppDataUsageV2Test {
-
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private EntityHeaderController mHeaderController;
- @Mock
- private PackageManager mPackageManager;
-
- private AppDataUsageV2 mFragment;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- FakeFeatureFactory.setupForTest();
- }
-
- @After
- public void tearDown() {
- ShadowEntityHeaderController.reset();
- }
-
- @Test
- public void bindAppHeader_allWorkApps_shouldNotShowAppInfoLink() {
- ShadowEntityHeaderController.setUseMock(mHeaderController);
- when(mHeaderController.setRecyclerView(any(), any())).thenReturn(mHeaderController);
- when(mHeaderController.setUid(anyInt())).thenReturn(mHeaderController);
-
- mFragment = spy(new AppDataUsageV2());
-
- when(mFragment.getPreferenceManager())
- .thenReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS));
- doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
- ReflectionHelpers.setField(mFragment, "mAppItem", mock(AppItem.class));
-
- mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
-
- verify(mHeaderController).setHasAppInfoLink(false);
- }
-
- @Test
- public void bindAppHeader_workApp_shouldSetWorkAppUid() throws
- PackageManager.NameNotFoundException {
- final int fakeUserId = 100;
-
- mFragment = spy(new AppDataUsageV2());
- final ArraySet<String> packages = new ArraySet<>();
- packages.add("pkg");
- final AppItem appItem = new AppItem(123456789);
-
- ReflectionHelpers.setField(mFragment, "mPackageManager", mPackageManager);
- ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
- ReflectionHelpers.setField(mFragment, "mPackages", packages);
-
- when(mPackageManager.getPackageUidAsUser(anyString(), anyInt()))
- .thenReturn(fakeUserId);
-
- ShadowEntityHeaderController.setUseMock(mHeaderController);
- when(mHeaderController.setRecyclerView(any(), any())).thenReturn(mHeaderController);
- when(mHeaderController.setUid(fakeUserId)).thenReturn(mHeaderController);
- when(mHeaderController.setHasAppInfoLink(anyBoolean())).thenReturn(mHeaderController);
-
- when(mFragment.getPreferenceManager())
- .thenReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS));
- doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
-
- mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
-
- verify(mHeaderController).setHasAppInfoLink(true);
- verify(mHeaderController).setUid(fakeUserId);
- }
-
- @Test
- public void changePreference_backgroundData_shouldUpdateUI() {
- mFragment = spy(new AppDataUsageV2());
- final AppItem appItem = new AppItem(123456789);
- final RestrictedSwitchPreference pref = mock(RestrictedSwitchPreference.class);
- final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
- ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
- ReflectionHelpers.setField(mFragment, "mRestrictBackground", pref);
- ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend);
-
- doNothing().when(mFragment).updatePrefs();
-
- mFragment.onPreferenceChange(pref, true /* value */);
-
- verify(mFragment).updatePrefs();
- }
-
- @Test
- public void updatePrefs_restrictedByAdmin_shouldDisablePreference() {
- mFragment = spy(new AppDataUsageV2());
- final int testUid = 123123;
- final AppItem appItem = new AppItem(testUid);
- final RestrictedSwitchPreference restrictBackgroundPref
- = mock(RestrictedSwitchPreference.class);
- final RestrictedSwitchPreference unrestrictedDataPref
- = mock(RestrictedSwitchPreference.class);
- final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
- final NetworkPolicyManager networkPolicyManager = mock(NetworkPolicyManager.class);
- ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
- ReflectionHelpers.setField(mFragment, "mRestrictBackground", restrictBackgroundPref);
- ReflectionHelpers.setField(mFragment, "mUnrestrictedData", unrestrictedDataPref);
- ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend);
- ReflectionHelpers.setField(mFragment.services, "mPolicyManager", networkPolicyManager);
-
- ShadowRestrictedLockUtilsInternal.setRestricted(true);
- doReturn(NetworkPolicyManager.POLICY_NONE).when(networkPolicyManager)
- .getUidPolicy(testUid);
-
- mFragment.updatePrefs();
-
- verify(restrictBackgroundPref).setDisabledByAdmin(any(EnforcedAdmin.class));
- verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class));
- }
-
- @Test
- public void bindData_noAppUsageData_shouldHideCycleSpinner() {
- mFragment = spy(new AppDataUsageV2());
- final SpinnerPreference cycle = mock(SpinnerPreference.class);
- ReflectionHelpers.setField(mFragment, "mCycle", cycle);
- final Preference preference = mock(Preference.class);
- ReflectionHelpers.setField(mFragment, "mBackgroundUsage", preference);
- ReflectionHelpers.setField(mFragment, "mForegroundUsage", preference);
- ReflectionHelpers.setField(mFragment, "mTotalUsage", preference);
- doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
-
- mFragment.bindData(0 /* position */);
-
- verify(cycle).setVisible(false);
- }
-
- @Test
- public void bindData_hasAppUsageData_shouldShowCycleSpinnerAndUpdateUsageSummary() {
- mFragment = spy(new AppDataUsageV2());
- final Context context = RuntimeEnvironment.application;
- doReturn(context).when(mFragment).getContext();
- final long backgroundBytes = 1234L;
- final long foregroundBytes = 5678L;
- final List<NetworkCycleDataForUid> appUsage = new ArrayList<>();
- appUsage.add(new NetworkCycleDataForUid.Builder()
- .setBackgroundUsage(backgroundBytes).setForegroundUsage(foregroundBytes).build());
- ReflectionHelpers.setField(mFragment, "mUsageData", appUsage);
- final Preference backgroundPref = mock(Preference.class);
- ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref);
- final Preference foregroundPref = mock(Preference.class);
- ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref);
- final Preference totalPref = mock(Preference.class);
- ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref);
- final SpinnerPreference cycle = mock(SpinnerPreference.class);
- ReflectionHelpers.setField(mFragment, "mCycle", cycle);
-
- mFragment.bindData(0 /* position */);
-
- verify(cycle).setVisible(true);
- verify(totalPref).setSummary(
- DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes));
- verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
- verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
- }
-}
diff --git a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
index ce58ae2..af56029 100644
--- a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
@@ -18,17 +18,15 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.content.Context;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkStatsHistory.Entry;
import android.util.SparseIntArray;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.widget.UsageView;
+import com.android.settingslib.net.NetworkCycleChartData;
+import com.android.settingslib.net.NetworkCycleData;
import org.junit.Before;
import org.junit.Test;
@@ -37,14 +35,17 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(SettingsRobolectricTestRunner.class)
public class ChartDataUsagePreferenceTest {
- private static final long MILLIS_IN_ONE_HOUR = 60 * 60 * 1000;
- private static final long MILLIS_IN_ONE_DAY = 24 * MILLIS_IN_ONE_HOUR;
- private static final long TIMESTAMP_NOW = Integer.MAX_VALUE;
+ private static final long TIMESTAMP_START = 1521583200000L;
+ private static final long TIMESTAMP_END = 1521676800000L;
- private NetworkStatsHistory mNetworkStatsHistory;
+ private List<NetworkCycleData> mNetworkCycleData;
+ private NetworkCycleChartData mNetworkCycleChartData;
private Context mContext;
private ChartDataUsagePreference mPreference;
@@ -54,23 +55,17 @@
mContext = RuntimeEnvironment.application;
mPreference = new ChartDataUsagePreference(mContext, null);
- mNetworkStatsHistory = spy(new NetworkStatsHistory(MILLIS_IN_ONE_HOUR, 10));
- addTestNetworkEntries();
- mPreference.setNetworkStats(mNetworkStatsHistory);
+ createTestNetworkData();
+ mPreference.setNetworkCycleData(mNetworkCycleChartData);
}
@Test
- public void calcPoints_notStartOfData_shouldAddDataPointsOnly() {
- final long start = TIMESTAMP_NOW - 20 * MILLIS_IN_ONE_DAY;
- final long end = TIMESTAMP_NOW - 5 * MILLIS_IN_ONE_DAY;
- mPreference.setVisibleRange(start, end);
- when(mNetworkStatsHistory.getIndexAfter(start)).thenReturn(2);
- when(mNetworkStatsHistory.getIndexAfter(end)).thenReturn(7);
+ public void calcPoints_dataAvailableFromCycleStart_shouldAddDataPointsOnly() {
final UsageView usageView = mock(UsageView.class);
final ArgumentCaptor<SparseIntArray> pointsCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
- mPreference.calcPoints(usageView);
+ mPreference.calcPoints(usageView, mNetworkCycleData.subList(0, 5));
verify(usageView).addPath(pointsCaptor.capture());
SparseIntArray points = pointsCaptor.getValue();
@@ -79,17 +74,12 @@
}
@Test
- public void calcPoints_startOfData_shouldIndicateStartOfData() {
- final long start = TIMESTAMP_NOW - 20 * MILLIS_IN_ONE_DAY;
- final long end = TIMESTAMP_NOW - 5 * MILLIS_IN_ONE_DAY;
- mPreference.setVisibleRange(start, end);
- when(mNetworkStatsHistory.getIndexAfter(start)).thenReturn(0);
- when(mNetworkStatsHistory.getIndexAfter(end)).thenReturn(5);
+ public void calcPoints_dataNotAvailableAtCycleStart_shouldIndicateStartOfData() {
final UsageView usageView = mock(UsageView.class);
final ArgumentCaptor<SparseIntArray> pointsCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
- mPreference.calcPoints(usageView);
+ mPreference.calcPoints(usageView, mNetworkCycleData.subList(2, 7));
verify(usageView).addPath(pointsCaptor.capture());
SparseIntArray points = pointsCaptor.getValue();
@@ -98,35 +88,29 @@
assertThat(points.valueAt(1)).isEqualTo(-1);
}
- private void addTestNetworkEntries() {
- // create 10 arbitary network data
- mNetworkStatsHistory.setValues(0, createEntry(1521583200000L, 743823454L, 16574289L));
- mNetworkStatsHistory.setValues(1, createEntry(1521586800000L, 64396L, 160364L));
- mNetworkStatsHistory.setValues(2, createEntry(1521590400000L, 2832L, 5299L));
- mNetworkStatsHistory.setValues(3, createEntry(1521655200000L, 83849690L, 3558238L));
- mNetworkStatsHistory.setValues(4, createEntry(1521658800000L, 1883657L, 353330L));
- mNetworkStatsHistory.setValues(5, createEntry(1521662400000L, 705259L, 279065L));
- mNetworkStatsHistory.setValues(6, createEntry(1521666000000L, 216169L, 155302L));
- mNetworkStatsHistory.setValues(7, createEntry(1521669600000L, 6069175L, 427581L));
- mNetworkStatsHistory.setValues(8, createEntry(1521673200000L, 120389L, 110807L));
- mNetworkStatsHistory.setValues(9, createEntry(1521676800000L, 29947L, 73257L));
+ private void createTestNetworkData() {
+ mNetworkCycleData = new ArrayList<>();
+ // create 10 arbitrary network data
+ mNetworkCycleData.add(createNetworkCycleData(1521583200000L, 1521586800000L, 743823454L));
+ mNetworkCycleData.add(createNetworkCycleData(1521586800000L, 1521590400000L, 64396L));
+ mNetworkCycleData.add(createNetworkCycleData(1521590400000L, 1521655200000L, 2832L));
+ mNetworkCycleData.add(createNetworkCycleData(1521655200000L, 1521658800000L, 83849690L));
+ mNetworkCycleData.add(createNetworkCycleData(1521658800000L, 1521662400000L, 1883657L));
+ mNetworkCycleData.add(createNetworkCycleData(1521662400000L, 1521666000000L, 705259L));
+ mNetworkCycleData.add(createNetworkCycleData(1521666000000L, 1521669600000L, 216169L));
+ mNetworkCycleData.add(createNetworkCycleData(1521669600000L, 1521673200000L, 6069175L));
+ mNetworkCycleData.add(createNetworkCycleData(1521673200000L, 1521676800000L, 120389L));
+ mNetworkCycleData.add(createNetworkCycleData(1521676800000L, 1521678800000L, 29947L));
+
+ final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
+ builder.setUsageBuckets(mNetworkCycleData)
+ .setStartTime(TIMESTAMP_START)
+ .setEndTime(TIMESTAMP_END);
+ mNetworkCycleChartData = builder.build();
}
- /**
- * Create a network entry to be used to calculate the usage chart. In the calculation, we only
- * need bucketStart, total bytes (rx + tx), and bucketDuration (which is set when we create
- * the NetworkStatsHistory object). Other fields are ignored, so we don't initialize here.
- *
- * @param start the timestamp when this entry begins
- * @param rx the total number of received bytes
- * @param tx the total number of transmitted bytes
- * @return the network entry with the corresponding start time and data usage
- */
- private Entry createEntry(long start, long rx, long tx) {
- Entry entry = new Entry();
- entry.bucketStart = start;
- entry.rxBytes = rx;
- entry.txBytes = tx;
- return entry;
+ private NetworkCycleData createNetworkCycleData(long start, long end, long usage) {
+ return new NetworkCycleData.Builder()
+ .setStartTime(start).setEndTime(end).setTotalUsage(usage).build();
}
}
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
index acd00fd..7a10d70 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -26,13 +26,11 @@
import android.content.Context;
import android.content.Intent;
+import android.net.ConnectivityManager;
import android.net.NetworkTemplate;
import android.os.Bundle;
import android.provider.Settings;
-import androidx.fragment.app.FragmentActivity;
-import androidx.preference.PreferenceManager;
-
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.NetworkPolicyEditor;
@@ -45,6 +43,9 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.util.ReflectionHelpers;
+import androidx.fragment.app.FragmentActivity;
+import androidx.preference.PreferenceManager;
+
@RunWith(SettingsRobolectricTestRunner.class)
public class DataUsageListTest {
@@ -98,6 +99,18 @@
}
@Test
+ public void processArgument_shouldGetNetworkTypeFromArgument() {
+ final Bundle args = new Bundle();
+ args.putInt(DataUsageList.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_WIFI);
+ args.putInt(DataUsageList.EXTRA_SUB_ID, 3);
+ mDataUsageList.setArguments(args);
+
+ mDataUsageList.processArgument();
+
+ assertThat(mDataUsageList.mNetworkType).isEqualTo(ConnectivityManager.TYPE_WIFI);
+ }
+
+ @Test
public void processArgument_fromIntent_shouldGetTemplateFromIntent() {
final FragmentActivity activity = mock(FragmentActivity.class);
final Intent intent = new Intent();
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java
deleted file mode 100644
index f561a05..0000000
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListV2Test.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.datausage;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.provider.Settings;
-
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settingslib.NetworkPolicyEditor;
-import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.util.ReflectionHelpers;
-
-import androidx.fragment.app.FragmentActivity;
-import androidx.preference.PreferenceManager;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class DataUsageListV2Test {
-
- @Mock
- private CellDataPreference.DataStateListener mListener;
- @Mock
- private TemplatePreference.NetworkServices mNetworkServices;
- @Mock
- private Context mContext;
- private DataUsageListV2 mDataUsageList;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- FakeFeatureFactory.setupForTest();
- mNetworkServices.mPolicyEditor = mock(NetworkPolicyEditor.class);
- mDataUsageList = spy(DataUsageListV2.class);
-
- doReturn(mContext).when(mDataUsageList).getContext();
- ReflectionHelpers.setField(mDataUsageList, "mDataStateListener", mListener);
- ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices);
- }
-
- @Test
- public void resumePause_shouldListenUnlistenDataStateChange() {
- ReflectionHelpers.setField(
- mDataUsageList, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
- ReflectionHelpers.setField(
- mDataUsageList, "mPreferenceManager", mock(PreferenceManager.class));
-
- mDataUsageList.onResume();
-
- verify(mListener).setListener(true, mDataUsageList.mSubId, mContext);
-
- mDataUsageList.onPause();
-
- verify(mListener).setListener(false, mDataUsageList.mSubId, mContext);
- }
-
- @Test
- public void processArgument_shouldGetTemplateFromArgument() {
- final Bundle args = new Bundle();
- args.putParcelable(DataUsageListV2.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
- args.putInt(DataUsageListV2.EXTRA_SUB_ID, 3);
- mDataUsageList.setArguments(args);
-
- mDataUsageList.processArgument();
-
- assertThat(mDataUsageList.mTemplate).isNotNull();
- assertThat(mDataUsageList.mSubId).isEqualTo(3);
- }
-
- @Test
- public void processArgument_shouldGetNetworkTypeFromArgument() {
- final Bundle args = new Bundle();
- args.putInt(DataUsageListV2.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_WIFI);
- args.putInt(DataUsageListV2.EXTRA_SUB_ID, 3);
- mDataUsageList.setArguments(args);
-
- mDataUsageList.processArgument();
-
- assertThat(mDataUsageList.mNetworkType).isEqualTo(ConnectivityManager.TYPE_WIFI);
- }
-
- @Test
- public void processArgument_fromIntent_shouldGetTemplateFromIntent() {
- final FragmentActivity activity = mock(FragmentActivity.class);
- final Intent intent = new Intent();
- intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
- intent.putExtra(Settings.EXTRA_SUB_ID, 3);
- when(activity.getIntent()).thenReturn(intent);
- doReturn(activity).when(mDataUsageList).getActivity();
-
- mDataUsageList.processArgument();
-
- assertThat(mDataUsageList.mTemplate).isNotNull();
- assertThat(mDataUsageList.mSubId).isEqualTo(3);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
index 9a67df8..4bd584e 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
@@ -29,9 +29,7 @@
import android.net.ConnectivityManager;
import android.telephony.TelephonyManager;
import android.util.DataUnit;
-import android.util.FeatureFlagUtils;
-import com.android.settings.core.FeatureFlags;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
@@ -102,7 +100,6 @@
@Test
public void hasEthernet_shouldQueryEthernetSummaryForUser() throws Exception {
- FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DATA_USAGE_V2, true);
when(mManager.isNetworkSupported(anyInt())).thenReturn(true);
final String subscriber = "TestSub";
when(mTelephonyManager.getSubscriberId()).thenReturn(subscriber);
diff --git a/tests/robotests/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceControllerTest.java
new file mode 100644
index 0000000..8b9b14f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceControllerTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AllowBackgroundActivityStartsPreferenceControllerTest {
+
+ @Mock
+ private SwitchPreference mPreference;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+
+ private Context mContext;
+ private AllowBackgroundActivityStartsPreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new AllowBackgroundActivityStartsPreferenceController(mContext);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreference);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void onPreferenceChange_settingEnabled_allowBackgroundActivityStartsShouldBeOn() {
+ mController.onPreferenceChange(mPreference, true /* new value */);
+
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */);
+
+ assertThat(mode).isEqualTo(1);
+ }
+
+ @Test
+ public void onPreferenceChange_settingDisabled_allowBackgroundActivityStartsShouldBeOff() {
+ mController.onPreferenceChange(mPreference, false /* new value */);
+
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */);
+
+ assertThat(mode).isEqualTo(0);
+ }
+
+ @Test
+ public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 0);
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(false);
+ }
+
+ @Test
+ public void updateState_settingEnabled_preferenceShouldBeChecked() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1);
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(true);
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
+ mController.onDeveloperOptionsSwitchDisabled();
+
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */);
+
+ assertThat(mode).isEqualTo(0);
+ verify(mPreference).setChecked(false);
+ verify(mPreference).setEnabled(false);
+ }
+}
+
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java
index 983621c..a966417 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeOptionMenuControllerTest.java
@@ -64,6 +64,7 @@
MockitoAnnotations.initMocks(this);
when(mVolumeInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
+ when(mVolumeInfo.isMountedWritable()).thenReturn(true);
when(mPrimaryInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
when(mMenu.findItem(anyInt())).thenReturn(mMigrateMenuItem);
when(mMigrateMenuItem.getItemId()).thenReturn(100);
@@ -82,6 +83,7 @@
@Test
public void testMigrateDataIsNotVisibleNormally() {
when(mPm.getPrimaryStorageCurrentVolume()).thenReturn(mPrimaryInfo);
+ when(mPrimaryInfo.isMountedWritable()).thenReturn(true);
mController.onCreateOptionsMenu(mMenu, mMenuInflater);
mController.onPrepareOptionsMenu(mMenu);
@@ -100,6 +102,17 @@
}
@Test
+ public void testMigrateDataIsNotVisibleWhenExternalVolumeIsNotMounted() {
+ when(mPm.getPrimaryStorageCurrentVolume()).thenReturn(mVolumeInfo);
+ when(mVolumeInfo.isMountedWritable()).thenReturn(false);
+
+ mController.onCreateOptionsMenu(mMenu, mMenuInflater);
+ mController.onPrepareOptionsMenu(mMenu);
+
+ verify(mMigrateMenuItem).setVisible(false);
+ }
+
+ @Test
public void testMigrateDataGoesToMigrateWizard() {
when(mPm.getPrimaryStorageCurrentVolume()).thenReturn(mVolumeInfo);
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
index f1d03c7..f7a61c8 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
@@ -28,6 +28,7 @@
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.widget.PreferenceCategoryController;
import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.drawer.CategoryKey;
import org.junit.Before;
import org.junit.Test;
@@ -59,7 +60,7 @@
assertThat(mSettings.getMetricsCategory())
.isEqualTo(MetricsEvent.ENTERPRISE_PRIVACY_SETTINGS);
assertThat(mSettings.getLogTag()).isEqualTo("EnterprisePrivacySettings");
- assertThat(mSettings.getCategoryKey()).isNull();
+ assertThat(mSettings.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_ENTERPRISE_PRIVACY);
assertThat(mSettings.getPreferenceScreenResId())
.isEqualTo(R.xml.enterprise_privacy_settings);
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
index c09af2b..051ef39 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverButtonPreferenceControllerTest.java
@@ -21,6 +21,8 @@
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.PowerManager;
@@ -37,22 +39,20 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowPowerManager;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = ShadowPowerManager.class)
public class BatterySaverButtonPreferenceControllerTest {
private BatterySaverButtonPreferenceController mController;
private Context mContext;
private Button mButtonOn;
private Button mButtonOff;
- private PowerManager mPowerManager;
private TwoStateButtonPreference mPreference;
@Mock
+ private PowerManager mPowerManager;
+ @Mock
private PreferenceScreen mPreferenceScreen;
@Before
@@ -61,10 +61,11 @@
mContext = spy(RuntimeEnvironment.application);
mButtonOn = new Button(mContext);
mButtonOff = new Button(mContext);
- mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mPreference = spy(new TwoStateButtonPreference(mContext, null /* AttributeSet */));
ReflectionHelpers.setField(mPreference, "mButtonOn", mButtonOn);
ReflectionHelpers.setField(mPreference, "mButtonOff", mButtonOff);
+
+ doReturn(mPowerManager).when(mContext).getSystemService(Context.POWER_SERVICE);
doReturn(mPreference).when(mPreferenceScreen).findPreference(anyString());
mController = new BatterySaverButtonPreferenceController(mContext, "test_key");
@@ -73,7 +74,7 @@
@Test
public void updateState_lowPowerOn_preferenceIsChecked() {
- mPowerManager.setPowerSaveMode(true);
+ when(mPowerManager.isPowerSaveMode()).thenReturn(true);
mController.updateState(mPreference);
@@ -82,7 +83,7 @@
@Test
public void testUpdateState_lowPowerOff_preferenceIsUnchecked() {
- mPowerManager.setPowerSaveMode(false);
+ when(mPowerManager.isPowerSaveMode()).thenReturn(false);
mController.updateState(mPreference);
@@ -93,13 +94,13 @@
public void setChecked_on_setPowerSaveMode() {
mController.setChecked(true);
- assertThat(mPowerManager.isPowerSaveMode()).isTrue();
+ verify(mPowerManager).setPowerSaveMode(true);
}
@Test
public void setChecked_off_unsetPowerSaveMode() {
mController.setChecked(false);
- assertThat(mPowerManager.isPowerSaveMode()).isFalse();
+ verify(mPowerManager).setPowerSaveMode(false);
}
}
diff --git a/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java
index d8f800d..e892eb2 100644
--- a/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/GesturesSettingsPreferenceControllerTest.java
@@ -16,6 +16,8 @@
package com.android.settings.gestures;
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
@@ -81,7 +83,7 @@
});
ReflectionHelpers.setField(mController, "mGestureControllers", mControllers);
- assertThat(mController.isAvailable()).isTrue();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
new file mode 100644
index 0000000..08631f7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.homepage.contextualcards;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ContextualCardFeatureProviderImplTest {
+
+ private Context mContext;
+ private ContextualCardFeatureProviderImpl mImpl;
+
+ @Before
+ public void setUp() {
+ mContext = spy(RuntimeEnvironment.application);
+ mImpl = new ContextualCardFeatureProviderImpl();
+ }
+
+ @Test
+ public void sendBroadcast_emptyAction_notSendBroadcast() {
+ final Intent intent = new Intent();
+ mImpl.sendBroadcast(mContext, intent);
+
+ verify(mContext, never()).sendBroadcast(intent);
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void sendBroadcast_hasAction_sendBroadcast() {
+ final Intent intent = new Intent();
+ mImpl.sendBroadcast(mContext, intent);
+
+ verify(mContext).sendBroadcast(intent);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index e8cb674..4f50197 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -27,11 +27,9 @@
import android.content.Context;
import android.net.Uri;
-import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice;
-import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.wifi.WifiSlice;
import org.junit.Before;
import org.junit.Test;
@@ -153,7 +151,7 @@
cards.add(new ContextualCard.Builder()
.setName("test_wifi")
.setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(WifiSlice.WIFI_URI)
+ .setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI)
.build());
cards.add(new ContextualCard.Builder()
.setName("test_flashlight")
@@ -164,7 +162,7 @@
cards.add(new ContextualCard.Builder()
.setName("test_connected")
.setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(ConnectedDeviceSlice.CONNECTED_DEVICE_URI)
+ .setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI)
.build());
cards.add(new ContextualCard.Builder()
.setName("test_gesture")
@@ -175,7 +173,7 @@
cards.add(new ContextualCard.Builder()
.setName("test_battery")
.setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(BatterySlice.BATTERY_CARD_URI)
+ .setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
.build());
return cards;
}
@@ -208,7 +206,7 @@
cards.add(new ContextualCard.Builder()
.setName("test_battery")
.setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(BatterySlice.BATTERY_CARD_URI)
+ .setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
.build());
return cards;
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
index 8287672..64a7c9c 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
@@ -18,13 +18,12 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyMap;
-import static org.mockito.Mockito.doNothing;
-
import android.content.Context;
import android.net.Uri;
import android.util.ArrayMap;
+import com.android.settings.homepage.contextualcards.conditional.ConditionFooterContextualCard;
+import com.android.settings.homepage.contextualcards.conditional.ConditionHeaderContextualCard;
import com.android.settings.homepage.contextualcards.conditional.ConditionalContextualCard;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -70,7 +69,7 @@
}
@Test
- public void onContextualCardUpdated_emtpyMapWithExistingCards_shouldOnlyKeepConditionalCard() {
+ public void onContextualCardUpdated_emptyMapWithExistingCards_shouldOnlyKeepConditionalCard() {
mManager.mContextualCards.add(new ConditionalContextualCard.Builder().build());
mManager.mContextualCards.add(
buildContextualCard(TEST_SLICE_URI));
@@ -84,6 +83,31 @@
.isEqualTo(ContextualCard.CardType.CONDITIONAL);
}
+ @Test
+ public void onContextualCardUpdated_hasEmptyMap_shouldKeepConditionalHeaderCard() {
+ mManager.mContextualCards.add(new ConditionHeaderContextualCard.Builder().build());
+ mManager.setListener(mListener);
+
+ mManager.onContextualCardUpdated(new ArrayMap<>());
+
+ assertThat(mManager.mContextualCards).hasSize(1);
+ assertThat(mManager.mContextualCards.get(0).getCardType())
+ .isEqualTo(ContextualCard.CardType.CONDITIONAL_HEADER);
+ }
+
+ @Test
+ public void onContextualCardUpdated_hasEmptyMap_shouldKeepConditionalFooterCard() {
+ mManager.mContextualCards.add(new ConditionFooterContextualCard.Builder().build());
+ mManager.setListener(mListener);
+
+ mManager.onContextualCardUpdated(new ArrayMap<>());
+
+ assertThat(mManager.mContextualCards).hasSize(1);
+ assertThat(mManager.mContextualCards.get(0).getCardType())
+ .isEqualTo(ContextualCard.CardType.CONDITIONAL_FOOTER);
+ }
+
+
private ContextualCard buildContextualCard(String sliceUri) {
return new ContextualCard.Builder()
.setName("test_name")
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
index 6b1f8b1..4b0b085 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
@@ -23,15 +23,13 @@
import static org.mockito.Mockito.spy;
import android.app.slice.SliceManager;
-import android.content.ContentResolver;
import android.content.Context;
-import android.net.Uri;
import android.os.Bundle;
import com.android.settings.intelligence.ContextualCardProto.ContextualCard;
import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.wifi.WifiSlice;
import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
@@ -48,18 +46,11 @@
@Mock
private SliceManager mSliceManager;
- private ContentResolver mResolver;
- private Uri mUri;
private SettingsContextualCardProvider mProvider;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mResolver = RuntimeEnvironment.application.getContentResolver();
- mUri = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SettingsContextualCardProvider.CARD_AUTHORITY)
- .build();
mProvider = spy(Robolectric.setupContentProvider(SettingsContextualCardProvider.class));
final Context context = spy(RuntimeEnvironment.application);
doReturn(mSliceManager).when(context).getSystemService(SliceManager.class);
@@ -83,7 +74,7 @@
final ContextualCardList cards = mProvider.getContextualCards();
ContextualCard wifiCard = null;
for (ContextualCard card : cards.getCardList()) {
- if (card.getSliceUri().equals(WifiSlice.WIFI_URI.toString())) {
+ if (card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI.toString())) {
wifiCard = card;
}
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
index bb61c7d..25689e6 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
@@ -58,7 +58,7 @@
final ActivityController<Activity> activityController = Robolectric.buildActivity(
Activity.class);
mActivity = activityController.get();
- mActivity.setTheme(R.style.Theme_AppCompat);
+ mActivity.setTheme(R.style.Theme_Settings_Home);
activityController.create();
mRenderer = new ConditionContextualCardRenderer(mActivity, mControllerRendererPool);
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java
index d0b5a24..ee8a582 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionHeaderContextualCardRendererTest.java
@@ -60,7 +60,7 @@
final ActivityController<Activity> activityController = Robolectric.buildActivity(
Activity.class);
mActivity = activityController.get();
- mActivity.setTheme(R.style.Theme_AppCompat);
+ mActivity.setTheme(R.style.Theme_Settings_Home);
activityController.create();
mRenderer = new ConditionHeaderContextualCardRenderer(mActivity, mControllerRendererPool);
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java
index 2618e1b..c337df1 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java
@@ -59,7 +59,7 @@
final ActivityController<Activity> activityController = Robolectric.buildActivity(
Activity.class);
mActivity = activityController.get();
- mActivity.setTheme(R.style.Theme_AppCompat);
+ mActivity.setTheme(R.style.Theme_Settings_Home);
activityController.create();
mRenderer = new LegacySuggestionContextualCardRenderer(mActivity, mControllerRendererPool);
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
index 23da127..472d2ca 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
@@ -36,6 +36,7 @@
import com.android.settings.testutils.SliceTester;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -49,12 +50,17 @@
@RunWith(SettingsRobolectricTestRunner.class)
public class ConnectedDeviceSliceTest {
+ private static final String BLUETOOTH_SUMMARY = "BluetoothSummary";
+ private static final String BLUETOOTH_TITLE = "BluetoothTitle";
+
@Mock
private CachedBluetoothDevice mCachedBluetoothDevice;
- private List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>();
- private Context mContext;
+ private List<CachedBluetoothDevice> mBluetoothConnectedDeviceList;
private ConnectedDeviceSlice mConnectedDeviceSlice;
+ private Context mContext;
+ private IconCompat mIcon;
+ private PendingIntent mDetailIntent;
@Before
public void setUp() {
@@ -65,35 +71,63 @@
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
mConnectedDeviceSlice = spy(new ConnectedDeviceSlice(mContext));
+
+ // Mock the icon and detail intent of Bluetooth.
+ mIcon = IconCompat.createWithResource(mContext, R.drawable.ic_homepage_connected_device);
+ mDetailIntent = PendingIntent.getActivity(mContext, 0, new Intent("test action"), 0);
+ doReturn(mIcon).when(mConnectedDeviceSlice).getConnectedDeviceIcon(any());
+ doReturn(mDetailIntent).when(mConnectedDeviceSlice).getBluetoothDetailIntent(any());
+
+ // Initial Bluetooth connected device list.
+ mBluetoothConnectedDeviceList = new ArrayList<>();
+ }
+
+ @After
+ public void tearDown() {
+ if (!mBluetoothConnectedDeviceList.isEmpty()) {
+ mBluetoothConnectedDeviceList.clear();
+ }
}
@Test
- public void getSlice_hasConnectedDevices_shouldBeCorrectSliceContent() {
- final String title = "BluetoothTitle";
- final String summary = "BluetoothSummary";
- final IconCompat icon = IconCompat.createWithResource(mContext,
- R.drawable.ic_homepage_connected_device);
- final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
- new Intent("test action"), 0);
- doReturn(title).when(mCachedBluetoothDevice).getName();
- doReturn(summary).when(mCachedBluetoothDevice).getConnectionSummary();
- mCachedDevices.add(mCachedBluetoothDevice);
- doReturn(mCachedDevices).when(mConnectedDeviceSlice).getBluetoothConnectedDevices();
- doReturn(icon).when(mConnectedDeviceSlice).getConnectedDeviceIcon(any());
- doReturn(pendingIntent).when(mConnectedDeviceSlice).getBluetoothDetailIntent(any());
+ public void getSlice_hasConnectedDevices_shouldHaveCorrectTitle() {
+ mockBluetoothDeviceList();
+ doReturn(mBluetoothConnectedDeviceList).when(
+ mConnectedDeviceSlice).getBluetoothConnectedDevices();
+
final Slice slice = mConnectedDeviceSlice.getSlice();
final List<SliceItem> sliceItems = slice.getItems();
- SliceTester.assertTitle(sliceItems, title);
+ SliceTester.assertTitle(sliceItems,
+ mContext.getString(R.string.bluetooth_connected_devices));
}
@Test
- public void getSlice_hasNoConnectedDevices_shouldReturnCorrectHeader() {
- final List<CachedBluetoothDevice> connectedBluetoothList = new ArrayList<>();
- doReturn(connectedBluetoothList).when(mConnectedDeviceSlice).getBluetoothConnectedDevices();
+ public void getSlice_hasConnectedDevices_shouldHaveCorrectContent() {
+ mockBluetoothDeviceList();
+ doReturn(mBluetoothConnectedDeviceList).when(
+ mConnectedDeviceSlice).getBluetoothConnectedDevices();
+
+ final Slice slice = mConnectedDeviceSlice.getSlice();
+
+ final List<SliceItem> sliceItems = slice.getItems();
+ SliceTester.assertTitle(sliceItems, BLUETOOTH_TITLE);
+ }
+
+ @Test
+ public void getSlice_noConnectedDevices_shouldHaveCorrectTitle() {
+ doReturn(mBluetoothConnectedDeviceList).when(
+ mConnectedDeviceSlice).getBluetoothConnectedDevices();
+
final Slice slice = mConnectedDeviceSlice.getSlice();
final List<SliceItem> sliceItems = slice.getItems();
SliceTester.assertTitle(sliceItems, mContext.getString(R.string.no_connected_devices));
}
+
+ private void mockBluetoothDeviceList() {
+ doReturn(BLUETOOTH_TITLE).when(mCachedBluetoothDevice).getName();
+ doReturn(BLUETOOTH_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary();
+ mBluetoothConnectedDeviceList.add(mCachedBluetoothDevice);
+ }
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
index 0be55d9..9787aee 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
@@ -16,6 +16,8 @@
package com.android.settings.homepage.contextualcards.slices;
+import static android.app.slice.Slice.HINT_ERROR;
+
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
@@ -66,7 +68,7 @@
@Test
@Config(shadows = ShadowPrivateStorageInfo.class)
- public void getSlice_hasLowStorage_shouldBeCorrectSliceContent() {
+ public void getSlice_lowStorage_shouldHaveStorageFreeTitle() {
ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
final Slice slice = mLowStorageSlice.getSlice();
@@ -77,12 +79,33 @@
@Test
@Config(shadows = ShadowPrivateStorageInfo.class)
- public void getSlice_hasNoLowStorage_shouldBeNull() {
+ public void getSlice_lowStorage_shouldNotHaveErrorHint() {
+ ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
+
+ final Slice slice = mLowStorageSlice.getSlice();
+
+ assertThat(slice.hasHint(HINT_ERROR)).isFalse();
+ }
+
+ @Test
+ @Config(shadows = ShadowPrivateStorageInfo.class)
+ public void getSlice_storageFree_shouldHaveStorageSettingsTitle() {
ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(100L, 100L));
final Slice slice = mLowStorageSlice.getSlice();
- assertThat(slice).isNull();
+ final List<SliceItem> sliceItems = slice.getItems();
+ SliceTester.assertTitle(sliceItems, mContext.getString(R.string.storage_settings));
+ }
+
+ @Test
+ @Config(shadows = ShadowPrivateStorageInfo.class)
+ public void getSlice_storageFree_shouldHaveErrorHint() {
+ ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(100L, 100L));
+
+ final Slice slice = mLowStorageSlice.getSlice();
+
+ assertThat(slice.hasHint(HINT_ERROR)).isTrue();
}
@Implements(PrivateStorageInfo.class)
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
index 362e1f5..af3b2e8 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
@@ -18,6 +18,11 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -27,14 +32,22 @@
import com.android.settings.homepage.contextualcards.CardContentProvider;
import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
import com.android.settings.homepage.contextualcards.ContextualCard;
+import com.android.settings.homepage.contextualcards.ContextualCardFeedbackDialog;
+import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
+import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowActivity;
import org.robolectric.shadows.ShadowContentResolver;
+import org.robolectric.shadows.androidx.fragment.FragmentController;
@RunWith(SettingsRobolectricTestRunner.class)
public class SliceContextualCardControllerTest {
@@ -46,27 +59,27 @@
private CardContentProvider mProvider;
private ContentResolver mResolver;
private SliceContextualCardController mController;
+ private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mProvider = Robolectric.setupContentProvider(CardContentProvider.class);
ShadowContentResolver.registerProviderInternal(CardContentProvider.CARD_AUTHORITY,
mProvider);
mResolver = mContext.getContentResolver();
- mController = new SliceContextualCardController(mContext);
+ mController = spy(new SliceContextualCardController(mContext));
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
}
@Test
public void onDismissed_cardShouldBeMarkedAsDismissed() {
final Uri providerUri = CardContentProvider.URI;
- final ContextualCard card = new ContextualCard.Builder()
- .setName(TEST_CARD_NAME)
- .setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(Uri.parse(TEST_SLICE_URI))
- .build();
mResolver.insert(providerUri, generateOneRow());
+ doNothing().when(mController).showFeedbackDialog(any(ContextualCard.class));
+ final ContextualCard card = getTestSliceCard();
mController.onDismissed(card);
final String[] columns = {CardDatabaseHelper.CardColumns.CARD_DISMISSED};
@@ -78,6 +91,34 @@
cr.close();
assertThat(qryDismissed).isEqualTo(1);
+ verify(mFeatureFactory.mContextualCardFeatureProvider).logContextualCardDismiss(
+ mContext, card);
+ }
+
+ @Test
+ public void onDismissed_noFeedbackEmail_shouldNotShowFeedbackDialog() {
+ mResolver.insert(CardContentProvider.URI, generateOneRow());
+ final ContextualCardsFragment fragment =
+ FragmentController.of(new ContextualCardsFragment()).create().get();
+ final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity());
+
+ mController.onDismissed(getTestSliceCard());
+
+ assertThat(shadowActivity.getNextStartedActivity()).isNull();
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void onDismissed_hasFeedbackEmail_shouldShowFeedbackDialog() {
+ mResolver.insert(CardContentProvider.URI, generateOneRow());
+ final ContextualCardsFragment fragment =
+ FragmentController.of(new ContextualCardsFragment()).create().get();
+ final ShadowActivity shadowActivity = Shadows.shadowOf(fragment.getActivity());
+
+ mController.onDismissed(getTestSliceCard());
+
+ assertThat(shadowActivity.getNextStartedActivity().getComponent().getClassName())
+ .isEqualTo(ContextualCardFeedbackDialog.class.getName());
}
private ContentValues generateOneRow() {
@@ -93,4 +134,12 @@
return values;
}
+
+ private ContextualCard getTestSliceCard() {
+ return new ContextualCard.Builder()
+ .setName(TEST_CARD_NAME)
+ .setCardType(ContextualCard.CardType.SLICE)
+ .setSliceUri(Uri.parse(TEST_SLICE_URI))
+ .build();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
index abfddbb..13a2bc5 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
@@ -66,7 +66,7 @@
final ActivityController<Activity> activityController = Robolectric.buildActivity(
Activity.class);
mActivity = activityController.get();
- mActivity.setTheme(R.style.Theme_AppCompat);
+ mActivity.setTheme(R.style.Theme_Settings_Home);
activityController.create();
mLifecycleOwner = new ContextualCardsFragment();
mRenderer = new SliceContextualCardRenderer(mActivity, mLifecycleOwner,
diff --git a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
index d260a97..5269dd7 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
@@ -44,6 +44,7 @@
import com.android.ims.ImsManager;
import com.android.settings.R;
import com.android.settings.slices.CustomSliceManager;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SlicesFeatureProvider;
@@ -107,7 +108,7 @@
mEnhanced4gLteSliceHelper.setDefaultVoiceSubId(-1);
final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice(
- Enhanced4gLteSliceHelper.SLICE_URI);
+ CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
assertThat(slice).isNull();
}
@@ -117,7 +118,7 @@
when(mMockImsManager.isVolteEnabledByPlatform()).thenReturn(false);
final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice(
- Enhanced4gLteSliceHelper.SLICE_URI);
+ CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
assertThat(slice).isNull();
@@ -132,7 +133,7 @@
when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null);
final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice(
- Enhanced4gLteSliceHelper.SLICE_URI);
+ CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
testEnhanced4gLteSettingsToggleSlice(slice);
@@ -148,7 +149,7 @@
when(mSlicesFeatureProvider.getNewEnhanced4gLteSliceHelper(mContext))
.thenReturn(mEnhanced4gLteSliceHelper);
- final Slice slice = mProvider.onBindSlice(Enhanced4gLteSliceHelper.SLICE_URI);
+ final Slice slice = mProvider.onBindSlice(CustomSliceRegistry.ENHANCED_4G_SLICE_URI);
assertThat(mEnhanced4gLteSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
testEnhanced4gLteSettingsToggleSlice(slice);
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
index ec50e2b..3eae266 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
@@ -16,13 +16,17 @@
package com.android.settings.notification;
-import static junit.framework.Assert.assertEquals;
-
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+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 android.app.AutomaticZenRule;
-import android.app.NotificationManager;
import android.content.Context;
import android.provider.Settings;
@@ -31,161 +35,122 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.internal.util.reflection.FieldSetter;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
-import java.util.Arrays;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModeAutomaticRulesPreferenceControllerTest {
- private static final String GENERIC_RULE_NAME = "test";
- private static final String DEFAULT_ID_1 = "DEFAULT_1";
- private static final String DEFAULT_ID_2 = "DEFAULT_2";
-
private ZenModeAutomaticRulesPreferenceController mController;
- private final List<String> mDefaultIds = Arrays.asList(DEFAULT_ID_1, DEFAULT_ID_2);
-
@Mock
private ZenModeBackend mBackend;
@Mock
- private NotificationManager mNotificationManager;
- @Mock
private PreferenceCategory mockPref;
@Mock
- private NotificationManager.Policy mPolicy;
- @Mock
private PreferenceScreen mPreferenceScreen;
-
+ @Mock
+ private ZenRulePreference mZenRulePreference;
private Context mContext;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- ShadowApplication shadowApplication = ShadowApplication.getInstance();
- shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
-
mContext = RuntimeEnvironment.application;
- when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
- mController = new ZenModeAutomaticRulesPreferenceController(mContext, mock(Fragment.class),
- mock(Lifecycle.class));
-
+ mController = spy(new ZenModeAutomaticRulesPreferenceController(mContext, mock(Fragment.class),
+ null));
ReflectionHelpers.setField(mController, "mBackend", mBackend);
- ReflectionHelpers.setField(mController, "mDefaultRuleIds", mDefaultIds);
-
when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
mockPref);
mController.displayPreference(mPreferenceScreen);
+ doReturn(mZenRulePreference).when(mController).createZenRulePreference(any());
}
@Test
- public void updateState_checkRuleOrderingDescending() {
- final int NUM_RULES = 4;
- when(mNotificationManager.getAutomaticZenRules()).thenReturn(
- mockAutoZenRulesDecreasingCreationTime(NUM_RULES));
+ public void testUpdateState_clearsPreferencesWhenAddingNewPreferences() {
+ final int NUM_RULES = 3;
+ Map<String, AutomaticZenRule> rMap = new HashMap<>();
- Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
- assertEquals(NUM_RULES, rules.length);
+ String ruleId1 = "test1_id";
+ String ruleId2 = "test2_id";
+ String ruleId3 = "test3_id";
- // check ordering, most recent should be at the bottom/end (ie higher creation time)
- for (int i = 0; i < NUM_RULES; i++) {
- assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i].getKey());
- }
+ AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+ AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
+ AutomaticZenRule autoRule3 = new AutomaticZenRule("test_rule_3", null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 30);
+
+ rMap.put(ruleId1, autoRule1);
+ rMap.put(ruleId2, autoRule2);
+ rMap.put(ruleId3, autoRule3);
+
+ // should add 3 new preferences to mockPref
+ mockGetAutomaticZenRules(NUM_RULES, rMap);
+ mController.updateState(mockPref);
+ verify(mockPref, times(1)).removeAll();
+ verify(mockPref, times(NUM_RULES)).addPreference(any());
}
@Test
- public void updateState_checkRuleOrderingAscending() {
- final int NUM_RULES = 4;
- when(mNotificationManager.getAutomaticZenRules()).thenReturn(
- mockAutoZenRulesAscendingCreationTime(NUM_RULES));
+ public void testUpdateState_clearsPreferencesWhenRemovingPreferences(){
+ final int NUM_RULES = 2;
+ Map<String, AutomaticZenRule> rMap = new HashMap<>();
- Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
- assertEquals(NUM_RULES, rules.length);
+ String ruleId1 = "test1_id";
+ String ruleId2 = "test2_id";
- // check ordering, most recent should be at the bottom/end (ie higher creation time)
- for (int i = 0; i < NUM_RULES; i++) {
- assertEquals(GENERIC_RULE_NAME + i, rules[i].getKey());
- }
+ AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+ AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
+
+ rMap.put(ruleId1, autoRule1);
+ rMap.put(ruleId2, autoRule2);
+
+ // update state should re-add all preferences since a preference was deleted
+ when(mockPref.getPreferenceCount()).thenReturn(NUM_RULES + 2);
+ mockGetAutomaticZenRules(NUM_RULES, rMap);
+ mController.updateState(mockPref);
+ verify(mockPref, times(1)).removeAll();
+ verify(mockPref, times(NUM_RULES)).addPreference(any());
}
@Test
- public void updateState_checkRuleOrderingDescending_withDefaultRules() {
- final int NUM_RULES = 4;
+ public void testUpdateState_updateEnableState() throws NoSuchFieldException {
+ final int NUM_RULES = 1;
+ Map<String, AutomaticZenRule> rMap = new HashMap<>();
+ String testId = "test1_id";
+ AutomaticZenRule rule = new AutomaticZenRule("rule_name", null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
+ rMap.put(testId, rule);
- Map<String, AutomaticZenRule> ruleMap = mockAutoZenRulesDecreasingCreationTime(NUM_RULES);
- ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_1_NAME", null,
- null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
- ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
- null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
- when(mNotificationManager.getAutomaticZenRules()).thenReturn(ruleMap);
+ when(mockPref.getPreferenceCount()).thenReturn(NUM_RULES);
+ when(mockPref.getPreference(anyInt())).thenReturn(mZenRulePreference);
- Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
- assertEquals(NUM_RULES + 2, rules.length);
-
- assertEquals(rules[0].getKey(), DEFAULT_ID_1);
- assertEquals(rules[1].getKey(), DEFAULT_ID_2);
- // NON-DEFAULT RULES check ordering, most recent at the bottom/end
- for (int i = 0; i < NUM_RULES; i++) {
- assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i + 2].getKey());
- }
+ // update state should NOT re-add all the preferences, should only update enable state
+ rule.setEnabled(false);
+ rMap.put(testId, rule);
+ mockGetAutomaticZenRules(NUM_RULES, rMap);
+ FieldSetter.setField(mZenRulePreference, ZenRulePreference.class.getDeclaredField("mId"), testId);
+ mController.updateState(mockPref);
+ verify(mZenRulePreference, times(1)).setChecked(false);
+ verify(mController, never()).reloadAllRules(any());
}
- @Test
- public void updateState_checkRuleOrderingMix() {
- final int NUM_RULES = 4;
- // map with creation times: 0, 2, 4, 6
- Map<String,AutomaticZenRule> rMap = mockAutoZenRulesAscendingCreationTime(NUM_RULES);
-
- final String insertedRule1 = "insertedRule1";
- rMap.put(insertedRule1, new AutomaticZenRule(insertedRule1, null, null,
- Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 5));
-
- final String insertedRule2 = "insertedRule2";
- rMap.put(insertedRule2, new AutomaticZenRule(insertedRule2, null, null,
- Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 3));
-
- // rule map with rule creation times, 0, 2, 4, 6, 5, 3
- // sort should create ordering based on creation times: 0, 2, 3, 4, 5, 6
- when(mNotificationManager.getAutomaticZenRules()).thenReturn(rMap);
-
- Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
- assertEquals(NUM_RULES + 2, rules.length); // inserted 2 rules
-
- // check ordering of inserted rules
- assertEquals(insertedRule1, rules[4].getKey());
- assertEquals(insertedRule2, rules[2].getKey());
- }
-
- private Map<String, AutomaticZenRule> mockAutoZenRulesAscendingCreationTime(int numRules) {
- Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
-
- for (int i = 0; i < numRules; i++) {
- ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
- null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, i * 2));
- }
-
- return ruleMap;
- }
-
- private Map<String, AutomaticZenRule> mockAutoZenRulesDecreasingCreationTime(int numRules) {
- Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
-
- for (int i = 0; i < numRules; i++) {
- ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
- null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, numRules - i));
- }
-
- return ruleMap;
+ private void mockGetAutomaticZenRules(int numRules, Map<String, AutomaticZenRule> rules) {
+ Map.Entry<String, AutomaticZenRule>[] arr = new Map.Entry[numRules];
+ rules.entrySet().toArray(arr);
+ when(mBackend.getAutomaticZenRules()).thenReturn(arr);
}
}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
new file mode 100644
index 0000000..94a3c01
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
@@ -0,0 +1,108 @@
+package com.android.settings.notification;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.app.AutomaticZenRule;
+import android.provider.Settings;
+import android.service.notification.ZenModeConfig;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ZenModeBackendTest {
+
+ private static final String GENERIC_RULE_NAME = "test";
+ private static final String DEFAULT_ID_1 = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
+ private static final String DEFAULT_ID_2 = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
+
+ @Test
+ public void updateState_checkRuleOrderingDescending() {
+ final int NUM_RULES = 4;
+ Map.Entry<String, AutomaticZenRule>[] rules = populateAutoZenRulesDescendingCreationTime(
+ NUM_RULES, false);
+ Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR);
+
+ // check ordering, most recent should be at the end
+ for (int i = 0; i < NUM_RULES; i++) {
+ assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i].getKey());
+ }
+ }
+
+ @Test
+ public void updateState_checkRuleOrderingAscending() {
+ final int NUM_RULES = 4;
+ Map.Entry<String, AutomaticZenRule>[] rules = populateAutoZenRulesAscendingCreationTime(
+ NUM_RULES, false);
+ Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR);
+
+ // check ordering, most recent should be at the end
+ for (int i = 0; i < NUM_RULES; i++) {
+ assertEquals(GENERIC_RULE_NAME + i, rules[i].getKey());
+ }
+ }
+
+ @Test
+ public void updateState_checkRuleOrderingDescending_withDefaultRules() {
+ final int NUM_RULES = 4;
+
+ Map.Entry<String, AutomaticZenRule>[] rules = populateAutoZenRulesDescendingCreationTime(NUM_RULES,
+ true);
+ Arrays.sort(rules, ZenModeBackend.RULE_COMPARATOR);
+
+ assertEquals(rules[0].getKey(), DEFAULT_ID_1);
+ assertEquals(rules[1].getKey(), DEFAULT_ID_2);
+ // NON-DEFAULT RULES check ordering, most recent at the bottom/end
+ for (int i = 0; i < NUM_RULES; i++) {
+ assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i + 2].getKey());
+ }
+ }
+
+ private Map.Entry<String, AutomaticZenRule>[] populateAutoZenRulesAscendingCreationTime(
+ int numRules, boolean addDefaultRules) {
+ Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
+
+ for (int i = 0; i < numRules; i++) {
+ ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, i * 2));
+ }
+
+ if (addDefaultRules) {
+ ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
+ ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
+ }
+
+ Map.Entry<String, AutomaticZenRule>[] toReturn = new Map.Entry[ruleMap.size()];
+ ruleMap.entrySet().toArray(toReturn);
+ return toReturn;
+ }
+
+ private Map.Entry<String, AutomaticZenRule>[] populateAutoZenRulesDescendingCreationTime(
+ int numRules, boolean addDefaultRules) {
+ Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
+
+ for (int i = 0; i < numRules; i++) {
+ ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, numRules - i));
+ }
+
+ if (addDefaultRules) {
+ ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
+ ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null,
+ null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
+ }
+
+ Map.Entry<String, AutomaticZenRule>[] toReturn = new Map.Entry[ruleMap.size()];
+ ruleMap.entrySet().toArray(toReturn);
+ return toReturn;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
index c1634fb..ca9f942 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
@@ -126,7 +126,7 @@
}
@Test
- public void app_manualRule_setFooterTitle() {
+ public void testDefaultNotifPolicy_app_manualRule_setFooterTitle() {
Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
injectManualRuleFromApp();
mController.updateState(mockPref);
@@ -137,7 +137,7 @@
}
@Test
- public void time_manualRule_setFooterTitle() {
+ public void testDefaultNotifPolicy_time_manualRule_setFooterTitle() {
Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
String placeholder = "placeholder";
injectManualRuleWithTimeCountdown(1000, placeholder);
@@ -148,7 +148,7 @@
}
@Test
- public void forever_manualRule_setFooterTitle() {
+ public void testDefaultNotifPolicy_forever_manualRule_setFooterTitle() {
Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
injectManualRuleWithIndefiniteEnd();
mController.updateState(mockPref);
@@ -158,7 +158,7 @@
}
@Test
- public void automaticRule_noManualRule_setFooterTitle() {
+ public void testDefaultNotifPolicy_automaticRule_noManualRule_setFooterTitle() {
Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
// no manual rule
ReflectionHelpers.setField(mZenModeConfig, MANUAL_RULE_FIELD, null);
@@ -174,7 +174,7 @@
}
@Test
- public void manualRuleEndsLast_hasAutomaticRule_setFooterTitle() {
+ public void testDefaultNotifPolicy_manualRuleEndsLast_hasAutomaticRule_setFooterTitle() {
Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
// manual rule that ends after automatic rule ends
injectManualRuleWithIndefiniteEnd();
@@ -190,7 +190,7 @@
}
@Test
- public void automaticRuleEndsLast_hasManualRule_setFooterTitle() {
+ public void testDefaultNotifPolicy_automaticRuleEndsLast_hasManualRule_setFooterTitle() {
Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
// manual rule that ends before automatic rule ends
injectManualRuleWithTimeCountdown(1000, "");
@@ -208,14 +208,15 @@
}
@Test
- public void multipleAutomaticRules_appAutoRuleautomaticRuleApp_setFooterTitle() {
+ public void testDefaultNotifPolicy_multipleAutomaticRules_autoRuleApp_setFooterTitle() {
Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
// automatic rule that ends after manual rule ends
ZenRule rule1 = injectNewAutomaticRule(TEST_RULE_NAME + "1", false, false);
when(mConfigWrapper.parseAutomaticRuleEndTime(rule1.conditionId)).thenReturn(10000L);
- ZenRule rule2 = injectNewAutomaticRule(TEST_RULE_NAME + "2", true, true);
+ // automatic rule that is an app
+ injectNewAutomaticRule(TEST_RULE_NAME + "2", true, true);
ZenRule rule3 = injectNewAutomaticRule(TEST_RULE_NAME + "3", true, false);
when(mConfigWrapper.parseAutomaticRuleEndTime(rule3.conditionId)).thenReturn(9000L);
@@ -229,7 +230,7 @@
}
@Test
- public void multipleAutomaticRules_setFooterTitle() {
+ public void testDefaultNotifPolicy_multipleAutomaticRules_setFooterTitle() {
Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
// automatic rule that ends after manual rule ends
diff --git a/tests/robotests/src/com/android/settings/panel/FakePanelContent.java b/tests/robotests/src/com/android/settings/panel/FakePanelContent.java
new file mode 100644
index 0000000..60f0d5d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/FakePanelContent.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.panel;
+
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
+
+import android.content.Intent;
+import android.net.Uri;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Fake PanelContent for testing.
+ */
+public class FakePanelContent implements PanelContent {
+
+ public static final String FAKE_KEY = "fake_key";
+
+ public static final CharSequence TITLE = "title";
+
+ public static final List<Uri> SLICE_URIS = Arrays.asList(
+ WIFI_SLICE_URI
+ );
+
+ public static final Intent INTENT = new Intent();
+
+ @Override
+ public CharSequence getTitle() {
+ return TITLE;
+ }
+
+ @Override
+ public List<Uri> getSlices() {
+ return SLICE_URIS;
+ }
+
+ @Override
+ public Intent getSeeMoreIntent() {
+ return INTENT;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/panel/FakeSettingsPanelActivity.java b/tests/robotests/src/com/android/settings/panel/FakeSettingsPanelActivity.java
new file mode 100644
index 0000000..afd0bec
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/FakeSettingsPanelActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.panel;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+public class FakeSettingsPanelActivity extends SettingsPanelActivity {
+ @Override
+ public ComponentName getCallingActivity() {
+ return new ComponentName("fake-package", "fake-class");
+ }
+
+ @Override
+ public Intent getIntent() {
+ final Intent intent = new Intent();
+ intent.putExtra(SettingsPanelActivity.EXTRA_PANEL_TYPE, FakePanelContent.FAKE_KEY);
+ return intent;
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java b/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java
index 3e210f5..aae85ab 100644
--- a/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java
+++ b/tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java
@@ -21,8 +21,8 @@
import android.net.Uri;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.wifi.WifiSlice;
import org.junit.Before;
import org.junit.Test;
@@ -46,7 +46,12 @@
public void getSlices_containsNecessarySlices() {
final List<Uri> uris = mPanel.getSlices();
- assertThat(uris).containsExactly(WifiSlice.WIFI_URI,
- InternetConnectivityPanel.AIRPLANE_URI);
+ assertThat(uris).containsExactly(CustomSliceRegistry.WIFI_SLICE_URI,
+ CustomSliceRegistry.AIRPLANE_URI);
+ }
+
+ @Test
+ public void getSeeMoreIntent_notNull() {
+ assertThat(mPanel.getSeeMoreIntent()).isNotNull();
}
}
diff --git a/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java b/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
new file mode 100644
index 0000000..cf344d2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.settings.panel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+
+import com.android.settings.R;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class PanelFragmentTest {
+
+ private Context mContext;
+ private PanelFragment mPanelFragment;
+ private FakeFeatureFactory mFakeFeatureFactory;
+ private PanelFeatureProvider mPanelFeatureProvider;
+ private FakePanelContent mFakePanelContent;
+
+ private final String FAKE_EXTRA = "fake_extra";
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+
+ mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
+ mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+ mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
+ mFakePanelContent = new FakePanelContent();
+ doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
+
+ ActivityController<FakeSettingsPanelActivity> activityController =
+ Robolectric.buildActivity(FakeSettingsPanelActivity.class);
+ activityController.setup();
+
+ mPanelFragment =
+ spy((PanelFragment)
+ activityController
+ .get()
+ .getSupportFragmentManager()
+ .findFragmentById(R.id.main_content));
+ }
+
+ @Test
+ public void onCreateView_adapterGetsDataset() {
+ final Bundle bundle = new Bundle();
+ bundle.putString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT, FAKE_EXTRA);
+ doReturn(bundle).when(mPanelFragment).getArguments();
+ mPanelFragment.onCreateView(LayoutInflater.from(mContext),
+ new LinearLayout(mContext), null);
+ PanelSlicesAdapter adapter = mPanelFragment.mAdapter;
+
+ assertThat(adapter.getData()).containsAllIn(mFakePanelContent.getSlices());
+ }
+
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
new file mode 100644
index 0000000..02a7d0a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.panel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.settings.R;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+
+import org.junit.Test;
+
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class PanelSlicesAdapterTest {
+
+ private Context mContext;
+ private PanelFragment mPanelFragment;
+ private FakePanelContent mFakePanelContent;
+ private FakeFeatureFactory mFakeFeatureFactory;
+ private PanelFeatureProvider mPanelFeatureProvider;
+
+ private PanelSlicesAdapter mAdapter;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+
+ mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
+ mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+ mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
+ mFakePanelContent = new FakePanelContent();
+ doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
+
+ ActivityController<FakeSettingsPanelActivity> activityController =
+ Robolectric.buildActivity(FakeSettingsPanelActivity.class);
+ activityController.setup();
+
+ mPanelFragment =
+ spy((PanelFragment)
+ activityController
+ .get()
+ .getSupportFragmentManager()
+ .findFragmentById(R.id.main_content));
+
+ mAdapter = new PanelSlicesAdapter(mPanelFragment, mFakePanelContent.getSlices());
+ }
+
+ @Test
+ public void onCreateViewHolder_returnsSliceRowViewHolder() {
+ final ViewGroup view = new FrameLayout(mContext);
+ final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
+ mAdapter.onCreateViewHolder(view, 0);
+
+ assertThat(viewHolder.sliceView).isNotNull();
+ }
+
+ @Test
+ public void onBindViewHolder_bindsSlice() {
+ final int position = 0;
+ final ViewGroup view = new FrameLayout(mContext);
+ final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
+ mAdapter.onCreateViewHolder(view, 0 /* view type*/);
+
+ mAdapter.onBindViewHolder(viewHolder, position);
+
+ assertThat(viewHolder.sliceLiveData).isNotNull();
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
new file mode 100644
index 0000000..21019d3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.panel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class VolumePanelTest {
+
+ private VolumePanel mPanel;
+
+ @Before
+ public void setUp() {
+ mPanel = VolumePanel.create(RuntimeEnvironment.application);
+ }
+
+ @Test
+ public void getSlices_containsNecessarySlices() {
+ final List<Uri> uris = mPanel.getSlices();
+
+ assertThat(uris).containsExactly(
+ CustomSliceRegistry.VOLUME_CALL_URI,
+ CustomSliceRegistry.VOLUME_MEDIA_URI,
+ CustomSliceRegistry.VOLUME_RINGER_URI,
+ CustomSliceRegistry.VOLUME_ALARM_URI);
+ }
+
+ @Test
+ public void getSeeMoreIntent_notNull() {
+ assertThat(mPanel.getSeeMoreIntent()).isNotNull();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
index b0e4025..37fd888 100644
--- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
@@ -53,6 +53,8 @@
mActivity = Robolectric.setupActivity(Activity.class);
mProvider = new SearchFeatureProviderImpl();
mPackageManager = Shadows.shadowOf(mActivity.getPackageManager());
+ Settings.Global.putInt(mActivity.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
}
@Test
@@ -82,7 +84,7 @@
@Test
@Config(shadows = ShadowUtils.class)
- public void initSearchToolbar_NotHaveResolvedInfo_shouldNotStartActivity() {
+ public void initSearchToolbar_noResolvedInfo_shouldNotStartActivity() {
final Toolbar toolbar = new Toolbar(mActivity);
// This ensures navigationView is created.
toolbar.setNavigationContentDescription("test");
@@ -90,9 +92,21 @@
toolbar.performClick();
- final Intent launchIntent = Shadows.shadowOf(mActivity).getNextStartedActivity();
+ assertThat(Shadows.shadowOf(mActivity).getNextStartedActivity()).isNull();
+ }
- assertThat(launchIntent).isNull();
+ @Test
+ public void initSearchToolbar_deviceNotProvisioned_shouldNotCreateSearchBar() {
+ final Toolbar toolbar = new Toolbar(mActivity);
+ // This ensures navigationView is created.
+ toolbar.setNavigationContentDescription("test");
+
+ Settings.Global.putInt(mActivity.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 0);
+
+ toolbar.performClick();
+
+ assertThat(Shadows.shadowOf(mActivity).getNextStartedActivity()).isNull();
}
@Test(expected = IllegalArgumentException.class)
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index 3c2cbdb..8e3c1c8 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -48,10 +48,6 @@
import androidx.slice.widget.SliceLiveData;
import com.android.settings.R;
-import com.android.settings.bluetooth.BluetoothSliceBuilder;
-import com.android.settings.flashlight.FlashlightSliceBuilder;
-import com.android.settings.location.LocationSliceBuilder;
-import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.testutils.DatabaseTestUtils;
import com.android.settings.testutils.FakeToggleController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -113,14 +109,14 @@
private SliceManager mManager;
private static final List<Uri> SPECIAL_CASE_PLATFORM_URIS = Arrays.asList(
- WifiSlice.WIFI_URI,
- BluetoothSliceBuilder.BLUETOOTH_URI,
- LocationSliceBuilder.LOCATION_URI
+ CustomSliceRegistry.WIFI_SLICE_URI,
+ CustomSliceRegistry.BLUETOOTH_URI,
+ CustomSliceRegistry.LOCATION_SLICE_URI
);
private static final List<Uri> SPECIAL_CASE_OEM_URIS = Arrays.asList(
- ZenModeSliceBuilder.ZEN_MODE_URI,
- FlashlightSliceBuilder.FLASHLIGHT_URI
+ CustomSliceRegistry.ZEN_MODE_SLICE_URI,
+ CustomSliceRegistry.FLASHLIGHT_SLICE_URI
);
@Before
@@ -472,9 +468,9 @@
@Test
public void bindSlice_wifiSlice_returnsWifiSlice() {
- final Slice wifiSlice = mProvider.onBindSlice(WifiSlice.WIFI_URI);
+ final Slice wifiSlice = mProvider.onBindSlice(CustomSliceRegistry.WIFI_SLICE_URI);
- assertThat(wifiSlice.getUri()).isEqualTo(WifiSlice.WIFI_URI);
+ assertThat(wifiSlice.getUri()).isEqualTo(CustomSliceRegistry.WIFI_SLICE_URI);
}
@Test
@@ -482,9 +478,10 @@
Settings.Secure.putInt(
mContext.getContentResolver(), Settings.Secure.FLASHLIGHT_AVAILABLE, 1);
- final Slice flashlightSlice = mProvider.onBindSlice(FlashlightSliceBuilder.FLASHLIGHT_URI);
+ final Slice flashlightSlice = mProvider.onBindSlice(
+ CustomSliceRegistry.FLASHLIGHT_SLICE_URI);
- assertThat(flashlightSlice.getUri()).isEqualTo(FlashlightSliceBuilder.FLASHLIGHT_URI);
+ assertThat(flashlightSlice.getUri()).isEqualTo(CustomSliceRegistry.FLASHLIGHT_SLICE_URI);
}
@Test
@@ -526,22 +523,22 @@
@Test
public void onSlicePinned_backgroundWorker_started() {
- mProvider.onSlicePinned(WifiSlice.WIFI_URI);
+ mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
verify(ShadowWifiScanWorker.getWifiTracker()).onStart();
}
@Test
public void onSlicePinned_backgroundWorker_stopped() {
- mProvider.onSlicePinned(WifiSlice.WIFI_URI);
- mProvider.onSliceUnpinned(WifiSlice.WIFI_URI);
+ mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
+ mProvider.onSliceUnpinned(CustomSliceRegistry.WIFI_SLICE_URI);
verify(ShadowWifiScanWorker.getWifiTracker()).onStop();
}
@Test
public void shutdown_backgroundWorker_closed() {
- mProvider.onSlicePinned(WifiSlice.WIFI_URI);
+ mProvider.onSlicePinned(CustomSliceRegistry.WIFI_SLICE_URI);
mProvider.shutdown();
verify(ShadowWifiScanWorker.getWifiTracker()).onDestroy();
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 2e2104b..f9937f4 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -218,6 +218,19 @@
}
@Test
+ public void getDynamicSummary_allowDynamicSummary_nullSummary_returnsNull() {
+ final SliceData data = getDummyData(true /*isDynamicSummaryAllowed*/);
+ final FakePreferenceController controller = spy(
+ new FakePreferenceController(mContext, KEY));
+ final String controllerSummary = null;
+ doReturn(controllerSummary).when(controller).getSummary();
+
+ final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data);
+
+ assertThat(summary).isNull();
+ }
+
+ @Test
public void getDynamicSummary_returnsScreenTitle() {
final SliceData data = getDummyData();
final FakePreferenceController controller = new FakePreferenceController(mContext, KEY);
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index e14ef1f..bb475f3 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -28,6 +28,7 @@
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.gestures.AssistGestureFeatureProvider;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.localepicker.LocaleFeatureProvider;
import com.android.settings.overlay.DockUpdaterFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
@@ -62,8 +63,9 @@
public final UserFeatureProvider userFeatureProvider;
public final AssistGestureFeatureProvider assistGestureFeatureProvider;
public final AccountFeatureProvider mAccountFeatureProvider;
- public final PanelFeatureProvider mPanelFeatureProvider;
+ public final ContextualCardFeatureProvider mContextualCardFeatureProvider;
+ public PanelFeatureProvider panelFeatureProvider;
public SlicesFeatureProvider slicesFeatureProvider;
public SearchFeatureProvider searchFeatureProvider;
@@ -104,7 +106,8 @@
assistGestureFeatureProvider = mock(AssistGestureFeatureProvider.class);
slicesFeatureProvider = mock(SlicesFeatureProvider.class);
mAccountFeatureProvider = mock(AccountFeatureProvider.class);
- mPanelFeatureProvider = mock(PanelFeatureProvider.class);
+ mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class);
+ panelFeatureProvider = mock(PanelFeatureProvider.class);
}
@Override
@@ -189,6 +192,10 @@
@Override
public PanelFeatureProvider getPanelFeatureProvider() {
- return mPanelFeatureProvider;
+ return panelFeatureProvider;
+ }
+
+ public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
+ return mContextualCardFeatureProvider;
}
}
diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
index 9417e9c..74914f4 100644
--- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
+++ b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
@@ -84,6 +84,8 @@
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SearchWidget/res/")), null));
paths.add(new ResourcePath(null,
+ Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/ActionButtonsPreference/res")), null));
+ paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SettingsLayoutPreference/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/core/res/res")), null));
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index be4199d..26eeb71 100644
--- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -110,8 +110,6 @@
final SliceAction mainToggleAction = toggles.get(0);
- final IconCompat expectedToggleIcon = IconCompat.createWithResource(context,
- sliceData.getIconResource());
assertThat(mainToggleAction.getIcon()).isNull();
// Check intent in Toggle Action
diff --git a/tests/robotests/src/com/android/settings/widget/ActionButtonPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/ActionButtonPreferenceTest.java
deleted file mode 100644
index 34a9872..0000000
--- a/tests/robotests/src/com/android/settings/widget/ActionButtonPreferenceTest.java
+++ /dev/null
@@ -1,283 +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.widget;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-import android.widget.Button;
-
-import androidx.preference.PreferenceViewHolder;
-
-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.robolectric.RuntimeEnvironment;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class ActionButtonPreferenceTest {
-
- private Context mContext;
- private View mRootView;
- private ActionButtonPreference mPref;
- private PreferenceViewHolder mHolder;
-
- @Before
- public void setUp() {
- mContext = RuntimeEnvironment.application;
- mRootView = View.inflate(mContext, R.layout.settings_action_buttons, null /* parent */);
- mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
- mPref = new ActionButtonPreference(mContext);
- }
-
- @Test
- public void onBindViewHolder_setTitle_shouldShowButtonByDefault() {
- mPref.setButton1Text(R.string.settings_label);
- mPref.setButton2Text(R.string.settings_label);
- mPref.setButton3Text(R.string.settings_label);
- mPref.setButton4Text(R.string.settings_label);
-
- mPref.onBindViewHolder(mHolder);
-
- assertThat(mRootView.findViewById(R.id.button1).getVisibility())
- .isEqualTo(View.VISIBLE);
- assertThat(mRootView.findViewById(R.id.button2).getVisibility())
- .isEqualTo(View.VISIBLE);
- assertThat(mRootView.findViewById(R.id.button3).getVisibility())
- .isEqualTo(View.VISIBLE);
- assertThat(mRootView.findViewById(R.id.button4).getVisibility())
- .isEqualTo(View.VISIBLE);
- }
-
- @Test
- public void onBindViewHolder_setIcon_shouldShowButtonByDefault() {
- mPref.setButton1Icon(R.drawable.ic_settings);
- mPref.setButton2Icon(R.drawable.ic_settings);
- mPref.setButton3Icon(R.drawable.ic_settings);
- mPref.setButton4Icon(R.drawable.ic_settings);
-
- mPref.onBindViewHolder(mHolder);
-
- assertThat(mRootView.findViewById(R.id.button1).getVisibility())
- .isEqualTo(View.VISIBLE);
- assertThat(mRootView.findViewById(R.id.button2).getVisibility())
- .isEqualTo(View.VISIBLE);
- assertThat(mRootView.findViewById(R.id.button3).getVisibility())
- .isEqualTo(View.VISIBLE);
- assertThat(mRootView.findViewById(R.id.button4).getVisibility())
- .isEqualTo(View.VISIBLE);
- }
-
- @Test
- public void onBindViewHolder_notSetTitleOrIcon_shouldNotShowButtonByDefault() {
- mPref.onBindViewHolder(mHolder);
-
- assertThat(mRootView.findViewById(R.id.button1).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button2).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button3).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button4).getVisibility())
- .isEqualTo(View.GONE);
- }
-
- @Test
- public void onBindViewHolder_setVisibleIsGoneAndSetTitle_shouldNotShowButton() {
- mPref.setButton1Text(R.string.settings_label).setButton1Visible(false);
- mPref.setButton2Text(R.string.settings_label).setButton2Visible(false);
- mPref.setButton3Text(R.string.settings_label).setButton3Visible(false);
- mPref.setButton4Text(R.string.settings_label).setButton4Visible(false);
-
- mPref.onBindViewHolder(mHolder);
-
- assertThat(mRootView.findViewById(R.id.button1).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button2).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button3).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button4).getVisibility())
- .isEqualTo(View.GONE);
- }
-
- @Test
- public void onBindViewHolder_setVisibleIsGoneAndSetIcon_shouldNotShowButton() {
- mPref.setButton1Icon(R.drawable.ic_settings).setButton1Visible(false);
- mPref.setButton2Icon(R.drawable.ic_settings).setButton2Visible(false);
- mPref.setButton3Icon(R.drawable.ic_settings).setButton3Visible(false);
- mPref.setButton4Icon(R.drawable.ic_settings).setButton4Visible(false);
-
- mPref.onBindViewHolder(mHolder);
-
- assertThat(mRootView.findViewById(R.id.button1).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button2).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button3).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button4).getVisibility())
- .isEqualTo(View.GONE);
- }
-
- @Test
- public void onBindViewHolder_setVisibility_shouldUpdateButtonVisibility() {
- mPref.setButton1Text(R.string.settings_label).setButton1Visible(false);
- mPref.setButton2Text(R.string.settings_label).setButton2Visible(false);
- mPref.setButton3Text(R.string.settings_label).setButton3Visible(false);
- mPref.setButton4Text(R.string.settings_label).setButton4Visible(false);
-
- mPref.onBindViewHolder(mHolder);
-
- assertThat(mRootView.findViewById(R.id.button1).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button2).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button3).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mRootView.findViewById(R.id.button4).getVisibility())
- .isEqualTo(View.GONE);
-
- mPref.setButton1Visible(true);
- mPref.setButton2Visible(true);
- mPref.setButton3Visible(true);
- mPref.setButton4Visible(true);
-
- mPref.onBindViewHolder(mHolder);
-
- assertThat(mRootView.findViewById(R.id.button1).getVisibility())
- .isEqualTo(View.VISIBLE);
- assertThat(mRootView.findViewById(R.id.button2).getVisibility())
- .isEqualTo(View.VISIBLE);
- assertThat(mRootView.findViewById(R.id.button3).getVisibility())
- .isEqualTo(View.VISIBLE);
- assertThat(mRootView.findViewById(R.id.button4).getVisibility())
- .isEqualTo(View.VISIBLE);
- }
-
- @Test
- public void onBindViewHolder_setEnabled_shouldEnableButton() {
- mPref.setButton1Enabled(true);
- mPref.setButton2Enabled(false);
- mPref.setButton3Enabled(true);
- mPref.setButton4Enabled(false);
-
- mPref.onBindViewHolder(mHolder);
-
- assertThat(mRootView.findViewById(R.id.button1).isEnabled()).isTrue();
- assertThat(mRootView.findViewById(R.id.button2).isEnabled()).isFalse();
- assertThat(mRootView.findViewById(R.id.button3).isEnabled()).isTrue();
- assertThat(mRootView.findViewById(R.id.button4).isEnabled()).isFalse();
- }
-
- @Test
- public void onBindViewHolder_setText_shouldShowSameText() {
- mPref.setButton1Text(R.string.settings_label);
- mPref.setButton2Text(R.string.settings_label);
- mPref.setButton3Text(R.string.settings_label);
- mPref.setButton4Text(R.string.settings_label);
-
- mPref.onBindViewHolder(mHolder);
-
- assertThat(((Button) mRootView.findViewById(R.id.button1)).getText())
- .isEqualTo(mContext.getText(R.string.settings_label));
- assertThat(((Button) mRootView.findViewById(R.id.button2)).getText())
- .isEqualTo(mContext.getText(R.string.settings_label));
- assertThat(((Button) mRootView.findViewById(R.id.button3)).getText())
- .isEqualTo(mContext.getText(R.string.settings_label));
- assertThat(((Button) mRootView.findViewById(R.id.button4)).getText())
- .isEqualTo(mContext.getText(R.string.settings_label));
- }
-
- @Test
- public void onBindViewHolder_setButtonIcon_iconMustDisplayAboveText() {
- mPref.setButton1Text(R.string.settings_label);
- mPref.setButton1Icon(R.drawable.ic_settings);
-
- mPref.onBindViewHolder(mHolder);
- final Drawable[] drawablesAroundText =
- ((Button) mRootView.findViewById(R.id.button1))
- .getCompoundDrawables();
-
- assertThat(drawablesAroundText[1 /* top */]).isNotNull();
- }
-
- @Test
- public void setButtonIcon_iconResourceIdIsZero_shouldNotDisplayIcon() {
- mPref.setButton1Text(R.string.settings_label);
- mPref.setButton1Icon(0);
-
- mPref.onBindViewHolder(mHolder);
- final Drawable[] drawablesAroundText =
- ((Button) mRootView.findViewById(R.id.button1))
- .getCompoundDrawables();
-
- assertThat(drawablesAroundText[1 /* top */]).isNull();
- }
-
- @Test
- public void setButtonIcon_iconResourceIdNotExisting_shouldNotDisplayIconAndCrash() {
- mPref.setButton1Text(R.string.settings_label);
- mPref.setButton1Icon(999999999 /* not existing id */);
- // Should not crash here
- mPref.onBindViewHolder(mHolder);
- final Drawable[] drawablesAroundText =
- ((Button) mRootView.findViewById(R.id.button1))
- .getCompoundDrawables();
-
- assertThat(drawablesAroundText[1 /* top */]).isNull();
- }
-
- public static ActionButtonPreference createMock() {
- final ActionButtonPreference pref = mock(ActionButtonPreference.class);
- when(pref.setButton1Text(anyInt())).thenReturn(pref);
- when(pref.setButton1Icon(anyInt())).thenReturn(pref);
- when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
- when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
- when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-
- when(pref.setButton2Text(anyInt())).thenReturn(pref);
- when(pref.setButton2Icon(anyInt())).thenReturn(pref);
- when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
- when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
- when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-
- when(pref.setButton3Text(anyInt())).thenReturn(pref);
- when(pref.setButton3Icon(anyInt())).thenReturn(pref);
- when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref);
- when(pref.setButton3Visible(anyBoolean())).thenReturn(pref);
- when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
-
- when(pref.setButton4Text(anyInt())).thenReturn(pref);
- when(pref.setButton4Icon(anyInt())).thenReturn(pref);
- when(pref.setButton4Enabled(anyBoolean())).thenReturn(pref);
- when(pref.setButton4Visible(anyBoolean())).thenReturn(pref);
- when(pref.setButton4OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
- return pref;
- }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/widget/RoundedHomepageIconTest.java b/tests/robotests/src/com/android/settings/widget/RoundedHomepageIconTest.java
index aaffa93..5bc8dda 100644
--- a/tests/robotests/src/com/android/settings/widget/RoundedHomepageIconTest.java
+++ b/tests/robotests/src/com/android/settings/widget/RoundedHomepageIconTest.java
@@ -101,7 +101,7 @@
public void onBindTile_externalTileWithBackgroundColorHint_shouldUpdateIcon() {
final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT,
- R.color.memory_critical);
+ R.color.material_blue_500);
doReturn(Icon.createWithResource(mContext, R.drawable.ic_settings))
.when(tile).getIcon(mContext);
@@ -110,7 +110,7 @@
icon.setBackgroundColor(mContext, tile);
assertThat(icon.mBackgroundColor)
- .isEqualTo(mContext.getColor(R.color.memory_critical));
+ .isEqualTo(mContext.getColor(R.color.material_blue_500));
}
}
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
index ae4c753..11dd56e 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
@@ -49,6 +49,7 @@
import com.android.ims.ImsManager;
import com.android.settings.R;
import com.android.settings.slices.CustomSliceManager;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceData;
@@ -113,7 +114,7 @@
mWfcSliceHelper.setDefaultVoiceSubId(-1);
final Slice slice = mWfcSliceHelper.createWifiCallingSlice(
- WifiCallingSliceHelper.WIFI_CALLING_URI);
+ CustomSliceRegistry.WIFI_CALLING_URI);
assertThat(slice).isNull();
}
@@ -123,7 +124,7 @@
when(mMockImsManager.isWfcEnabledByPlatform()).thenReturn(false);
final Slice slice = mWfcSliceHelper.createWifiCallingSlice(
- WifiCallingSliceHelper.WIFI_CALLING_URI);
+ CustomSliceRegistry.WIFI_CALLING_URI);
assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
assertThat(slice).isNull();
@@ -144,7 +145,7 @@
mWfcSliceHelper.setActivationAppIntent(new Intent()); // dummy Intent
final Slice slice = mWfcSliceHelper.createWifiCallingSlice(
- WifiCallingSliceHelper.WIFI_CALLING_URI);
+ CustomSliceRegistry.WIFI_CALLING_URI);
assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
testWifiCallingSettingsUnavailableSlice(slice, null,
@@ -161,7 +162,7 @@
when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null);
final Slice slice = mWfcSliceHelper.createWifiCallingSlice(
- WifiCallingSliceHelper.WIFI_CALLING_URI);
+ CustomSliceRegistry.WIFI_CALLING_URI);
assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
testWifiCallingSettingsToggleSlice(slice, null);
@@ -177,7 +178,7 @@
when(mSlicesFeatureProvider.getNewWifiCallingSliceHelper(mContext))
.thenReturn(mWfcSliceHelper);
- final Slice slice = mProvider.onBindSlice(WifiCallingSliceHelper.WIFI_CALLING_URI);
+ final Slice slice = mProvider.onBindSlice(CustomSliceRegistry.WIFI_CALLING_URI);
assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
testWifiCallingSettingsToggleSlice(slice, null);
@@ -217,7 +218,7 @@
mWfcSliceHelper.setIsWifiCallingPrefEditable(false);
final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice(
- WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI);
+ CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI);
assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
assertThat(slice).isNull();
@@ -232,7 +233,7 @@
mWfcSliceHelper.setIsWifiCallingPrefEditable(true);
final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice(
- WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI);
+ CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI);
assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
testWifiCallingSettingsUnavailableSlice(slice, null,
@@ -251,7 +252,7 @@
mWfcSliceHelper.setIsWifiCallingPrefEditable(true);
final Slice slice = mWfcSliceHelper.createWifiCallingPreferenceSlice(
- WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI);
+ CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI);
assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
testWifiCallingPreferenceSlice(slice, null,
@@ -271,7 +272,7 @@
mWfcSliceHelper.setIsWifiCallingPrefEditable(true);
final Slice slice = mProvider.onBindSlice(
- WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI);
+ CustomSliceRegistry.WIFI_CALLING_PREFERENCE_URI);
assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1);
testWifiCallingPreferenceSlice(slice, null,
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index 4a0988a..39215c1 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -17,12 +17,14 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
@@ -57,6 +59,7 @@
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
@@ -66,12 +69,10 @@
import com.android.settings.testutils.shadow.ShadowBidiFormatter;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
-import com.android.settings.widget.ActionButtonPreference;
-import com.android.settings.widget.ActionButtonPreferenceTest;
import com.android.settings.widget.EntityHeaderController;
-import com.android.settings.wifi.WifiDetailPreference;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.ActionButtonsPreference;
import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.wifi.AccessPoint;
@@ -142,29 +143,29 @@
private ImageView mockHeaderIcon;
@Mock
- private ActionButtonPreference mockButtonsPref;
+ private ActionButtonsPreference mockButtonsPref;
@Mock
- private WifiDetailPreference mockSignalStrengthPref;
+ private Preference mockSignalStrengthPref;
@Mock
- private WifiDetailPreference mockLinkSpeedPref;
+ private Preference mockLinkSpeedPref;
@Mock
- private WifiDetailPreference mockFrequencyPref;
+ private Preference mockFrequencyPref;
@Mock
- private WifiDetailPreference mockSecurityPref;
+ private Preference mockSecurityPref;
@Mock
- private WifiDetailPreference mockMacAddressPref;
+ private Preference mockMacAddressPref;
@Mock
- private WifiDetailPreference mockIpAddressPref;
+ private Preference mockIpAddressPref;
@Mock
- private WifiDetailPreference mockGatewayPref;
+ private Preference mockGatewayPref;
@Mock
- private WifiDetailPreference mockSubnetPref;
+ private Preference mockSubnetPref;
@Mock
- private WifiDetailPreference mockDnsPref;
+ private Preference mockDnsPref;
@Mock
private PreferenceCategory mockIpv6Category;
@Mock
- private WifiDetailPreference mockIpv6AddressesPref;
+ private Preference mockIpv6AddressesPref;
@Mock
private PackageManager mockPackageManager;
@@ -247,7 +248,7 @@
.thenReturn(mockNetworkInfo);
doNothing().when(mockConnectivityManager).registerNetworkCallback(
nullable(NetworkRequest.class), mCallbackCaptor.capture(), nullable(Handler.class));
- mockButtonsPref = ActionButtonPreferenceTest.createMock();
+ mockButtonsPref = createMock();
when(mockButtonsPref.setButton1OnClickListener(mForgetClickListener.capture()))
.thenReturn(mockButtonsPref);
@@ -336,7 +337,7 @@
public void securityPreference_stringShouldBeSet() {
displayAndResume();
- verify(mockSecurityPref).setDetailText(SECURITY);
+ verify(mockSecurityPref).setSummary(SECURITY);
}
@Test
@@ -413,7 +414,7 @@
displayAndResume();
- verify(mockSignalStrengthPref).setDetailText(expectedStrength);
+ verify(mockSignalStrengthPref).setSummary(expectedStrength);
}
@Test
@@ -422,7 +423,7 @@
displayAndResume();
- verify(mockLinkSpeedPref).setDetailText(expectedLinkSpeed);
+ verify(mockLinkSpeedPref).setSummary(expectedLinkSpeed);
}
@Test
@@ -438,7 +439,7 @@
public void macAddressPref_shouldHaveDetailTextSet() {
displayAndResume();
- verify(mockMacAddressPref).setDetailText(MAC_ADDRESS);
+ verify(mockMacAddressPref).setSummary(MAC_ADDRESS);
}
@Test
@@ -447,7 +448,7 @@
displayAndResume();
- verify(mockIpAddressPref).setDetailText(Constants.IPV4_ADDR.getAddress().getHostAddress());
+ verify(mockIpAddressPref).setSummary(Constants.IPV4_ADDR.getAddress().getHostAddress());
}
@Test
@@ -458,8 +459,8 @@
displayAndResume();
- verify(mockSubnetPref).setDetailText("255.255.255.128");
- verify(mockGatewayPref).setDetailText("192.0.2.127");
+ verify(mockSubnetPref).setSummary("255.255.255.128");
+ verify(mockGatewayPref).setSummary("192.0.2.127");
}
@Test
@@ -470,7 +471,7 @@
displayAndResume();
- verify(mockDnsPref).setDetailText(
+ verify(mockDnsPref).setSummary(
"8.8.4.4\n" +
"8.8.8.8\n" +
Constants.IPV6_DNS.getHostAddress());
@@ -551,15 +552,15 @@
lp.addRoute(Constants.IPV4_DEFAULT);
updateLinkProperties(lp);
- inOrder.verify(mockGatewayPref).setDetailText(Constants.IPV4_GATEWAY.getHostAddress());
+ inOrder.verify(mockGatewayPref).setSummary(Constants.IPV4_GATEWAY.getHostAddress());
inOrder.verify(mockGatewayPref).setVisible(true);
lp.addLinkAddress(Constants.IPV4_ADDR);
lp.addRoute(Constants.IPV4_SUBNET);
updateLinkProperties(lp);
- inOrder.verify(mockIpAddressPref).setDetailText(asString(Constants.IPV4_ADDR));
+ inOrder.verify(mockIpAddressPref).setSummary(asString(Constants.IPV4_ADDR));
inOrder.verify(mockIpAddressPref).setVisible(true);
- inOrder.verify(mockSubnetPref).setDetailText("255.255.255.128");
+ inOrder.verify(mockSubnetPref).setSummary("255.255.255.128");
inOrder.verify(mockSubnetPref).setVisible(true);
lp.addLinkAddress(Constants.IPV6_GLOBAL1);
@@ -578,13 +579,13 @@
lp.addDnsServer(Constants.IPV6_DNS);
updateLinkProperties(lp);
- inOrder.verify(mockDnsPref).setDetailText(Constants.IPV6_DNS.getHostAddress());
+ inOrder.verify(mockDnsPref).setSummary(Constants.IPV6_DNS.getHostAddress());
inOrder.verify(mockDnsPref).setVisible(true);
lp.addDnsServer(Constants.IPV4_DNS1);
lp.addDnsServer(Constants.IPV4_DNS2);
updateLinkProperties(lp);
- inOrder.verify(mockDnsPref).setDetailText(
+ inOrder.verify(mockDnsPref).setSummary(
Constants.IPV6_DNS.getHostAddress() + "\n" +
Constants.IPV4_DNS1.getHostAddress() + "\n" +
Constants.IPV4_DNS2.getHostAddress());
@@ -849,4 +850,21 @@
verify(mockAccessPoint, times(2)).getLevel();
verify(mockIconInjector, times(2)).getIcon(anyInt());
}
+
+ private ActionButtonsPreference createMock() {
+ final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+ when(pref.setButton1Text(anyInt())).thenReturn(pref);
+ when(pref.setButton1Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+ when(pref.setButton2Text(anyInt())).thenReturn(pref);
+ when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+ return pref;
+ }
}
diff --git a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
index 81f1fac..bd8649d 100644
--- a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
+++ b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
@@ -26,11 +26,6 @@
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
-import com.android.settings.bluetooth.BluetoothSliceBuilder;
-import com.android.settings.location.LocationSliceBuilder;
-import com.android.settings.notification.ZenModeSliceBuilder;
-import com.android.settings.wifi.WifiSlice;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,7 +52,8 @@
@Test
@Presubmit
public void launchesDeepLinkIntent_wifiSlice_shouldNotCrash() {
- final Intent deepLinkIntent = getSpringboardIntent(WifiSlice.WIFI_URI.toString());
+ final Intent deepLinkIntent = getSpringboardIntent(
+ CustomSliceRegistry.WIFI_SLICE_URI.toString());
mContext.startActivity(deepLinkIntent);
}
@@ -66,7 +62,7 @@
@Presubmit
public void launchesDeepLinkIntent_bluetoothSlice_shouldNotCrash() {
final Intent deepLinkIntent = getSpringboardIntent(
- BluetoothSliceBuilder.BLUETOOTH_URI.toString());
+ CustomSliceRegistry.BLUETOOTH_URI.toString());
mContext.startActivity(deepLinkIntent);
}
@@ -75,7 +71,7 @@
@Presubmit
public void launchesDeepLinkIntent_dndSlice_shouldNotCrash() {
final Intent deepLinkIntent = getSpringboardIntent(
- ZenModeSliceBuilder.ZEN_MODE_URI.toString());
+ CustomSliceRegistry.ZEN_MODE_SLICE_URI.toString());
mContext.startActivity(deepLinkIntent);
}
@@ -84,7 +80,7 @@
@Presubmit
public void launchesDeepLinkIntent_locationSlice_shouldNotCrash() {
final Intent deepLinkIntent = getSpringboardIntent(
- LocationSliceBuilder.LOCATION_URI.toString());
+ CustomSliceRegistry.LOCATION_SLICE_URI.toString());
mContext.startActivity(deepLinkIntent);
}
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
index d101c92..70e9587 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
@@ -35,23 +35,42 @@
new ActivityTestRule<>(WifiDppConfiguratorActivity.class);
@Test
- public void testLaunchModeQrCodeScanner_shouldNotAutoFinish() {
- Intent intent = new Intent();
- intent.putExtra(WifiDppConfiguratorActivity.EXTRA_LAUNCH_MODE,
- WifiDppConfiguratorActivity.LaunchMode.LAUNCH_MODE_QR_CODE_SCANNER.getMode());
+ public void launchActivity_qrCodeScanner_shouldNotAutoFinish() {
+ Intent intent = new Intent(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
+
mActivityRule.launchActivity(intent);
assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(false);
- mActivityRule.finishActivity();
}
@Test
- public void testNoLaunchMode_shouldFinishActivityWithResultCodeCanceled() {
- // If we do not specify launch mode, the activity will finish itself right away
- Intent intent = new Intent();
+ public void launchActivity_qrCodeGenerator_shouldNotAutoFinish() {
+ Intent intent = new Intent(
+ WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
+
mActivityRule.launchActivity(intent);
- assertThat(mActivityRule.getActivityResult().getResultCode()).
- isEqualTo(Activity.RESULT_CANCELED);
+ assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(false);
+ }
+
+ @Test
+ public void launchActivity_chooseSavedWifiNetwork_shouldNotAutoFinish() {
+ Intent intent = new Intent(
+ WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_CHOOSE_SAVED_WIFI_NETWORK);
+
+ mActivityRule.launchActivity(intent);
+
+ assertThat(mActivityRule.getActivity().isFinishing()).isEqualTo(false);
+ }
+
+ @Test
+ public void testActivity_shouldImplementsWifiNetworkConfigRetriever() {
+ WifiDppConfiguratorActivity activity = mActivityRule.getActivity();
+
+ assertThat(activity instanceof WifiNetworkConfig.Retriever).isEqualTo(true);
}
}
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
index 58fa61f..98742ed 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
@@ -24,9 +24,12 @@
import android.app.Activity;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
+import com.android.settings.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -40,16 +43,17 @@
@Before
public void setUp() {
- Intent intent = new Intent();
- intent.putExtra(WifiDppConfiguratorActivity.EXTRA_LAUNCH_MODE,
- WifiDppConfiguratorActivity.LaunchMode.LAUNCH_MODE_QR_CODE_SCANNER.getMode());
+ Intent intent = new Intent(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WEP");
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "GoogleGuest");
mActivityRule.launchActivity(intent);
}
@Test
- public void testLeftButton_shouldFinishActivityWithResultCodeCanceled() {
- onView(withText("Cancel")).perform(click());
- assertThat(mActivityRule.getActivityResult().getResultCode()).
- isEqualTo(Activity.RESULT_CANCELED);
+ public void rotateScreen_shouldNotCrash() {
+ mActivityRule.getActivity().setRequestedOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ mActivityRule.getActivity().setRequestedOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}