Snap for 5138341 from b4dcebec03 to qt-release
Change-Id: I735aca69d09042e089b615beaf681646f5cd1602
This commit is contained in:
@@ -109,6 +109,22 @@
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="switch_bar_background">#dadce0</color>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values-night/colors.xml"
|
||||
line="19"
|
||||
column="3"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
@@ -125,6 +141,22 @@
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="switchbar_switch_track_tint">#82000000</color>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values-night/colors.xml"
|
||||
line="20"
|
||||
column="3"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
@@ -1221,8 +1253,8 @@
|
||||
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_location_background">#1A73E8</color>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
errorLine1=" <color name="homepage_location_background">#2EC7DC</color>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="128"
|
||||
@@ -1238,7 +1270,7 @@
|
||||
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_about_background">#9FA8DA</color>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="129"
|
||||
@@ -1253,12 +1285,28 @@
|
||||
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_privacy_background">#1A73E8</color>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
errorLine1=" <color name="homepage_privacy_background">#5E97F6</color>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="130"
|
||||
column="5"/>
|
||||
file="res/values/colors.xml"
|
||||
line="130"
|
||||
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="switchbar_switch_track_tint">#BFFFFFFF</color>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="134"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
@@ -1271,76 +1319,76 @@
|
||||
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="battery_good_color_light">#43a047</color> <!-- Material Green 600 -->"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="135"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="battery_maybe_color_light">#ef6c00</color> <!-- Material Orange 800 -->"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="136"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="battery_bad_color_light">#f44336</color> <!-- Material Red 500 -->"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="137"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="battery_good_color_dark">#4caf50</color> <!-- Material Green 500 -->"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="138"
|
||||
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="battery_maybe_color_dark">#fdd835</color> <!-- Material Yellow 600 -->"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="139"
|
||||
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="battery_maybe_color_light">#ef6c00</color> <!-- Material Orange 800 -->"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="140"
|
||||
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="battery_bad_color_light">#f44336</color> <!-- Material Red 500 -->"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="141"
|
||||
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="battery_good_color_dark">#4caf50</color> <!-- Material Green 500 -->"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="142"
|
||||
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="battery_maybe_color_dark">#fdd835</color> <!-- Material Yellow 600 -->"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="143"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
@@ -1353,7 +1401,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="140"
|
||||
line="144"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
@@ -1369,7 +1417,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="143"
|
||||
line="147"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
@@ -1385,7 +1433,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="144"
|
||||
line="148"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
@@ -1401,7 +1449,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="145"
|
||||
line="149"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
@@ -1417,7 +1465,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="146"
|
||||
line="150"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
@@ -1433,7 +1481,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="147"
|
||||
line="151"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
@@ -1449,7 +1497,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/layout-land/confirm_lock_pattern_normal.xml"
|
||||
line="111"
|
||||
line="103"
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
@@ -1734,7 +1782,7 @@
|
||||
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=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/drawable/ic_homepage_about.xml"
|
||||
line="23"
|
||||
@@ -1853,6 +1901,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=" android:color="@color/homepage_location_background"/>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/drawable/ic_homepage_location.xml"
|
||||
line="23"
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
@@ -1869,6 +1933,22 @@
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" android:color="@color/homepage_privacy_background"/>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/drawable/ic_homepage_privacy.xml"
|
||||
line="23"
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
@@ -1917,54 +1997,6 @@
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" android:color="@color/homepage_location_background" />"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/drawable/ic_homepage_privacy.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_location_background" />"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/drawable/ic_homepage_location.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_location_background" />"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/drawable/ic_preference_location.xml"
|
||||
line="23"
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
@@ -1997,6 +2029,22 @@
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" android:color="@color/homepage_location_background"/>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/drawable/ic_preference_location.xml"
|
||||
line="23"
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
@@ -2505,7 +2553,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values-en-rXC/strings.xml"
|
||||
line="2524"
|
||||
line="2530"
|
||||
column="168"/>
|
||||
</issue>
|
||||
|
||||
@@ -2521,7 +2569,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values-en-rAU/strings.xml"
|
||||
line="2525"
|
||||
line="2531"
|
||||
column="64"/>
|
||||
</issue>
|
||||
|
||||
@@ -2537,7 +2585,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values-en-rCA/strings.xml"
|
||||
line="2525"
|
||||
line="2531"
|
||||
column="64"/>
|
||||
</issue>
|
||||
|
||||
@@ -2553,7 +2601,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values-en-rGB/strings.xml"
|
||||
line="2525"
|
||||
line="2531"
|
||||
column="64"/>
|
||||
</issue>
|
||||
|
||||
@@ -2569,7 +2617,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values-en-rIN/strings.xml"
|
||||
line="2525"
|
||||
line="2531"
|
||||
column="64"/>
|
||||
</issue>
|
||||
|
||||
@@ -2585,7 +2633,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/strings.xml"
|
||||
line="5865"
|
||||
line="5886"
|
||||
column="36"/>
|
||||
</issue>
|
||||
|
||||
@@ -2601,7 +2649,7 @@
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/styles.xml"
|
||||
line="171"
|
||||
line="179"
|
||||
column="41"/>
|
||||
</issue>
|
||||
|
||||
@@ -2617,7 +2665,7 @@
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/styles.xml"
|
||||
line="425"
|
||||
line="443"
|
||||
column="44"/>
|
||||
</issue>
|
||||
|
||||
@@ -2633,7 +2681,7 @@
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/styles.xml"
|
||||
line="431"
|
||||
line="449"
|
||||
column="44"/>
|
||||
</issue>
|
||||
|
||||
@@ -2649,7 +2697,7 @@
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/styles.xml"
|
||||
line="432"
|
||||
line="450"
|
||||
column="44"/>
|
||||
</issue>
|
||||
|
||||
@@ -2713,7 +2761,7 @@
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/themes.xml"
|
||||
line="86"
|
||||
line="91"
|
||||
column="47"/>
|
||||
</issue>
|
||||
|
||||
@@ -2725,12 +2773,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=" <item name="android:statusBarColor">#00000000</item>"
|
||||
errorLine2=" ^">
|
||||
errorLine1=" <item name="switchBarBackgroundColor">@color/switch_bar_background</item>"
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/themes.xml"
|
||||
line="151"
|
||||
column="45"/>
|
||||
line="91"
|
||||
column="47"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
@@ -2741,12 +2789,28 @@
|
||||
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="android:navigationBarColor">#00000000</item>"
|
||||
errorLine2=" ^">
|
||||
errorLine1=" <item name="android:trackTint">@color/switchbar_switch_track_tint</item>"
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/themes.xml"
|
||||
line="152"
|
||||
column="49"/>
|
||||
line="97"
|
||||
column="40"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <item name="android:trackTint">@color/switchbar_switch_track_tint</item>"
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/themes.xml"
|
||||
line="97"
|
||||
column="40"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
@@ -2789,12 +2853,28 @@
|
||||
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="android:navigationBarDividerColor">#1f000000</item>"
|
||||
errorLine2=" ^">
|
||||
errorLine1=" <item name="android:statusBarColor">#00000000</item>"
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/themes.xml"
|
||||
line="175"
|
||||
column="56"/>
|
||||
line="169"
|
||||
column="45"/>
|
||||
</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="android:navigationBarColor">#00000000</item>"
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/themes.xml"
|
||||
line="170"
|
||||
column="49"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
@@ -2905,7 +2985,7 @@
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/themes_suw.xml"
|
||||
line="187"
|
||||
line="186"
|
||||
column="43"/>
|
||||
</issue>
|
||||
|
||||
@@ -2921,7 +3001,7 @@
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/themes_suw.xml"
|
||||
line="188"
|
||||
line="187"
|
||||
column="42"/>
|
||||
</issue>
|
||||
|
||||
@@ -2937,7 +3017,7 @@
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="res/values/themes_suw.xml"
|
||||
line="189"
|
||||
line="188"
|
||||
column="45"/>
|
||||
</issue>
|
||||
|
||||
|
||||
@@ -21,6 +21,5 @@
|
||||
android:height="18dp">
|
||||
<path
|
||||
android:pathData="M36 16l-2 0 0 -4C34 6.48 29.52 2 24 2 18.48 2 14 6.48 14 12l0 4 -2 0c-2.21 0 -4 1.79 -4 4l0 20c0 2.21 1.79 4 4 4l24 0c2.21 0 4 -1.79 4 -4l0 -20c0 -2.21 -1.79 -4 -4 -4zM24 34c-2.21 0 -4 -1.79 -4 -4 0 -2.21 1.79 -4 4 -4 2.21 0 4 1.79 4 4 0 2.21 -1.79 4 -4 4zm6.2 -18l-12.4 0 0 -4c0 -3.42 2.78 -6.2 6.2 -6.2 3.42 0 6.2 2.78 6.2 6.2l0 4z"
|
||||
android:fillColor="?android:attr/colorForeground"
|
||||
android:fillAlpha="0.54" />
|
||||
android:fillColor="?attr/frictionIconColor" />
|
||||
</vector>
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
android:width="18dp"
|
||||
android:height="18dp">
|
||||
|
||||
<path android:fillColor="?android:attr/colorForeground"
|
||||
android:fillAlpha="0.54"
|
||||
<path android:fillColor="?attr/frictionIconColor"
|
||||
android:pathData="M9.56 8.1c-1.6-.51-2.66-.71-2.66-1.88 0-.83 .72 -1.62 2.1-1.62 1.59 0 2.1 .88
|
||||
2.1 1.94H13c0-1.79-1.17-3.09-3-3.44V1H8v2.11c-1.58 .32 -3 1.37-3 3.12 0 2.25
|
||||
1.78 2.8 4 3.52 1.88 .61 2.25 1.04 2.25 2.09 0 .9-.67 1.56-2.25 1.56-1.2
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
@@ -15,6 +14,12 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="#FFFFFF" />
|
||||
</selector>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41z"/>
|
||||
</vector>
|
||||
31
res/drawable/ic_settings_delete.xml
Normal file
31
res/drawable/ic_settings_delete.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
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:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M15,4V3H9v1H4v2h1v13c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V6h1V4H15zM17,19H7V6h10V19z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M9,8h2v9h-2z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M13,8h2v9h-2z"/>
|
||||
</vector>
|
||||
31
res/drawable/ic_settings_force_stop.xml
Normal file
31
res/drawable/ic_settings_force_stop.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
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:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,5.99L19.53,19H4.47L12,5.99M12,2L1,21h22L12,2L12,2z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M13,16l-2,0l0,2l2,0l0,-2z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M13,10l-2,0l0,4l2,0l0,-4z"/>
|
||||
</vector>
|
||||
28
res/drawable/ic_settings_install.xml
Normal file
28
res/drawable/ic_settings_install.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<!--
|
||||
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:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M18,15v3H6v-3H4v3c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-3H18z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M17,11.5l-1.41,-1.41l-2.59,2.58l0,-8.67l-2,0l0,8.67l-2.59,-2.58l-1.41,1.41l5,5z"/>
|
||||
</vector>
|
||||
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
@@ -15,7 +14,12 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<selector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="#BFFFFFFF" />
|
||||
</selector>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19,19H5V5h7V3H5C3.89,3 3,3.9 3,5v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2V19zM14,3v2h3.59l-9.83,9.83l1.41,1.41L19,6.41V10h2V3H14z"/>
|
||||
</vector>
|
||||
78
res/layout-land/storage_summary_donut.xml
Normal file
78
res/layout-land/storage_summary_donut.xml
Normal file
@@ -0,0 +1,78 @@
|
||||
<?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:background="?android:attr/colorPrimary"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/preference_no_icon_padding_start"
|
||||
android:paddingEnd="@dimen/storage_summary_padding_end"
|
||||
android:paddingTop="32dp"
|
||||
android:paddingBottom="32dp" >
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamily"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Display1"
|
||||
android:textSize="36sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:maxLines="10"
|
||||
android:paddingBottom="20dp"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Body1" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/deletion_helper_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/summary"
|
||||
android:text="@string/storage_menu_free"
|
||||
style="@style/ActionPrimaryButton" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.android.settings.widget.DonutView
|
||||
android:id="@+id/donut"
|
||||
android:layout_width="112dp"
|
||||
android:layout_height="112dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:gravity="end|center_vertical"
|
||||
android:minWidth="58dp"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
|
||||
|
||||
</LinearLayout>
|
||||
78
res/layout-sw360dp/storage_summary_donut.xml
Normal file
78
res/layout-sw360dp/storage_summary_donut.xml
Normal file
@@ -0,0 +1,78 @@
|
||||
<?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:background="?android:attr/colorPrimary"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/preference_no_icon_padding_start"
|
||||
android:paddingEnd="@dimen/storage_summary_padding_end"
|
||||
android:paddingTop="32dp"
|
||||
android:paddingBottom="32dp" >
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamily"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Display1"
|
||||
android:textSize="36sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:maxLines="10"
|
||||
android:paddingBottom="20dp"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Body1" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/deletion_helper_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/summary"
|
||||
android:text="@string/storage_menu_free"
|
||||
style="@style/ActionPrimaryButton" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.android.settings.widget.DonutView
|
||||
android:id="@+id/donut"
|
||||
android:layout_width="112dp"
|
||||
android:layout_height="112dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:gravity="end|center_vertical"
|
||||
android:minWidth="58dp"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -21,15 +21,15 @@
|
||||
android:id="@+id/search_bar_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
android:background="?android:attr/colorPrimary">
|
||||
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"
|
||||
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:cardBackgroundColor="?android:attr/colorBackground"
|
||||
app:cardElevation="@dimen/search_bar_card_elevation">
|
||||
<Toolbar
|
||||
android:id="@+id/search_action_bar"
|
||||
@@ -37,8 +37,7 @@
|
||||
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"
|
||||
android:theme="?android:attr/actionBarTheme">
|
||||
android:navigationIcon="@drawable/ic_search_24dp">
|
||||
<TextView
|
||||
android:id="@+id/search_action_bar_title"
|
||||
style="@style/TextAppearance.SearchBar"
|
||||
|
||||
@@ -18,62 +18,46 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/colorPrimary"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal" >
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="32dp"
|
||||
android:paddingBottom="32dp" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:enabled="false"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/preference_no_icon_padding_start"
|
||||
android:paddingEnd="@dimen/storage_summary_padding_end"
|
||||
android:paddingTop="32dp"
|
||||
android:paddingBottom="32dp" >
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamily"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Display1"
|
||||
android:textSize="36sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:fontFamily="@*android:string/config_headlineFontFamily"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Display1"
|
||||
android:textSize="36sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:maxLines="10"
|
||||
android:paddingBottom="20dp"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Body1" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/deletion_helper_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/summary"
|
||||
android:text="@string/storage_menu_free"
|
||||
style="@style/ActionPrimaryButton" />
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:maxLines="10"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Body1" />
|
||||
|
||||
<com.android.settings.widget.DonutView
|
||||
android:id="@+id/donut"
|
||||
android:layout_width="112dp"
|
||||
android:layout_height="112dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:gravity="end|center_vertical"
|
||||
android:minWidth="58dp"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
|
||||
android:layout_width="168dp"
|
||||
android:layout_height="168dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:minWidth="58dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/deletion_helper_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/storage_menu_free"
|
||||
style="@style/ActionPrimaryButton" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="@style/TextAppearance.Switch"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textColor="?android:attr/textColorPrimaryInverse"
|
||||
android:textAlignment="viewStart"/>
|
||||
|
||||
<ImageView
|
||||
|
||||
@@ -19,47 +19,28 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingTop="24dp"
|
||||
android:paddingStart="68dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<FrameLayout
|
||||
<Button
|
||||
android:id="@+id/button1"
|
||||
style="@style/SettingsActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content">
|
||||
<Button
|
||||
android:id="@+id/button1_positive"
|
||||
style="@style/ActionPrimaryButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp" />
|
||||
<Button
|
||||
android:id="@+id/button1_negative"
|
||||
style="@style/ActionSecondaryButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp" />
|
||||
</FrameLayout>
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="20dp"/>
|
||||
<Space
|
||||
android:layout_width="16dp"
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="wrap_content" />
|
||||
<FrameLayout
|
||||
|
||||
<Button
|
||||
android:id="@+id/button2"
|
||||
style="@style/SettingsActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content">
|
||||
<Button
|
||||
android:id="@+id/button2_positive"
|
||||
style="@style/ActionPrimaryButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp" />
|
||||
<Button
|
||||
android:id="@+id/button2_negative"
|
||||
style="@style/ActionSecondaryButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp" />
|
||||
</FrameLayout>
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="20dp"/>
|
||||
</LinearLayout>
|
||||
@@ -30,4 +30,9 @@
|
||||
<!-- Display, Screen zoom -->
|
||||
<dimen name="screen_zoom_preview_height">160dp</dimen>
|
||||
|
||||
<!-- Text size of the big number in the donut. -->
|
||||
<dimen name="storage_donut_view_percent_text_size">30sp</dimen>
|
||||
<!-- Text size of the label text in the donut. -->
|
||||
<dimen name="storage_donut_view_label_text_size">14sp</dimen>
|
||||
|
||||
</resources>
|
||||
|
||||
23
res/values-night/colors.xml
Normal file
23
res/values-night/colors.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<color name="switchbar_text_color">@android:color/black</color>
|
||||
<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>
|
||||
</resources>
|
||||
|
||||
24
res/values-night/styles.xml
Normal file
24
res/values-night/styles.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<style name="Widget.ActionBar.Base" parent="@android:style/Widget.DeviceDefault.ActionBar.Solid">
|
||||
<item name="android:background">?android:attr/colorPrimaryDark</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -20,6 +20,21 @@
|
||||
<style name="Theme.Settings.Home" parent="Theme.Settings.HomeBase">
|
||||
<item name="colorPrimary">@*android:color/primary_device_default_settings</item>
|
||||
<item name="colorPrimaryDark">@*android:color/primary_dark_device_default_settings</item>
|
||||
<item name="android:colorBackground">?android:attr/colorPrimaryDark</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.Settings.SearchBar" parent="Theme.Settings">
|
||||
<item name="android:colorBackground">?android:attr/colorPrimaryDark</item>
|
||||
<item name="cardBackgroundColor">?android:attr/colorPrimary</item>
|
||||
<item name="android:colorControlNormal">?android:attr/colorAccent</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.SubSettings" parent="Theme.SubSettings.Base">
|
||||
<item name="android:colorControlNormal">?android:attr/colorAccent</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.AlertDialog.Base" parent="@style/Theme.AppCompat.DayNight.Dialog.Alert">
|
||||
<item name="colorAccent">@*android:color/accent_device_default_dark</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -25,4 +25,8 @@
|
||||
<!-- Suggestion cards-->
|
||||
<dimen name="suggestion_card_padding_bottom_one_card">22dp</dimen>
|
||||
|
||||
<!-- Text size of the big number in the donut. -->
|
||||
<dimen name="storage_donut_view_percent_text_size">30sp</dimen>
|
||||
<!-- Text size of the label text in the donut. -->
|
||||
<dimen name="storage_donut_view_label_text_size">14sp</dimen>
|
||||
</resources>
|
||||
@@ -697,6 +697,33 @@
|
||||
<item>Accessibility volume</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Keys for the list of accessibility timeouts xml. -->
|
||||
<string-array name="accessibility_timeout_content_selector_keys" translatable="false">
|
||||
<item>accessibility_content_timeout_default</item>
|
||||
<item>accessibility_content_timeout_10secs</item>
|
||||
<item>accessibility_content_timeout_30secs</item>
|
||||
<item>accessibility_content_timeout_1min</item>
|
||||
<item>accessibility_content_timeout_2mins</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Keys for the list of accessibility timeouts xml. -->
|
||||
<string-array name="accessibility_timeout_control_selector_keys" translatable="false">
|
||||
<item>accessibility_control_timeout_default</item>
|
||||
<item>accessibility_control_timeout_10secs</item>
|
||||
<item>accessibility_control_timeout_30secs</item>
|
||||
<item>accessibility_control_timeout_1min</item>
|
||||
<item>accessibility_control_timeout_2mins</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Values for the list of accessibility timeouts, pairs to Keys . -->
|
||||
<integer-array name="accessibility_timeout_selector_values" translatable="false">
|
||||
<item>0</item>
|
||||
<item>10000</item>
|
||||
<item>30000</item>
|
||||
<item>60000</item>
|
||||
<item>120000</item>
|
||||
</integer-array>
|
||||
|
||||
<!-- Titles for the list of long press timeout options. -->
|
||||
<string-array name="long_press_timeout_selector_titles">
|
||||
<!-- A title for the option for short long-press timeout [CHAR LIMIT=25] -->
|
||||
|
||||
@@ -154,4 +154,5 @@
|
||||
<attr name="side_margin" format="reference|dimension" />
|
||||
<attr name="wifi_signal_color" format="reference" />
|
||||
|
||||
<attr name="frictionIconColor" format="reference|color" />
|
||||
</resources>
|
||||
|
||||
@@ -130,6 +130,10 @@
|
||||
<color name="homepage_privacy_background">#5E97F6</color>
|
||||
<!-- End of dashboard/homepage icon background colors -->
|
||||
|
||||
<color name="switchbar_text_color">@android:color/white</color>
|
||||
<color name="switchbar_switch_track_tint">#BFFFFFFF</color>
|
||||
<color name="switchbar_switch_thumb_tint">@android:color/white</color>
|
||||
|
||||
<color name="glif_error_color">@*android:color/material_red_A700</color>
|
||||
|
||||
<color name="battery_good_color_light">#43a047</color> <!-- Material Green 600 -->
|
||||
|
||||
@@ -274,11 +274,11 @@
|
||||
<!-- Padding between the donut and the storage summary. -->
|
||||
<dimen name="storage_summary_padding_end">16dp</dimen>
|
||||
<!-- Text size of the big number in the donut. -->
|
||||
<dimen name="storage_donut_view_percent_text_size">30sp</dimen>
|
||||
<dimen name="storage_donut_view_percent_text_size">45sp</dimen>
|
||||
<!-- Text size of the percentage sign in the donut. -->
|
||||
<dimen name="storage_donut_view_percent_sign_size">20sp</dimen>
|
||||
<!-- Text size of the label text in the donut. -->
|
||||
<dimen name="storage_donut_view_label_text_size">14sp</dimen>
|
||||
<dimen name="storage_donut_view_label_text_size">21sp</dimen>
|
||||
<!-- Text size of the label text in the donut if the label text is long. -->
|
||||
<dimen name="storage_donut_view_shrunken_label_text_size">10sp</dimen>
|
||||
<!-- The width of the storage summary donut -->
|
||||
|
||||
@@ -4002,8 +4002,6 @@
|
||||
<string name="uninstall_all_users_text">Uninstall for all users</string>
|
||||
<!-- [CHAR LIMIT=NONE] Manage applications, individual application info screen, button label under Storage heading. Button to install an application for the user. -->
|
||||
<string name="install_text">Install</string>
|
||||
<!-- [CHAR LIMIT=25] Manage applications, individual application info screen, button label under Storage heading. Button to disable an existing application. -->
|
||||
<string name="disable_text">Disable</string>
|
||||
<!-- [CHAR LIMIT=25] Manage applications, individual application info screen, button label under Storage heading. Button to re-enable an existing application. -->
|
||||
<string name="enable_text">Enable</string>
|
||||
<!-- Manage applications, individual application info screen, button label under Storage heading. Button to clear all data associated with tis app (for example, remove all cached emails for an Email app) -->
|
||||
@@ -4575,6 +4573,24 @@
|
||||
<string name="accessibility_toggle_master_mono_title">Mono audio</string>
|
||||
<!-- Summary for the accessibility preference for master mono. [CHAR LIMIT=50] -->
|
||||
<string name="accessibility_toggle_master_mono_summary">Combine channels when playing audio</string>
|
||||
|
||||
<!-- Title for accessibility preference to accessibility timeout. [CHAR LIMIT=35] -->
|
||||
<string name="accessibility_timeout_default">Default</string>
|
||||
<!-- Title for accessibility preference to accessibility timeout. [CHAR LIMIT=35] -->
|
||||
<string name="accessibility_timeout_10secs">10 seconds</string>
|
||||
<!-- Title for accessibility preference to accessibility timeout. [CHAR LIMIT=35] -->
|
||||
<string name="accessibility_timeout_30secs">30 seconds</string>
|
||||
<!-- Title for accessibility preference to accessibility timeout. [CHAR LIMIT=35] -->
|
||||
<string name="accessibility_timeout_1min">1 minute</string>
|
||||
<!-- Title for accessibility preference to accessibility timeout. [CHAR LIMIT=35] -->
|
||||
<string name="accessibility_timeout_2mins">2 minutes</string>
|
||||
<!-- Title for accessibility preference to accessibility message_timeout. [CHAR LIMIT=35] -->
|
||||
<string name="accessibility_accessibility_content_timeout_preference_title">Content Timeout</string>
|
||||
<!-- Title for accessibility preference to accessibility message_timeout. [CHAR LIMIT=35] -->
|
||||
<string name="accessibility_accessibility_control_timeout_preference_title">Control Timeout</string>
|
||||
<!-- Title for accessibility preference to accessibility message_timeout. [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_accessibility_timeout_preference_summary">Choose how long it takes before automatically disappearing messages go away.\nSome apps may not support this setting yet.</string>
|
||||
|
||||
<!-- Title for accessibility preference to choose long-press delay i.e. timeout before it is detected. [CHAR LIMIT=35] -->
|
||||
<string name="accessibility_long_press_timeout_preference_title">Touch & hold delay</string>
|
||||
<!-- Title for the accessibility preference to configure display color inversion. [CHAR LIMIT=NONE] -->
|
||||
@@ -8025,6 +8041,19 @@
|
||||
<!-- [CHAR LIMIT=80] Zen mode settings: Allow event notifications/sounds to bypass DND -->
|
||||
<string name="zen_mode_events">Allow events</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Zen mode settings: Allow apps to bypass DND -->
|
||||
<string name="zen_mode_bypassing_apps">Allow apps to override</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Zen mode settings: Allow apps to bypass DND title-->
|
||||
<string name="zen_mode_bypassing_apps_title">Overrides Do Not Disturb</string>
|
||||
|
||||
<!-- [CHAR LIMIT=80] Zen mode settings: Allow apps to bypass DND -->
|
||||
<plurals name="zen_mode_bypassing_apps_subtext">
|
||||
<item quantity="zero">No apps can override Do Not Disturb</item>
|
||||
<item quantity="one">1 app can override Do Not Disturb</item>
|
||||
<item quantity="other"><xliff:g id="number" example="2">%1$d</xliff:g> apps can override Do Not Disturb</item>
|
||||
</plurals>
|
||||
|
||||
<!-- [CHAR LIMIT=50] Zen mode settings: Events (ie: calendar events) -->
|
||||
<string name="zen_mode_events_list">events</string>
|
||||
|
||||
@@ -10302,4 +10331,7 @@
|
||||
<string name="contextual_card_dismiss_keep">Keep</string>
|
||||
<!-- String for contextual card dismissal [CHAR LIMIT=NONE] -->
|
||||
<string name="contextual_card_dismiss_confirm_message">Remove this suggestion?</string>
|
||||
|
||||
<!-- 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>
|
||||
@@ -16,12 +16,15 @@
|
||||
|
||||
<resources>
|
||||
|
||||
<style name="Theme.ActionBar"
|
||||
parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid">
|
||||
<style name="Widget.ActionBar.Base"
|
||||
parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid"/>
|
||||
|
||||
<style name="Widget.ActionBar"
|
||||
parent="Widget.ActionBar.Base">
|
||||
<item name="android:contentInsetStart">@dimen/actionbar_contentInsetStart</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.ActionBar.SubSettings" parent="Theme.ActionBar">
|
||||
<style name="Widget.ActionBar.SubSettings" parent="Widget.ActionBar">
|
||||
<item name="android:contentInsetStart">@dimen/actionbar_subsettings_contentInsetStart</item>
|
||||
</style>
|
||||
|
||||
@@ -426,6 +429,11 @@
|
||||
|
||||
<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>
|
||||
</style>
|
||||
|
||||
<style name="LockPatternContainerStyle">
|
||||
<item name="android:maxHeight">400dp</item>
|
||||
<item name="android:maxWidth">420dp</item>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<item name="suwListItemIconColor">?android:attr/colorAccent</item>
|
||||
|
||||
<!-- Redefine the ActionBar style for contentInsetStart -->
|
||||
<item name="android:actionBarStyle">@style/Theme.ActionBar</item>
|
||||
<item name="android:actionBarStyle">@style/Widget.ActionBar</item>
|
||||
|
||||
<item name="switchBarTheme">@style/ThemeOverlay.SwitchBar.Settings</item>
|
||||
|
||||
@@ -62,13 +62,18 @@
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.SubSettings" parent="Theme.Settings">
|
||||
<style name="Theme.SubSettings.Base" parent="Theme.Settings">
|
||||
<!-- Redefine the ActionBar style for contentInsetStart -->
|
||||
<item name="android:actionBarStyle">@style/Theme.ActionBar.SubSettings</item>
|
||||
<item name="android:actionBarStyle">@style/Widget.ActionBar.SubSettings</item>
|
||||
|
||||
<item name="switchBarTheme">@style/ThemeOverlay.SwitchBar.Settings</item>
|
||||
|
||||
<!-- Friction icon color for wifi preferences -->
|
||||
<item name="frictionIconColor">?android:colorControlNormal</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.SubSettings" parent="Theme.SubSettings.Base"/>
|
||||
|
||||
<style name="Theme.ProvisioningActivity" parent="@android:style/Theme.Translucent.NoTitleBar">
|
||||
<item name="android:windowAnimationStyle">@null</item>
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
@@ -80,7 +85,6 @@
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.SwitchBar.Settings" parent="@android:style/ThemeOverlay.Material.ActionBar">
|
||||
<item name="android:textColorPrimary">@android:color/white</item>
|
||||
<item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
|
||||
<item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
|
||||
<item name="switchBarBackgroundColor">@color/switch_bar_background</item>
|
||||
@@ -107,14 +111,17 @@
|
||||
<item name="android:windowSoftInputMode">adjustResize</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.AlertDialog" parent="@style/Theme.AppCompat.DayNight.Dialog.Alert">
|
||||
<style name="Theme.AlertDialog.Base" parent="@style/Theme.AppCompat.DayNight.Dialog.Alert">
|
||||
<item name="colorAccent">@*android:color/accent_device_default_light</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.AlertDialog" parent="Theme.AlertDialog.Base">
|
||||
<item name="android:windowSoftInputMode">adjustResize</item>
|
||||
|
||||
<!-- Redefine the ActionBar style for contentInsetStart -->
|
||||
<item name="android:actionBarStyle">@style/Theme.ActionBar</item>
|
||||
<item name="android:actionBarStyle">@style/Widget.ActionBar</item>
|
||||
|
||||
<!-- copied from Theme.DeviceDefault.Light.Dialog.Alert -->
|
||||
<item name="colorAccent">@*android:color/accent_device_default_light</item>
|
||||
<item name="dialogCornerRadius">@*android:dimen/config_dialogCornerRadius</item>
|
||||
</style>
|
||||
|
||||
@@ -183,4 +190,9 @@
|
||||
<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>
|
||||
|
||||
</resources>
|
||||
|
||||
63
res/xml/accessibility_content_timeout_settings.xml
Normal file
63
res/xml/accessibility_content_timeout_settings.xml
Normal file
@@ -0,0 +1,63 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:key="accessibility_content_timeout_preference"
|
||||
android:title="@string/accessibility_accessibility_content_timeout_preference_title"
|
||||
android:persistent="false" >
|
||||
|
||||
<com.android.settings.widget.VideoPreference
|
||||
android:key="accessibility_content_timeout_video"
|
||||
app:animation="@raw/gesture_swipe_up"
|
||||
app:preview="@drawable/gesture_swipe_up"
|
||||
android:persistent="false" />
|
||||
|
||||
<Preference
|
||||
android:key="accessibility_content_timeout_summary"
|
||||
android:selectable="false"
|
||||
android:enabled="true"
|
||||
android:summary="@string/accessibility_accessibility_timeout_preference_summary"
|
||||
android:persistent="false" />
|
||||
|
||||
<com.android.settings.widget.RadioButtonPreference
|
||||
android:key="accessibility_content_timeout_default"
|
||||
android:title="@string/accessibility_timeout_default"
|
||||
android:persistent="false" />
|
||||
|
||||
<com.android.settings.widget.RadioButtonPreference
|
||||
android:key="accessibility_content_timeout_10secs"
|
||||
android:title="@string/accessibility_timeout_10secs"
|
||||
android:persistent="false" />
|
||||
|
||||
<com.android.settings.widget.RadioButtonPreference
|
||||
android:key="accessibility_content_timeout_30secs"
|
||||
android:title="@string/accessibility_timeout_30secs"
|
||||
android:persistent="false" />
|
||||
|
||||
<com.android.settings.widget.RadioButtonPreference
|
||||
android:key="accessibility_content_timeout_1min"
|
||||
android:title="@string/accessibility_timeout_1min"
|
||||
android:persistent="false" />
|
||||
|
||||
<com.android.settings.widget.RadioButtonPreference
|
||||
android:key="accessibility_content_timeout_2mins"
|
||||
android:title="@string/accessibility_timeout_2mins"
|
||||
android:persistent="false" />
|
||||
|
||||
</PreferenceScreen>
|
||||
63
res/xml/accessibility_control_timeout_settings.xml
Normal file
63
res/xml/accessibility_control_timeout_settings.xml
Normal file
@@ -0,0 +1,63 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:key="accessibility_control_timeout_preference"
|
||||
android:title="@string/accessibility_accessibility_control_timeout_preference_title"
|
||||
android:persistent="false" >
|
||||
|
||||
<com.android.settings.widget.VideoPreference
|
||||
android:key="accessibility_control_timeout_video"
|
||||
app:animation="@raw/gesture_swipe_up"
|
||||
app:preview="@drawable/gesture_swipe_up"
|
||||
android:persistent="false" />
|
||||
|
||||
<Preference
|
||||
android:key="accessibility_control_timeout_summary"
|
||||
android:selectable="false"
|
||||
android:enabled="true"
|
||||
android:summary="@string/accessibility_accessibility_timeout_preference_summary"
|
||||
android:persistent="false" />
|
||||
|
||||
<com.android.settings.widget.RadioButtonPreference
|
||||
android:key="accessibility_control_timeout_default"
|
||||
android:title="@string/accessibility_timeout_default"
|
||||
android:persistent="false" />
|
||||
|
||||
<com.android.settings.widget.RadioButtonPreference
|
||||
android:key="accessibility_control_timeout_10secs"
|
||||
android:title="@string/accessibility_timeout_10secs"
|
||||
android:persistent="false" />
|
||||
|
||||
<com.android.settings.widget.RadioButtonPreference
|
||||
android:key="accessibility_control_timeout_30secs"
|
||||
android:title="@string/accessibility_timeout_30secs"
|
||||
android:persistent="false" />
|
||||
|
||||
<com.android.settings.widget.RadioButtonPreference
|
||||
android:key="accessibility_control_timeout_1min"
|
||||
android:title="@string/accessibility_timeout_1min"
|
||||
android:persistent="false" />
|
||||
|
||||
<com.android.settings.widget.RadioButtonPreference
|
||||
android:key="accessibility_control_timeout_2mins"
|
||||
android:title="@string/accessibility_timeout_2mins"
|
||||
android:persistent="false" />
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -71,6 +71,14 @@
|
||||
<SwitchPreference
|
||||
android:key="toggle_disable_animations"
|
||||
android:title="@string/accessibility_disable_animations" />
|
||||
|
||||
<Preference
|
||||
android:fragment="com.android.settings.accessibility.AccessibilityContentTimeoutPreferenceFragment"
|
||||
android:key="accessibility_content_timeout_preference_fragment"
|
||||
android:title="@string/accessibility_accessibility_content_timeout_preference_title"
|
||||
android:icon="@drawable/ic_accessibility_generic"
|
||||
android:persistent="false" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
@@ -100,6 +108,13 @@
|
||||
android:entryValues="@array/long_press_timeout_selector_values"
|
||||
android:persistent="false"/>
|
||||
|
||||
<Preference
|
||||
android:fragment="com.android.settings.accessibility.AccessibilityControlTimeoutPreferenceFragment"
|
||||
android:key="accessibility_control_timeout_preference_fragment"
|
||||
android:title="@string/accessibility_accessibility_control_timeout_preference_title"
|
||||
android:icon="@drawable/ic_accessibility_generic"
|
||||
android:persistent="false" />
|
||||
|
||||
<Preference
|
||||
android:fragment="com.android.settings.accessibility.VibrationSettings"
|
||||
android:key="vibration_preference_screen"
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
android:key="header_view"
|
||||
android:layout="@layout/settings_entity_header"
|
||||
android:selectable="false"
|
||||
android:order="-10000" />
|
||||
android:order="-10000"
|
||||
settings:allowDividerBelow="true"/>
|
||||
|
||||
<com.android.settings.applications.LayoutPreference
|
||||
android:key="instant_app_buttons"
|
||||
@@ -40,7 +41,8 @@
|
||||
<Preference
|
||||
android:key="notification_settings"
|
||||
android:title="@string/notifications_label"
|
||||
settings:controller="com.android.settings.applications.appinfo.AppNotificationPreferenceController" />
|
||||
settings:controller="com.android.settings.applications.appinfo.AppNotificationPreferenceController"
|
||||
settings:allowDividerAbove="true"/>
|
||||
|
||||
<com.android.settings.widget.FixedLineSummaryPreference
|
||||
android:key="permission_settings"
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
-->
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/device_details_title">
|
||||
|
||||
<com.android.settings.applications.LayoutPreference
|
||||
android:key="bluetooth_device_header"
|
||||
android:layout="@layout/settings_entity_header"
|
||||
android:selectable="false"/>
|
||||
android:selectable="false"
|
||||
settings:allowDividerBelow="true"/>
|
||||
|
||||
<com.android.settings.widget.ActionButtonPreference
|
||||
android:key="action_buttons" />
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
android:key="connection_header"
|
||||
android:layout="@layout/settings_entity_header"
|
||||
android:selectable="false"
|
||||
android:order="-10000"/>
|
||||
android:order="-10000"
|
||||
settings:allowDividerBelow="true"/>
|
||||
|
||||
<!-- Buttons -->
|
||||
<com.android.settings.widget.ActionButtonPreference
|
||||
|
||||
21
res/xml/zen_mode_bypassing_apps.xml
Normal file
21
res/xml/zen_mode_bypassing_apps.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:key="zen_mode_bypassing_apps_screen"
|
||||
android:title="@string/zen_mode_bypassing_apps_title" />
|
||||
@@ -20,50 +20,55 @@
|
||||
android:key="zen_mode_sound_vibration_settings_page"
|
||||
android:title="@string/zen_category_exceptions" >
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/zen_mode_settings_category"
|
||||
android:key="zen_mode_settings_category_sound_vibration">
|
||||
<PreferenceCategory
|
||||
android:title="@string/zen_mode_settings_category"
|
||||
android:key="zen_mode_settings_category_sound_vibration">
|
||||
|
||||
<!-- Calls -->
|
||||
<Preference
|
||||
android:key="zen_mode_calls_settings"
|
||||
android:title="@string/zen_mode_calls_title"
|
||||
android:fragment="com.android.settings.notification.ZenModeCallsSettings" />
|
||||
<!-- Calls -->
|
||||
<Preference
|
||||
android:key="zen_mode_calls_settings"
|
||||
android:title="@string/zen_mode_calls_title"
|
||||
android:fragment="com.android.settings.notification.ZenModeCallsSettings" />
|
||||
|
||||
<!-- Messages -->
|
||||
<Preference
|
||||
android:key="zen_mode_messages_settings"
|
||||
android:title="@string/zen_mode_messages_title"
|
||||
android:fragment="com.android.settings.notification.ZenModeMessagesSettings" />
|
||||
<!-- Messages -->
|
||||
<Preference
|
||||
android:key="zen_mode_messages_settings"
|
||||
android:title="@string/zen_mode_messages_title"
|
||||
android:fragment="com.android.settings.notification.ZenModeMessagesSettings" />
|
||||
|
||||
<!-- Alarms -->
|
||||
<SwitchPreference
|
||||
android:key="zen_mode_alarms"
|
||||
android:title="@string/zen_mode_alarms"/>
|
||||
<!-- Alarms -->
|
||||
<SwitchPreference
|
||||
android:key="zen_mode_alarms"
|
||||
android:title="@string/zen_mode_alarms"/>
|
||||
|
||||
<!-- Media -->
|
||||
<SwitchPreference
|
||||
android:key="zen_mode_media"
|
||||
android:title="@string/zen_mode_media"/>
|
||||
<!-- Media -->
|
||||
<SwitchPreference
|
||||
android:key="zen_mode_media"
|
||||
android:title="@string/zen_mode_media"/>
|
||||
|
||||
<!-- System -->
|
||||
<SwitchPreference
|
||||
android:key="zen_mode_system"
|
||||
android:title="@string/zen_mode_system"/>
|
||||
<!-- System -->
|
||||
<SwitchPreference
|
||||
android:key="zen_mode_system"
|
||||
android:title="@string/zen_mode_system"/>
|
||||
|
||||
<!-- Reminders -->
|
||||
<SwitchPreference
|
||||
android:key="zen_mode_reminders"
|
||||
android:title="@string/zen_mode_reminders"/>
|
||||
<!-- Reminders -->
|
||||
<SwitchPreference
|
||||
android:key="zen_mode_reminders"
|
||||
android:title="@string/zen_mode_reminders"/>
|
||||
|
||||
<!-- Events -->
|
||||
<SwitchPreference
|
||||
android:key="zen_mode_events"
|
||||
android:title="@string/zen_mode_events"/>
|
||||
<!-- Events -->
|
||||
<SwitchPreference
|
||||
android:key="zen_mode_events"
|
||||
android:title="@string/zen_mode_events"/>
|
||||
|
||||
<!-- TODO: beverlyt, add "Allow apps to override" -->
|
||||
</PreferenceCategory>
|
||||
<!-- Apps overriding DND -->
|
||||
<Preference
|
||||
android:key="zen_mode_bypassing_apps"
|
||||
android:title="@string/zen_mode_bypassing_apps"
|
||||
android:fragment="com.android.settings.notification.ZenModeBypassingAppsSettings"/>
|
||||
|
||||
<com.android.settingslib.widget.FooterPreference/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<com.android.settingslib.widget.FooterPreference/>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -128,6 +128,9 @@ public class SettingsInitialize extends BroadcastReceiver {
|
||||
final List<ShortcutInfo> pinnedShortcuts = shortcutManager.getPinnedShortcuts();
|
||||
final List<ShortcutInfo> updates = new ArrayList<>();
|
||||
for (ShortcutInfo info : pinnedShortcuts) {
|
||||
if (info.isImmutable()) {
|
||||
continue;
|
||||
}
|
||||
final Intent shortcutIntent = info.getIntent();
|
||||
shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
final ShortcutInfo updatedInfo = new ShortcutInfo.Builder(context, info.getId())
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@SearchIndexable
|
||||
public final class AccessibilityContentTimeoutPreferenceFragment extends DashboardFragment
|
||||
implements AccessibilityTimeoutController.OnChangeListener {
|
||||
|
||||
static final String TAG = "AccessibilityContentTimeoutPreferenceFragment";
|
||||
private static final List<AbstractPreferenceController> sControllers = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(Preference preference) {
|
||||
for (AbstractPreferenceController controller : sControllers) {
|
||||
controller.updateState(preference);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
for (AbstractPreferenceController controller :
|
||||
buildPreferenceControllers(getPrefContext(), getSettingsLifecycle())) {
|
||||
((AccessibilityTimeoutController)controller).setOnChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
for (AbstractPreferenceController controller :
|
||||
buildPreferenceControllers(getPrefContext(), getSettingsLifecycle())) {
|
||||
((AccessibilityTimeoutController)controller).setOnChangeListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.ACCESSIBILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.accessibility_content_timeout_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context, getSettingsLifecycle());
|
||||
}
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
||||
Lifecycle lifecycle) {
|
||||
if (sControllers.size() == 0) {
|
||||
Resources resources = context.getResources();
|
||||
|
||||
String[] timeoutKeys = resources.getStringArray(
|
||||
R.array.accessibility_timeout_content_selector_keys);
|
||||
|
||||
for (int i=0; i < timeoutKeys.length; i++) {
|
||||
sControllers.add(new AccessibilityTimeoutController(
|
||||
context, lifecycle, timeoutKeys[i], TAG));
|
||||
}
|
||||
}
|
||||
return sControllers;
|
||||
}
|
||||
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
boolean enabled) {
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.accessibility_content_timeout_settings;
|
||||
return Arrays.asList(sir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
final List<String> keys = super.getNonIndexableKeys(context);
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> createPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@SearchIndexable
|
||||
public final class AccessibilityControlTimeoutPreferenceFragment extends DashboardFragment
|
||||
implements AccessibilityTimeoutController.OnChangeListener {
|
||||
|
||||
static final String TAG = "AccessibilityControlTimeoutPreferenceFragment";
|
||||
private static final List<AbstractPreferenceController> sControllers = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(Preference preference) {
|
||||
for (AbstractPreferenceController controller : sControllers) {
|
||||
controller.updateState(preference);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
for (AbstractPreferenceController controller :
|
||||
buildPreferenceControllers(getPrefContext(), getSettingsLifecycle())) {
|
||||
((AccessibilityTimeoutController)controller).setOnChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
for (AbstractPreferenceController controller :
|
||||
buildPreferenceControllers(getPrefContext(), getSettingsLifecycle())) {
|
||||
((AccessibilityTimeoutController)controller).setOnChangeListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.ACCESSIBILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.accessibility_control_timeout_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context, getSettingsLifecycle());
|
||||
}
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
||||
Lifecycle lifecycle) {
|
||||
if (sControllers.size() == 0) {
|
||||
Resources resources = context.getResources();
|
||||
|
||||
String[] timeoutKeys = resources.getStringArray(
|
||||
R.array.accessibility_timeout_control_selector_keys);
|
||||
|
||||
for (int i=0; i < timeoutKeys.length; i++) {
|
||||
sControllers.add(new AccessibilityTimeoutController(
|
||||
context, lifecycle, timeoutKeys[i], TAG));
|
||||
}
|
||||
}
|
||||
return sControllers;
|
||||
}
|
||||
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
boolean enabled) {
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.accessibility_control_timeout_settings;
|
||||
return Arrays.asList(sir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
final List<String> keys = super.getNonIndexableKeys(context);
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> createPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.widget.RadioButtonPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.lang.Integer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AccessibilityTimeoutController extends AbstractPreferenceController implements
|
||||
LifecycleObserver, RadioButtonPreference.OnClickListener, PreferenceControllerMixin {
|
||||
|
||||
// pair the preference key and timeout value
|
||||
private final Map<String, Integer> mAccessibilityTimeoutKeyToValueMap = new HashMap<>();
|
||||
|
||||
private final String mPreferenceKey;
|
||||
private final String mfragmentTag;
|
||||
private final ContentResolver mContentResolver;
|
||||
private final Resources mResources;
|
||||
private OnChangeListener mOnChangeListener;
|
||||
private RadioButtonPreference mPreference;
|
||||
private int mAccessibilityUiTimeoutValue;
|
||||
|
||||
public AccessibilityTimeoutController(Context context, Lifecycle lifecycle,
|
||||
String preferenceKey, String fragmentTag) {
|
||||
super(context);
|
||||
|
||||
mContentResolver = context.getContentResolver();
|
||||
mResources = context.getResources();
|
||||
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
mPreferenceKey = preferenceKey;
|
||||
mfragmentTag = fragmentTag;
|
||||
}
|
||||
|
||||
public void setOnChangeListener(OnChangeListener listener) {
|
||||
mOnChangeListener = listener;
|
||||
}
|
||||
|
||||
private Map<String, Integer> getTimeoutValueToKeyMap() {
|
||||
if (mAccessibilityTimeoutKeyToValueMap.size() == 0) {
|
||||
|
||||
String[] timeoutKeys = null;
|
||||
if (mfragmentTag.equals(AccessibilityContentTimeoutPreferenceFragment.TAG)) {
|
||||
timeoutKeys = mResources.getStringArray(
|
||||
R.array.accessibility_timeout_content_selector_keys);
|
||||
} else if (mfragmentTag.equals(AccessibilityControlTimeoutPreferenceFragment.TAG)) {
|
||||
timeoutKeys = mResources.getStringArray(
|
||||
R.array.accessibility_timeout_control_selector_keys);
|
||||
}
|
||||
|
||||
int[] timeoutValues = mResources.getIntArray(
|
||||
R.array.accessibility_timeout_selector_values);
|
||||
|
||||
final int timeoutValueCount = timeoutValues.length;
|
||||
for (int i = 0; i < timeoutValueCount; i++) {
|
||||
mAccessibilityTimeoutKeyToValueMap.put(timeoutKeys[i], timeoutValues[i]);
|
||||
}
|
||||
}
|
||||
return mAccessibilityTimeoutKeyToValueMap;
|
||||
}
|
||||
|
||||
private void putSecureString(String name, String value) {
|
||||
Settings.Secure.putString(mContentResolver, name, value);
|
||||
}
|
||||
|
||||
private void handlePreferenceChange(String value) {
|
||||
if (mfragmentTag.equals(AccessibilityContentTimeoutPreferenceFragment.TAG)) {
|
||||
putSecureString(Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, value);
|
||||
} else if (mfragmentTag.equals(AccessibilityControlTimeoutPreferenceFragment.TAG)) {
|
||||
putSecureString(Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return mPreferenceKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
|
||||
mPreference = (RadioButtonPreference)
|
||||
screen.findPreference(getPreferenceKey());
|
||||
mPreference.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRadioButtonClicked(RadioButtonPreference preference) {
|
||||
int value = getTimeoutValueToKeyMap().get(mPreferenceKey);
|
||||
handlePreferenceChange(String.valueOf(value));
|
||||
if (mOnChangeListener != null) {
|
||||
mOnChangeListener.onCheckedChanged(mPreference);
|
||||
}
|
||||
}
|
||||
|
||||
protected void getAccessibilityUiValue() {
|
||||
String timeoutValue = null;
|
||||
if (mfragmentTag.equals(AccessibilityContentTimeoutPreferenceFragment.TAG)) {
|
||||
timeoutValue = Settings.Secure.getString(mContentResolver,
|
||||
Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS);
|
||||
} else if (mfragmentTag.equals(AccessibilityControlTimeoutPreferenceFragment.TAG)) {
|
||||
timeoutValue = Settings.Secure.getString(mContentResolver,
|
||||
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS);
|
||||
}
|
||||
mAccessibilityUiTimeoutValue = timeoutValue == null? 0: Integer.parseInt(timeoutValue);
|
||||
}
|
||||
|
||||
protected void updatePreferenceCheckedState(int value) {
|
||||
if (mAccessibilityUiTimeoutValue == value) {
|
||||
mPreference.setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
|
||||
getAccessibilityUiValue();
|
||||
|
||||
// reset RadioButton
|
||||
mPreference.setChecked(false);
|
||||
int preferenceValue = getTimeoutValueToKeyMap().get(mPreference.getKey());
|
||||
updatePreferenceCheckedState(preferenceValue);
|
||||
}
|
||||
|
||||
public static interface OnChangeListener {
|
||||
void onCheckedChanged(Preference preference);
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,6 @@ import java.util.Set;
|
||||
public class AppPermissionsPreferenceController extends BasePreferenceController {
|
||||
|
||||
private static final String TAG = "AppPermissionPrefCtrl";
|
||||
private static final String KEY_APP_PERMISSION_GROUPS = "manage_perms";
|
||||
private static final String[] PERMISSION_GROUPS = new String[]{
|
||||
"android.permission-group.LOCATION",
|
||||
"android.permission-group.MICROPHONE",
|
||||
@@ -46,8 +45,8 @@ public class AppPermissionsPreferenceController extends BasePreferenceController
|
||||
|
||||
private final PackageManager mPackageManager;
|
||||
|
||||
public AppPermissionsPreferenceController(Context context) {
|
||||
super(context, KEY_APP_PERMISSION_GROUPS);
|
||||
public AppPermissionsPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mPackageManager = context.getPackageManager();
|
||||
}
|
||||
|
||||
|
||||
@@ -167,10 +167,7 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
.setComputingString(R.string.computing_size)
|
||||
.setErrorString(R.string.invalid_size_value)
|
||||
.build();
|
||||
mButtonsPref = ((ActionButtonPreference) findPreference(KEY_HEADER_BUTTONS))
|
||||
.setButton1Positive(false)
|
||||
.setButton2Positive(false);
|
||||
|
||||
mButtonsPref = ((ActionButtonPreference) findPreference(KEY_HEADER_BUTTONS));
|
||||
mStorageUsed = findPreference(KEY_STORAGE_USED);
|
||||
mChangeStorageButton = (Button) ((LayoutPreference) findPreference(KEY_CHANGE_STORAGE))
|
||||
.findViewById(R.id.button);
|
||||
@@ -178,7 +175,9 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
mChangeStorageButton.setOnClickListener(this);
|
||||
|
||||
// Cache section
|
||||
mButtonsPref.setButton2Text(R.string.clear_cache_btn_text);
|
||||
mButtonsPref
|
||||
.setButton2Text(R.string.clear_cache_btn_text)
|
||||
.setButton2Icon(R.drawable.ic_settings_delete);
|
||||
|
||||
// URI permissions section
|
||||
mUri = (PreferenceCategory) findPreference(KEY_URI_CATEGORY);
|
||||
@@ -304,16 +303,20 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
|| !isManageSpaceActivityAvailable) {
|
||||
mButtonsPref
|
||||
.setButton1Text(R.string.clear_user_data_text)
|
||||
.setButton1Icon(R.drawable.ic_settings_delete)
|
||||
.setButton1Enabled(false);
|
||||
mCanClearData = false;
|
||||
} else {
|
||||
if (appHasSpaceManagementUI) {
|
||||
mButtonsPref.setButton1Text(R.string.manage_space_text);
|
||||
} else {
|
||||
mButtonsPref.setButton1Text(R.string.clear_user_data_text);
|
||||
mButtonsPref
|
||||
.setButton1Text(R.string.clear_user_data_text)
|
||||
.setButton1Icon(R.drawable.ic_settings_delete);
|
||||
}
|
||||
mButtonsPref
|
||||
.setButton1Text(R.string.clear_user_data_text)
|
||||
.setButton1Icon(R.drawable.ic_settings_delete)
|
||||
.setButton1OnClickListener(v -> handleClearDataClick());
|
||||
}
|
||||
|
||||
@@ -384,7 +387,9 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
private void processClearMsg(Message msg) {
|
||||
int result = msg.arg1;
|
||||
String packageName = mAppEntry.info.packageName;
|
||||
mButtonsPref.setButton1Text(R.string.clear_user_data_text);
|
||||
mButtonsPref
|
||||
.setButton1Text(R.string.clear_user_data_text)
|
||||
.setButton1Icon(R.drawable.ic_settings_delete);
|
||||
if (result == OP_SUCCESSFUL) {
|
||||
Log.i(TAG, "Cleared user data for package : " + packageName);
|
||||
updateSize();
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import com.android.internal.telephony.SmsApplication;
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -138,6 +139,9 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide
|
||||
if (defaultSms != null) {
|
||||
keepEnabledPackages.add(defaultSms.getPackageName());
|
||||
}
|
||||
// Keep Settings intelligence enabled, otherwise search feature will be disabled.
|
||||
keepEnabledPackages.add(
|
||||
mContext.getString(R.string.config_settingsintelligence_package_name));
|
||||
return keepEnabledPackages;
|
||||
}
|
||||
|
||||
|
||||
@@ -167,11 +167,11 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp
|
||||
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())
|
||||
.setButton1Positive(false)
|
||||
.setButton2Positive(false)
|
||||
.setButton2Enabled(false);
|
||||
}
|
||||
}
|
||||
@@ -547,16 +547,16 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp
|
||||
if (mHomePackages.contains(mAppEntry.info.packageName)
|
||||
|| isSystemPackage(mActivity.getResources(), mPm, mPackageInfo)) {
|
||||
// Disable button for core system applications.
|
||||
mButtonsPref.setButton1Text(R.string.disable_text)
|
||||
.setButton1Positive(false);
|
||||
mButtonsPref.setButton1Text(R.string.uninstall_text)
|
||||
.setButton1Icon(R.drawable.ic_settings_delete);
|
||||
} else if (mAppEntry.info.enabled && !isDisabledUntilUsed()) {
|
||||
mButtonsPref.setButton1Text(R.string.disable_text)
|
||||
.setButton1Positive(false);
|
||||
mButtonsPref.setButton1Text(R.string.uninstall_text)
|
||||
.setButton1Icon(R.drawable.ic_settings_delete);
|
||||
disableable = !mApplicationFeatureProvider.getKeepEnabledPackages()
|
||||
.contains(mAppEntry.info.packageName);
|
||||
} else {
|
||||
mButtonsPref.setButton1Text(R.string.enable_text)
|
||||
.setButton1Positive(true);
|
||||
mButtonsPref.setButton1Text(R.string.install_text)
|
||||
.setButton1Icon(R.drawable.ic_settings_install);
|
||||
disableable = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
|
||||
// Result code identifiers
|
||||
@VisibleForTesting
|
||||
static final int REQUEST_UNINSTALL = 0;
|
||||
private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
|
||||
private static final int REQUEST_REMOVE_DEVICE_ADMIN = 5;
|
||||
|
||||
static final int SUB_INFO_FRAGMENT = 1;
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
|
||||
|
||||
if (shouldLaunchConfirmLock()) {
|
||||
launchConfirmLock(R.string.security_settings_face_preference_title,
|
||||
Utils.getFingerprintManagerOrNull(this).preEnroll());
|
||||
Utils.getFaceManagerOrNull(this).generateChallenge());
|
||||
mShouldFinishOnStop = false;
|
||||
} else {
|
||||
startEnrollment();
|
||||
|
||||
@@ -53,8 +53,8 @@ public class BluetoothDetailsButtonsController extends BluetoothDetailsControlle
|
||||
protected void init(PreferenceScreen screen) {
|
||||
mActionButtons = ((ActionButtonPreference) screen.findPreference(getPreferenceKey()))
|
||||
.setButton1Text(R.string.forget)
|
||||
.setButton1Icon(R.drawable.ic_settings_delete)
|
||||
.setButton1OnClickListener((view) -> onForgetButtonPressed())
|
||||
.setButton1Positive(false)
|
||||
.setButton1Enabled(true);
|
||||
}
|
||||
|
||||
@@ -68,17 +68,17 @@ public class BluetoothDetailsButtonsController extends BluetoothDetailsControlle
|
||||
if (!mConnectButtonInitialized || !previouslyConnected) {
|
||||
mActionButtons
|
||||
.setButton2Text(R.string.bluetooth_device_context_disconnect)
|
||||
.setButton2OnClickListener(view -> mCachedDevice.disconnect())
|
||||
.setButton2Positive(false);
|
||||
.setButton2Icon(R.drawable.ic_settings_close)
|
||||
.setButton2OnClickListener(view -> mCachedDevice.disconnect());
|
||||
mConnectButtonInitialized = true;
|
||||
}
|
||||
} else {
|
||||
if (!mConnectButtonInitialized || previouslyConnected) {
|
||||
mActionButtons
|
||||
.setButton2Text(R.string.bluetooth_device_context_connect)
|
||||
// TODO (b/119646923) Icon is not ready.
|
||||
.setButton2OnClickListener(
|
||||
view -> mCachedDevice.connect(true /* connectAllProfiles */))
|
||||
.setButton2Positive(true);
|
||||
view -> mCachedDevice.connect(true /* connectAllProfiles */));
|
||||
mConnectButtonInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.android.settings.deviceinfo.aboutphone;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.deviceinfo.DeviceModelPreferenceController;
|
||||
import com.android.settings.deviceinfo.DeviceNamePreferenceController;
|
||||
|
||||
public class TopLevelAboutDevicePreferenceController extends BasePreferenceController {
|
||||
|
||||
@@ -34,6 +34,8 @@ public class TopLevelAboutDevicePreferenceController extends BasePreferenceContr
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return DeviceModelPreferenceController.getDeviceModel();
|
||||
final DeviceNamePreferenceController deviceNamePreferenceController =
|
||||
new DeviceNamePreferenceController(mContext);
|
||||
return deviceNamePreferenceController.getSummary();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class ContextualCard {
|
||||
private final boolean mIsHalfWidth;
|
||||
private final Drawable mIconDrawable;
|
||||
|
||||
String getName() {
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,10 +62,12 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
|
||||
private static final int[] SETTINGS_CARDS =
|
||||
{ContextualCard.CardType.CONDITIONAL, ContextualCard.CardType.LEGACY_SUGGESTION};
|
||||
|
||||
@VisibleForTesting
|
||||
final List<ContextualCard> mContextualCards;
|
||||
|
||||
private final Context mContext;
|
||||
private final ControllerRendererPool mControllerRendererPool;
|
||||
private final Lifecycle mLifecycle;
|
||||
private final List<ContextualCard> mContextualCards;
|
||||
private final List<LifecycleObserver> mLifecycleObservers;
|
||||
|
||||
private ContextualCardUpdateListener mListener;
|
||||
@@ -122,10 +124,23 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
|
||||
public void onContextualCardUpdated(Map<Integer, List<ContextualCard>> updateList) {
|
||||
final Set<Integer> cardTypes = updateList.keySet();
|
||||
//Remove the existing data that matches the certain cardType before inserting new data.
|
||||
final List<ContextualCard> cardsToKeep = mContextualCards
|
||||
.stream()
|
||||
.filter(card -> !cardTypes.contains(card.getCardType()))
|
||||
.collect(Collectors.toList());
|
||||
List<ContextualCard> cardsToKeep;
|
||||
|
||||
// We are not sure how many card types will be in the database, so when the list coming
|
||||
// from the database is empty (e.g. no eligible cards/cards are dismissed), we cannot
|
||||
// assign a specific card type for its map which is sending here. Thus, we assume that
|
||||
// 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()) {
|
||||
cardsToKeep = mContextualCards.stream()
|
||||
.filter(card -> card.getCardType() == ContextualCard.CardType.CONDITIONAL)
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
cardsToKeep = mContextualCards.stream()
|
||||
.filter(card -> !cardTypes.contains(card.getCardType()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
final List<ContextualCard> allCards = new ArrayList<>();
|
||||
allCards.addAll(cardsToKeep);
|
||||
allCards.addAll(
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
|
||||
|
||||
import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice;
|
||||
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;
|
||||
@@ -54,10 +55,17 @@ public class SettingsContextualCardProvider extends ContextualCardProvider {
|
||||
.setCardName(ConnectedDeviceSlice.PATH_CONNECTED_DEVICE)
|
||||
.setCardCategory(ContextualCard.Category.IMPORTANT)
|
||||
.build();
|
||||
final ContextualCard lowStorageCard =
|
||||
ContextualCard.newBuilder()
|
||||
.setSliceUri(LowStorageSlice.LOW_STORAGE_URI.toString())
|
||||
.setCardName(LowStorageSlice.PATH_LOW_STORAGE)
|
||||
.setCardCategory(ContextualCard.Category.IMPORTANT)
|
||||
.build();
|
||||
final ContextualCardList cards = ContextualCardList.newBuilder()
|
||||
.addCard(wifiCard)
|
||||
.addCard(batteryInfoCard)
|
||||
.addCard(connectedDeviceCard)
|
||||
.addCard(lowStorageCard)
|
||||
.build();
|
||||
|
||||
return cards;
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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.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;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.ListBuilder.RowBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.deviceinfo.StorageSettings;
|
||||
import com.android.settings.slices.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;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
public class LowStorageSlice implements CustomSliceable {
|
||||
|
||||
/**
|
||||
* The path denotes the unique name of Low storage Slice.
|
||||
*/
|
||||
public static final String PATH_LOW_STORAGE = "low_storage";
|
||||
|
||||
/**
|
||||
* Backing Uri for Low storage Slice.
|
||||
*/
|
||||
public static final Uri LOW_STORAGE_URI = new Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
|
||||
.appendPath(PATH_LOW_STORAGE)
|
||||
.build();
|
||||
|
||||
private static final String TAG = "LowStorageSlice";
|
||||
|
||||
/**
|
||||
* If user used >= 85% storage.
|
||||
*/
|
||||
private static final double LOW_STORAGE_THRESHOLD = 0.85;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public LowStorageSlice(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Low storage Slice bound to {@link #LOW_STORAGE_URI}
|
||||
*/
|
||||
@Override
|
||||
public Slice getSlice() {
|
||||
// Get current 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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
/**
|
||||
* 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))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getUri() {
|
||||
return LOW_STORAGE_URI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotifyChange(Intent intent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
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,
|
||||
screenTitle,
|
||||
MetricsProto.MetricsEvent.SLICE)
|
||||
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
|
||||
.setData(contentUri);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
import android.app.INotificationManager;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.usage.IUsageStatsManager;
|
||||
import android.app.usage.UsageEvents;
|
||||
import android.content.Context;
|
||||
@@ -38,8 +39,6 @@ import android.text.format.DateUtils;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
@@ -49,6 +48,8 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
public class NotificationBackend {
|
||||
private static final String TAG = "NotificationBackend";
|
||||
|
||||
@@ -208,6 +209,19 @@ public class NotificationBackend {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all notification channels associated with the package and uid that will bypass DND
|
||||
*/
|
||||
public ParceledListSlice<NotificationChannel> getNotificationChannelsBypassingDnd(String pkg,
|
||||
int uid) {
|
||||
try {
|
||||
return sINM.getNotificationChannelsBypassingDnd(pkg, uid);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return ParceledListSlice.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateChannel(String pkg, int uid, NotificationChannel channel) {
|
||||
try {
|
||||
sINM.updateNotificationChannelForPackage(pkg, uid, channel);
|
||||
@@ -260,6 +274,15 @@ public class NotificationBackend {
|
||||
}
|
||||
}
|
||||
|
||||
public int getNumAppsBypassingDnd(int uid) {
|
||||
try {
|
||||
return sINM.getAppsBypassingDndCount(uid);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public List<NotifyingApp> getRecentApps() {
|
||||
try {
|
||||
return sINM.getRecentNotifyingAppsForUser(UserHandle.myUserId()).getList();
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.NotificationChannel;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.widget.apppreference.AppPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.text.BidiFormatter;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
/**
|
||||
* Adds a preference to the PreferenceScreen for each notification channel that can bypass DND.
|
||||
*/
|
||||
public class ZenModeAllBypassingAppsPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private final String KEY = "zen_mode_bypassing_apps_category";
|
||||
|
||||
@VisibleForTesting ApplicationsState mApplicationsState;
|
||||
@VisibleForTesting PreferenceScreen mPreferenceScreen;
|
||||
@VisibleForTesting Context mPrefContext;
|
||||
|
||||
private ApplicationsState.Session mAppSession;
|
||||
private NotificationBackend mNotificationBackend = new NotificationBackend();
|
||||
private Fragment mHostFragment;
|
||||
|
||||
public ZenModeAllBypassingAppsPreferenceController(Context context, Application app,
|
||||
Fragment host) {
|
||||
|
||||
this(context, app == null ? null : ApplicationsState.getInstance(app), host);
|
||||
}
|
||||
|
||||
private ZenModeAllBypassingAppsPreferenceController(Context context, ApplicationsState appState,
|
||||
Fragment host) {
|
||||
super(context);
|
||||
mApplicationsState = appState;
|
||||
mHostFragment = host;
|
||||
|
||||
if (mApplicationsState != null && host != null) {
|
||||
mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, host.getLifecycle());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
mPreferenceScreen = screen;
|
||||
mPrefContext = mPreferenceScreen.getContext();
|
||||
updateNotificationChannelList();
|
||||
super.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to trigger the notification channels list to refresh.
|
||||
*/
|
||||
public void updateNotificationChannelList() {
|
||||
if (mAppSession == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationsState.AppFilter filter = ApplicationsState.FILTER_ALL_ENABLED;
|
||||
List<ApplicationsState.AppEntry> apps = mAppSession.rebuild(filter,
|
||||
ApplicationsState.ALPHA_COMPARATOR);
|
||||
if (apps != null) {
|
||||
updateNotificationChannelList(apps);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updateNotificationChannelList(List<ApplicationsState.AppEntry> apps) {
|
||||
if (mPreferenceScreen == null || apps == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Preference> channelsBypassingDnd = new ArrayList<>();
|
||||
for (ApplicationsState.AppEntry entry : apps) {
|
||||
String pkg = entry.info.packageName;
|
||||
mApplicationsState.ensureIcon(entry);
|
||||
for (NotificationChannel channel : mNotificationBackend
|
||||
.getNotificationChannelsBypassingDnd(pkg, entry.info.uid).getList()) {
|
||||
Preference pref = new AppPreference(mPrefContext);
|
||||
pref.setKey(pkg + "|" + channel.getId());
|
||||
pref.setTitle(BidiFormatter.getInstance().unicodeWrap(entry.label));
|
||||
pref.setIcon(entry.icon);
|
||||
pref.setSummary(BidiFormatter.getInstance().unicodeWrap(channel.getName()));
|
||||
|
||||
pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(AppInfoBase.ARG_PACKAGE_NAME, entry.info.packageName);
|
||||
args.putInt(AppInfoBase.ARG_PACKAGE_UID, entry.info.uid);
|
||||
args.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
|
||||
new SubSettingLauncher(mContext)
|
||||
.setDestination(ChannelNotificationSettings.class.getName())
|
||||
.setArguments(args)
|
||||
.setTitleRes(R.string.notification_channel_title)
|
||||
.setResultListener(mHostFragment, 0)
|
||||
.setSourceMetricsCategory(
|
||||
MetricsEvent.NOTIFICATION_ZEN_MODE_OVERRIDING_APP)
|
||||
.launch();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
channelsBypassingDnd.add(pref);
|
||||
}
|
||||
|
||||
mPreferenceScreen.removeAll();
|
||||
if (channelsBypassingDnd.size() > 0) {
|
||||
for (Preference prefToAdd : channelsBypassingDnd) {
|
||||
mPreferenceScreen.addPreference(prefToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final ApplicationsState.Callbacks mAppSessionCallbacks =
|
||||
new ApplicationsState.Callbacks() {
|
||||
|
||||
@Override
|
||||
public void onRunningStateChanged(boolean running) {
|
||||
updateNotificationChannelList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageListChanged() {
|
||||
updateNotificationChannelList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps) {
|
||||
updateNotificationChannelList(apps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageIconChanged() {
|
||||
updateNotificationChannelList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageSizeChanged(String packageName) {
|
||||
updateNotificationChannelList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllSizesComputed() { }
|
||||
|
||||
@Override
|
||||
public void onLauncherInfoChanged() {
|
||||
updateNotificationChannelList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadEntriesCompleted() {
|
||||
updateNotificationChannelList();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
public class ZenModeBypassingAppsPreferenceController extends AbstractZenModePreferenceController {
|
||||
|
||||
protected static final String KEY = "zen_mode_bypassing_apps";
|
||||
private NotificationBackend mNotificationBackend = new NotificationBackend();
|
||||
|
||||
public ZenModeBypassingAppsPreferenceController(Context context, Lifecycle lifecycle) {
|
||||
super(context, KEY, lifecycle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mNotificationBackend.getNumAppsBypassingDnd(UserHandle.getCallingUserId()) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
final int channelsBypassing =
|
||||
mNotificationBackend.getNumAppsBypassingDnd(UserHandle.getCallingUserId());
|
||||
return mContext.getResources().getQuantityString(R.plurals.zen_mode_bypassing_apps_subtext,
|
||||
channelsBypassing, channelsBypassing);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
@SearchIndexable
|
||||
public class ZenModeBypassingAppsSettings extends ZenModeSettingsBase implements
|
||||
Indexable {
|
||||
private final String TAG = "ZenBypassingApps";
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
final Activity activity = getActivity();
|
||||
final Application app;
|
||||
if (activity != null) {
|
||||
app = activity.getApplication();
|
||||
} else {
|
||||
app = null;
|
||||
}
|
||||
return buildPreferenceControllers(context, app, this);
|
||||
}
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
||||
Application app, Fragment host) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new ZenModeAllBypassingAppsPreferenceController(context, app, host));
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.zen_mode_bypassing_apps;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.NOTIFICATION_ZEN_MODE_OVERRIDING_APPS;
|
||||
}
|
||||
|
||||
/**
|
||||
* For Search.
|
||||
*/
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
boolean enabled) {
|
||||
final ArrayList<SearchIndexableResource> result = new ArrayList<>();
|
||||
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.zen_mode_bypassing_apps;
|
||||
result.add(sir);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> createPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context, null, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
@@ -55,6 +53,7 @@ public class ZenModeSoundVibrationSettings extends ZenModeSettingsBase implement
|
||||
controllers.add(new ZenModeEventsPreferenceController(context, lifecycle));
|
||||
controllers.add(new ZenModeBehaviorFooterPreferenceController(context, lifecycle,
|
||||
R.string.zen_sound_footer));
|
||||
controllers.add(new ZenModeBypassingAppsPreferenceController(context, lifecycle));
|
||||
return controllers;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,16 +28,16 @@ import android.icu.text.ListFormatter;
|
||||
import android.provider.Contacts;
|
||||
import android.provider.ContactsContract;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
public class ZenModeStarredContactsPreferenceController extends
|
||||
AbstractZenModePreferenceController implements Preference.OnPreferenceClickListener {
|
||||
|
||||
@@ -134,7 +134,6 @@ public class ZenModeStarredContactsPreferenceController extends
|
||||
@VisibleForTesting
|
||||
List<String> getStarredContacts(Cursor cursor) {
|
||||
List<String> starredContacts = new ArrayList<>();
|
||||
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
String contact = cursor.getString(0);
|
||||
@@ -147,7 +146,15 @@ public class ZenModeStarredContactsPreferenceController extends
|
||||
}
|
||||
|
||||
private List<String> getStarredContacts() {
|
||||
return getStarredContacts(queryData());
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = queryData();
|
||||
return getStarredContacts(cursor);
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Cursor queryData() {
|
||||
|
||||
@@ -23,8 +23,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.security.ShowPasswordPreferenceController;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -88,6 +89,11 @@ public interface SearchFeatureProvider {
|
||||
intent.setPackage(getSettingsIntelligencePkgName(activity));
|
||||
final Context context = activity.getApplicationContext();
|
||||
|
||||
if (activity.getPackageManager().queryIntentActivities(intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FeatureFactory.getFactory(context).getSlicesFeatureProvider()
|
||||
.indexSliceDataAsync(activity.getApplicationContext());
|
||||
FeatureFactory.getFactory(context).getMetricsFeatureProvider()
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.search.actionbar;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
@@ -80,6 +81,12 @@ public class SearchMenuController implements LifecycleObserver, OnCreateOptionsM
|
||||
searchItem.setOnMenuItemClickListener(target -> {
|
||||
final Intent intent = SearchFeatureProvider.SEARCH_UI_INTENT;
|
||||
intent.setPackage(SettingsIntelligencePkgName);
|
||||
|
||||
if (context.getPackageManager().queryIntentActivities(intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
FeatureFactory.getFactory(context).getMetricsFeatureProvider()
|
||||
.action(context, MetricsProto.MetricsEvent.ACTION_SEARCH_RESULTS);
|
||||
mHost.startActivityForResult(intent, 0 /* requestCode */);
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
|
||||
import com.android.settings.homepage.contextualcards.deviceinfo.DeviceInfoSlice;
|
||||
import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
|
||||
import com.android.settings.wifi.WifiSlice;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -105,5 +106,6 @@ public class CustomSliceManager {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,11 +171,9 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment
|
||||
|
||||
mActionButtons = ((ActionButtonPreference) findPreference(KEY_ACTION_BUTTONS))
|
||||
.setButton1Text(R.string.tts_play)
|
||||
.setButton1Positive(true)
|
||||
.setButton1OnClickListener(v -> speakSampleText())
|
||||
.setButton1Enabled(false)
|
||||
.setButton2Text(R.string.tts_reset)
|
||||
.setButton2Positive(false)
|
||||
.setButton2OnClickListener(v -> resetTts())
|
||||
.setButton1Enabled(true);
|
||||
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
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;
|
||||
@@ -30,6 +34,7 @@ import com.android.settings.R;
|
||||
|
||||
public class ActionButtonPreference extends Preference {
|
||||
|
||||
private final String TAG = "ActionButtonPreference";
|
||||
private final ButtonInfo mButton1Info = new ButtonInfo();
|
||||
private final ButtonInfo mButton2Info = new ButtonInfo();
|
||||
|
||||
@@ -62,12 +67,11 @@ public class ActionButtonPreference extends Preference {
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
holder.setDividerAllowedAbove(false);
|
||||
holder.setDividerAllowedBelow(false);
|
||||
mButton1Info.mPositiveButton = (Button) holder.findViewById(R.id.button1_positive);
|
||||
mButton1Info.mNegativeButton = (Button) holder.findViewById(R.id.button1_negative);
|
||||
mButton2Info.mPositiveButton = (Button) holder.findViewById(R.id.button2_positive);
|
||||
mButton2Info.mNegativeButton = (Button) holder.findViewById(R.id.button2_negative);
|
||||
holder.setDividerAllowedAbove(true);
|
||||
holder.setDividerAllowedBelow(true);
|
||||
|
||||
mButton1Info.mButton = (Button) holder.findViewById(R.id.button1);
|
||||
mButton2Info.mButton = (Button) holder.findViewById(R.id.button2);
|
||||
|
||||
mButton1Info.setUpButton();
|
||||
mButton2Info.setUpButton();
|
||||
@@ -82,6 +86,22 @@ public class ActionButtonPreference extends Preference {
|
||||
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;
|
||||
@@ -99,6 +119,22 @@ public class ActionButtonPreference extends Preference {
|
||||
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;
|
||||
@@ -123,65 +159,41 @@ public class ActionButtonPreference extends Preference {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ActionButtonPreference setButton1Positive(boolean isPositive) {
|
||||
if (isPositive != mButton1Info.mIsPositive) {
|
||||
mButton1Info.mIsPositive = isPositive;
|
||||
public ActionButtonPreference setButton1Visible(boolean isVisible) {
|
||||
if (isVisible != mButton1Info.mIsVisible) {
|
||||
mButton1Info.mIsVisible = isVisible;
|
||||
notifyChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ActionButtonPreference setButton2Positive(boolean isPositive) {
|
||||
if (isPositive != mButton2Info.mIsPositive) {
|
||||
mButton2Info.mIsPositive = isPositive;
|
||||
notifyChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public ActionButtonPreference setButton1Visible(boolean isPositive) {
|
||||
if (isPositive != mButton1Info.mIsVisible) {
|
||||
mButton1Info.mIsVisible = isPositive;
|
||||
notifyChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ActionButtonPreference setButton2Visible(boolean isPositive) {
|
||||
if (isPositive != mButton2Info.mIsVisible) {
|
||||
mButton2Info.mIsVisible = isPositive;
|
||||
public ActionButtonPreference setButton2Visible(boolean isVisible) {
|
||||
if (isVisible != mButton2Info.mIsVisible) {
|
||||
mButton2Info.mIsVisible = isVisible;
|
||||
notifyChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
static class ButtonInfo {
|
||||
private Button mPositiveButton;
|
||||
private Button mNegativeButton;
|
||||
private Button mButton;
|
||||
private CharSequence mText;
|
||||
private Drawable mIcon;
|
||||
private View.OnClickListener mListener;
|
||||
private boolean mIsPositive = true;
|
||||
private boolean mIsEnabled = true;
|
||||
private boolean mIsVisible = true;
|
||||
|
||||
void setUpButton() {
|
||||
setUpButton(mPositiveButton);
|
||||
setUpButton(mNegativeButton);
|
||||
if (!mIsVisible) {
|
||||
mPositiveButton.setVisibility(View.INVISIBLE);
|
||||
mNegativeButton.setVisibility(View.INVISIBLE);
|
||||
} else if (mIsPositive) {
|
||||
mPositiveButton.setVisibility(View.VISIBLE);
|
||||
mNegativeButton.setVisibility(View.INVISIBLE);
|
||||
mButton.setText(mText);
|
||||
mButton.setOnClickListener(mListener);
|
||||
mButton.setEnabled(mIsEnabled);
|
||||
mButton.setCompoundDrawablesWithIntrinsicBounds(
|
||||
null /* left */, mIcon /* top */, null /* right */, null /* bottom */);
|
||||
if (mIsVisible) {
|
||||
mButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mPositiveButton.setVisibility(View.INVISIBLE);
|
||||
mNegativeButton.setVisibility(View.VISIBLE);
|
||||
mButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpButton(Button button) {
|
||||
button.setText(mText);
|
||||
button.setOnClickListener(mListener);
|
||||
button.setEnabled(mIsEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,10 +278,9 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
|
||||
mButtonsPref = ((ActionButtonPreference) screen.findPreference(KEY_BUTTONS_PREF))
|
||||
.setButton1Text(R.string.forget)
|
||||
.setButton1Positive(false)
|
||||
.setButton1Icon(R.drawable.ic_settings_delete)
|
||||
.setButton1OnClickListener(view -> forgetNetwork())
|
||||
.setButton2Text(R.string.wifi_sign_in_button_text)
|
||||
.setButton2Positive(true)
|
||||
.setButton2OnClickListener(view -> signIntoNetwork());
|
||||
|
||||
mSignalStrengthPref =
|
||||
|
||||
136
src/com/android/settings/wifi/qrcode/QrDecorateView.java
Normal file
136
src/com/android/settings/wifi/qrcode/QrDecorateView.java
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi.qrcode;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
/**
|
||||
* Draws the lines at the corner of the inner frame.
|
||||
*/
|
||||
public class QrDecorateView extends View {
|
||||
private static final float CORNER_STROKE_WIDTH = 3f; // 3dp
|
||||
private static final float CORNER_LINE_LENGTH = 20f; // 20dp
|
||||
|
||||
final private Paint mPaint;
|
||||
private RectF mFrame;
|
||||
private boolean mFocused;
|
||||
|
||||
public QrDecorateView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public QrDecorateView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public QrDecorateView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, 0);
|
||||
}
|
||||
|
||||
public QrDecorateView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
final float strokeWidth = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
CORNER_STROKE_WIDTH,
|
||||
getResources().getDisplayMetrics()
|
||||
);
|
||||
mPaint = new Paint();
|
||||
mPaint.setStrokeWidth(strokeWidth);
|
||||
mFocused = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
calculateFramePos();
|
||||
final float cornerLineLength = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
CORNER_LINE_LENGTH,
|
||||
getResources().getDisplayMetrics()
|
||||
);
|
||||
mPaint.setColor(mFocused ? Color.GREEN : Color.WHITE);
|
||||
drawCorner(mFrame, cornerLineLength, canvas);
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
|
||||
private void drawCorner(RectF frame, float lineLength, Canvas canvas) {
|
||||
final float strokeWidth = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
CORNER_STROKE_WIDTH,
|
||||
getResources().getDisplayMetrics()
|
||||
);
|
||||
// Draw top-left corner.
|
||||
canvas.drawLine(
|
||||
frame.left - strokeWidth / 2,
|
||||
frame.top,
|
||||
frame.left + lineLength,
|
||||
frame.top,
|
||||
mPaint);
|
||||
canvas.drawLine(frame.left, frame.top, frame.left, frame.top + lineLength, mPaint);
|
||||
// Draw top-right corner.
|
||||
canvas.drawLine(
|
||||
frame.right + strokeWidth / 2,
|
||||
frame.top,
|
||||
frame.right - lineLength,
|
||||
frame.top,
|
||||
mPaint);
|
||||
canvas.drawLine(frame.right, frame.top, frame.right, frame.top + lineLength, mPaint);
|
||||
// Draw bottom-left corner.
|
||||
canvas.drawLine(
|
||||
frame.left - strokeWidth / 2,
|
||||
frame.bottom,
|
||||
frame.left + lineLength,
|
||||
frame.bottom,
|
||||
mPaint);
|
||||
canvas.drawLine(frame.left, frame.bottom, frame.left, frame.bottom - lineLength, mPaint);
|
||||
// Draw bottom-right corner.
|
||||
canvas.drawLine(
|
||||
frame.right + strokeWidth / 2,
|
||||
frame.bottom,
|
||||
frame.right - lineLength,
|
||||
frame.bottom,
|
||||
mPaint);
|
||||
canvas.drawLine(frame.right, frame.bottom, frame.right, frame.bottom - lineLength, mPaint);
|
||||
}
|
||||
|
||||
private void calculateFramePos() {
|
||||
final int centralX = getWidth() / 2;
|
||||
final int centralY = getHeight() / 2;
|
||||
final float halfFrameWidth = getWidth() / 3;
|
||||
mFrame = new RectF(
|
||||
centralX - halfFrameWidth,
|
||||
centralY - halfFrameWidth,
|
||||
centralX + halfFrameWidth,
|
||||
centralY + halfFrameWidth);
|
||||
}
|
||||
|
||||
// Draws green lines if focued. Otherwise, draws white lines.
|
||||
public void setFocused(boolean focused) {
|
||||
mFocused = focused;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
@@ -78,4 +78,23 @@ public class SettingsInitializeTest {
|
||||
assertThat(flags & Intent.FLAG_ACTIVITY_CLEAR_TOP).isEqualTo(
|
||||
Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshExistingShortcuts_shouldNotUpdateImmutableShortcut() {
|
||||
final String id = "test_shortcut_id";
|
||||
final ShortcutInfo info = new ShortcutInfo.Builder(mContext, id)
|
||||
.setShortLabel("test123")
|
||||
.setIntent(new Intent(Intent.ACTION_DEFAULT))
|
||||
.build();
|
||||
info.addFlags(ShortcutInfo.FLAG_IMMUTABLE);
|
||||
final List<ShortcutInfo> shortcuts = new ArrayList<>();
|
||||
shortcuts.add(info);
|
||||
ShadowShortcutManager.get().setPinnedShortcuts(shortcuts);
|
||||
|
||||
mSettingsInitialize.refreshExistingShortcuts(mContext);
|
||||
|
||||
final List<ShortcutInfo> updatedShortcuts =
|
||||
ShadowShortcutManager.get().getLastUpdatedShortcuts();
|
||||
assertThat(updatedShortcuts).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ public class SettingsPreferenceFragmentTest {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mFragment = spy(new TestFragment());
|
||||
doReturn(mActivity).when(mFragment).getActivity();
|
||||
when(mFragment.getContext()).thenReturn(mContext);
|
||||
|
||||
mEmptyView = new View(mContext);
|
||||
ReflectionHelpers.setField(mFragment, "mEmptyView", mEmptyView);
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.widget.RadioButtonPreference;
|
||||
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.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class AccessibilityTimeoutControllerTest
|
||||
implements AccessibilityTimeoutController.OnChangeListener {
|
||||
private static final String PREF_KEY = "accessibility_content_timeout_30secs";
|
||||
private static String PREF_TITLE;
|
||||
|
||||
private AccessibilityTimeoutController mController;
|
||||
|
||||
@Mock
|
||||
private RadioButtonPreference mMockPref;
|
||||
private Context mContext;
|
||||
private ContentResolver mContentResolver;
|
||||
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = new AccessibilityTimeoutController(mContext, mock(Lifecycle.class),
|
||||
PREF_KEY, AccessibilityContentTimeoutPreferenceFragment.TAG);
|
||||
mController.setOnChangeListener(this);
|
||||
mContentResolver = mContext.getContentResolver();
|
||||
PREF_TITLE = mContext.getResources().getString(R.string.accessibility_timeout_30secs);
|
||||
|
||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mMockPref);
|
||||
when(mMockPref.getKey()).thenReturn(PREF_KEY);
|
||||
when(mMockPref.getTitle()).thenReturn(PREF_TITLE);
|
||||
mController.displayPreference(mScreen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(Preference preference) {
|
||||
mController.updateState(preference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable() {
|
||||
assertTrue(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_notChecked() {
|
||||
Settings.Secure.putString(mContentResolver,
|
||||
Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, "0");
|
||||
|
||||
mController.updateState(mMockPref);
|
||||
|
||||
// the first checked state is seted to false by control
|
||||
verify(mMockPref).setChecked(false);
|
||||
verify(mMockPref).setChecked(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_checked() {
|
||||
Settings.Secure.putString(mContentResolver,
|
||||
Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, "30000");
|
||||
|
||||
mController.updateState(mMockPref);
|
||||
|
||||
// the first checked state is seted to false by control
|
||||
verify(mMockPref).setChecked(false);
|
||||
verify(mMockPref).setChecked(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRadioButtonClick() {
|
||||
mController.onRadioButtonClicked(mMockPref);
|
||||
|
||||
String accessibilityUiTimeoutValue = Settings.Secure.getString(mContentResolver,
|
||||
Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS);
|
||||
|
||||
assertThat(accessibilityUiTimeoutValue).isEqualTo("30000");
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,7 @@ public class AppPermissionsPreferenceControllerTest {
|
||||
when(mPackageManager.queryPermissionsByGroup(anyString(), anyInt()))
|
||||
.thenReturn(permissions);
|
||||
|
||||
mController = spy(new AppPermissionsPreferenceController(mContext));
|
||||
mController = spy(new AppPermissionsPreferenceController(mContext, "pref_key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.os.Build;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.ApplicationTestUtils;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.testutils.shadow.ShadowDefaultDialerManager;
|
||||
@@ -258,13 +259,16 @@ public final class ApplicationFeatureProviderImplTest {
|
||||
public void getKeepEnabledPackages_shouldContainDefaultPhoneAndSms() {
|
||||
final String testDialer = "com.android.test.defaultdialer";
|
||||
final String testSms = "com.android.test.defaultsms";
|
||||
final String settingsIntelligence = RuntimeEnvironment.application.getString(
|
||||
R.string.config_settingsintelligence_package_name);
|
||||
ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver"));
|
||||
ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
|
||||
ReflectionHelpers.setField(mProvider, "mContext", RuntimeEnvironment.application);
|
||||
|
||||
final Set<String> keepEnabledPackages = mProvider.getKeepEnabledPackages();
|
||||
|
||||
final List<String> expectedPackages = Arrays.asList(testDialer, testSms);
|
||||
final List<String> expectedPackages = Arrays.asList(testDialer, testSms,
|
||||
settingsIntelligence);
|
||||
assertThat(keepEnabledPackages).containsExactlyElementsIn(expectedPackages);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,12 +75,12 @@ public class LayoutPreferenceTest {
|
||||
|
||||
@Test
|
||||
public void disableSomeView_shouldMaintainStateAfterBind() {
|
||||
mPreference.findViewById(R.id.button1_positive).setEnabled(false);
|
||||
mPreference.findViewById(R.id.button2_positive).setEnabled(true);
|
||||
mPreference.findViewById(R.id.button1).setEnabled(false);
|
||||
mPreference.findViewById(R.id.button2).setEnabled(true);
|
||||
|
||||
mPreference.onBindViewHolder(mHolder);
|
||||
|
||||
assertThat(mPreference.findViewById(R.id.button1_positive).isEnabled()).isFalse();
|
||||
assertThat(mPreference.findViewById(R.id.button2_positive).isEnabled()).isTrue();
|
||||
assertThat(mPreference.findViewById(R.id.button1).isEnabled()).isFalse();
|
||||
assertThat(mPreference.findViewById(R.id.button2).isEnabled()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
|
||||
final boolean controllable = mController.handleDisableable();
|
||||
|
||||
verify(mButtonPrefs).setButton1Text(R.string.disable_text);
|
||||
verify(mButtonPrefs).setButton1Text(R.string.uninstall_text);
|
||||
assertThat(controllable).isFalse();
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
|
||||
final boolean controllable = mController.handleDisableable();
|
||||
|
||||
verify(mButtonPrefs).setButton1Text(R.string.disable_text);
|
||||
verify(mButtonPrefs).setButton1Text(R.string.uninstall_text);
|
||||
assertThat(controllable).isTrue();
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
|
||||
final boolean controllable = mController.handleDisableable();
|
||||
|
||||
verify(mButtonPrefs).setButton1Text(R.string.enable_text);
|
||||
verify(mButtonPrefs).setButton1Text(R.string.install_text);
|
||||
assertThat(controllable).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ public class BluetoothDetailsButtonsControllerTest extends BluetoothDetailsContr
|
||||
super.setUp();
|
||||
final View buttons = View.inflate(
|
||||
RuntimeEnvironment.application, R.layout.two_action_buttons, null /* parent */);
|
||||
mConnectButton = buttons.findViewById(R.id.button2_positive);
|
||||
mForgetButton = buttons.findViewById(R.id.button1_positive);
|
||||
mConnectButton = buttons.findViewById(R.id.button2);
|
||||
mForgetButton = buttons.findViewById(R.id.button1);
|
||||
mController =
|
||||
new BluetoothDetailsButtonsController(mContext, mFragment, mCachedDevice, mLifecycle);
|
||||
mButtonsPref = ActionButtonPreferenceTest.createMock();
|
||||
|
||||
@@ -41,6 +41,7 @@ import com.android.settings.testutils.shadow.ShadowDynamicLayout;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
@@ -83,6 +84,7 @@ public class RemoteDeviceNameDialogFragmentTest {
|
||||
return (AlertDialog) ShadowDialog.getLatestDialog();
|
||||
}
|
||||
|
||||
@Ignore("b/119592320")
|
||||
@Test
|
||||
public void deviceNameDisplayIsCorrect() {
|
||||
String deviceName = "ABC Corp Headphones";
|
||||
@@ -98,6 +100,7 @@ public class RemoteDeviceNameDialogFragmentTest {
|
||||
assertThat(negativeButton.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Ignore("b/119592320")
|
||||
@Test
|
||||
public void deviceNameEditSucceeds() {
|
||||
String deviceNameInitial = "ABC Corp Headphones";
|
||||
@@ -120,6 +123,7 @@ public class RemoteDeviceNameDialogFragmentTest {
|
||||
verify(mCachedDevice).setName(deviceNameModified);
|
||||
}
|
||||
|
||||
@Ignore("b/119592320")
|
||||
@Test
|
||||
public void deviceNameEditThenCancelDoesntRename() {
|
||||
String deviceNameInitial = "ABC Corp Headphones";
|
||||
|
||||
@@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings.Global;
|
||||
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
@@ -49,7 +50,15 @@ public class TopLevelAboutDevicePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_shouldReturnDeviceModel() {
|
||||
public void getSummary_deviceNameNotSet_shouldReturnDeviceModel() {
|
||||
assertThat(mController.getSummary().toString()).isEqualTo(Build.MODEL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_deviceNameSet_shouldReturnDeviceName() {
|
||||
Global.putString(mContext.getContentResolver(), Global.DEVICE_NAME, "Test");
|
||||
assertThat(mController.getSummary().toString()).isEqualTo("Test");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,8 +18,12 @@ package com.android.settings.homepage.contextualcards;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyMap;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.android.settings.homepage.contextualcards.conditional.ConditionalContextualCard;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
@@ -27,6 +31,8 @@ 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 java.util.ArrayList;
|
||||
@@ -35,11 +41,17 @@ import java.util.List;
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class ContextualCardManagerTest {
|
||||
|
||||
private static final String TEST_SLICE_URI = "context://test/test";
|
||||
|
||||
@Mock
|
||||
ContextualCardUpdateListener mListener;
|
||||
|
||||
private Context mContext;
|
||||
private ContextualCardManager mManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
final ContextualCardsFragment fragment = new ContextualCardsFragment();
|
||||
mManager = new ContextualCardManager(mContext, fragment.getSettingsLifecycle());
|
||||
@@ -47,10 +59,9 @@ public class ContextualCardManagerTest {
|
||||
|
||||
@Test
|
||||
public void sortCards_hasConditionalAndSliceCards_conditionalShouldAlwaysBeTheLast() {
|
||||
final String sliceUri = "content://com.android.settings.slices/action/flashlight";
|
||||
final List<ContextualCard> cards = new ArrayList<>();
|
||||
cards.add(new ConditionalContextualCard.Builder().build());
|
||||
cards.add(buildContextualCard(sliceUri));
|
||||
cards.add(buildContextualCard(TEST_SLICE_URI));
|
||||
|
||||
final List<ContextualCard> sortedCards = mManager.sortCards(cards);
|
||||
|
||||
@@ -58,6 +69,21 @@ public class ContextualCardManagerTest {
|
||||
.isEqualTo(ContextualCard.CardType.CONDITIONAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onContextualCardUpdated_emtpyMapWithExistingCards_shouldOnlyKeepConditionalCard() {
|
||||
mManager.mContextualCards.add(new ConditionalContextualCard.Builder().build());
|
||||
mManager.mContextualCards.add(
|
||||
buildContextualCard(TEST_SLICE_URI));
|
||||
mManager.setListener(mListener);
|
||||
|
||||
//Simulate database returns no contents.
|
||||
mManager.onContextualCardUpdated(new ArrayMap<>());
|
||||
|
||||
assertThat(mManager.mContextualCards).hasSize(1);
|
||||
assertThat(mManager.mContextualCards.get(0).getCardType())
|
||||
.isEqualTo(ContextualCard.CardType.CONDITIONAL);
|
||||
}
|
||||
|
||||
private ContextualCard buildContextualCard(String sliceUri) {
|
||||
return new ContextualCard.Builder()
|
||||
.setName("test_name")
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.slices;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.SliceItem;
|
||||
import androidx.slice.SliceProvider;
|
||||
import androidx.slice.widget.SliceLiveData;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.SliceTester;
|
||||
import com.android.settingslib.deviceinfo.PrivateStorageInfo;
|
||||
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.annotation.Resetter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class LowStorageSliceTest {
|
||||
|
||||
private Context mContext;
|
||||
private LowStorageSlice mLowStorageSlice;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
|
||||
// Set-up specs for SliceMetadata.
|
||||
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
|
||||
|
||||
mLowStorageSlice = new LowStorageSlice(mContext);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowPrivateStorageInfo.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowPrivateStorageInfo.class)
|
||||
public void getSlice_hasLowStorage_shouldBeCorrectSliceContent() {
|
||||
ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
|
||||
|
||||
final Slice slice = mLowStorageSlice.getSlice();
|
||||
|
||||
final List<SliceItem> sliceItems = slice.getItems();
|
||||
SliceTester.assertTitle(sliceItems, mContext.getString(R.string.storage_menu_free));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowPrivateStorageInfo.class)
|
||||
public void getSlice_hasNoLowStorage_shouldBeNull() {
|
||||
ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(100L, 100L));
|
||||
|
||||
final Slice slice = mLowStorageSlice.getSlice();
|
||||
|
||||
assertThat(slice).isNull();
|
||||
}
|
||||
|
||||
@Implements(PrivateStorageInfo.class)
|
||||
public static class ShadowPrivateStorageInfo {
|
||||
|
||||
private static PrivateStorageInfo sPrivateStorageInfo = null;
|
||||
|
||||
@Resetter
|
||||
public static void reset() {
|
||||
sPrivateStorageInfo = null;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public static PrivateStorageInfo getPrivateStorageInfo(
|
||||
StorageVolumeProvider storageVolumeProvider) {
|
||||
return sPrivateStorageInfo;
|
||||
}
|
||||
|
||||
public static void setPrivateStorageInfo(
|
||||
PrivateStorageInfo privateStorageInfo) {
|
||||
sPrivateStorageInfo = privateStorageInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class ApnEditorTest {
|
||||
@@ -113,6 +114,7 @@ public class ApnEditorTest {
|
||||
doReturn(mResources).when(mApnEditorUT).getResources();
|
||||
doNothing().when(mApnEditorUT).finish();
|
||||
doNothing().when(mApnEditorUT).showError();
|
||||
when(mApnEditorUT.getContext()).thenReturn(RuntimeEnvironment.application);
|
||||
|
||||
setMockPreference(mActivity);
|
||||
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class ZenModeAllBypassingAppsPreferenceControllerTest {
|
||||
private ZenModeAllBypassingAppsPreferenceController mController;
|
||||
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private NotificationBackend mBackend;
|
||||
@Mock
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
@Mock
|
||||
private ApplicationsState mApplicationState;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
|
||||
mController = new ZenModeAllBypassingAppsPreferenceController(
|
||||
mContext, null, mock(Fragment.class));
|
||||
mController.mPreferenceScreen = mPreferenceScreen;
|
||||
mController.mApplicationsState = mApplicationState;
|
||||
mController.mPrefContext = mContext;
|
||||
ReflectionHelpers.setField(mController, "mNotificationBackend", mBackend);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable() {
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNotificationChannelList() {
|
||||
ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
|
||||
entry.info = new ApplicationInfo();
|
||||
entry.info.packageName = "test";
|
||||
entry.info.uid = 0;
|
||||
|
||||
List<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||
appEntries.add(entry);
|
||||
|
||||
List<NotificationChannel> channelsBypassing = new ArrayList<>();
|
||||
channelsBypassing.add(mock(NotificationChannel.class));
|
||||
channelsBypassing.add(mock(NotificationChannel.class));
|
||||
channelsBypassing.add(mock(NotificationChannel.class));
|
||||
|
||||
when(mBackend.getNotificationChannelsBypassingDnd(entry.info.packageName,
|
||||
entry.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
|
||||
|
||||
mController.updateNotificationChannelList(appEntries);
|
||||
verify(mPreferenceScreen, times(3)).addPreference(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNotificationChannelList_nullChannels() {
|
||||
mController.updateNotificationChannelList(null);
|
||||
verify(mPreferenceScreen, never()).addPreference(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNotificationChannelList_emptyChannelsList() {
|
||||
mController.updateNotificationChannelList(new ArrayList<ApplicationsState.AppEntry>());
|
||||
verify(mPreferenceScreen, never()).addPreference(any());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
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.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class ZenModeBypassingAppsPreferenceControllerTest {
|
||||
|
||||
private ZenModeBypassingAppsPreferenceController mController;
|
||||
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private NotificationBackend mBackend;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
|
||||
mController = new ZenModeBypassingAppsPreferenceController(mContext, mock(Lifecycle.class));
|
||||
ReflectionHelpers.setField(mController, "mNotificationBackend", mBackend);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable() {
|
||||
when(mBackend.getNumAppsBypassingDnd(anyInt())).thenReturn(5);
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotAvailable() {
|
||||
when(mBackend.getNumAppsBypassingDnd(anyInt())).thenReturn(0);
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasSummary() {
|
||||
assertThat(mController.getSummary()).isNotNull();
|
||||
}
|
||||
}
|
||||
@@ -19,14 +19,15 @@ package com.android.settings.search;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.provider.Settings;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
@@ -37,25 +38,34 @@ import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowPackageManager;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class SearchFeatureProviderImplTest {
|
||||
|
||||
private SearchFeatureProviderImpl mProvider;
|
||||
private Activity mActivity;
|
||||
private ShadowPackageManager mPackageManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
FakeFeatureFactory.setupForTest();
|
||||
mActivity = Robolectric.setupActivity(Activity.class);
|
||||
mProvider = spy(new SearchFeatureProviderImpl());
|
||||
mProvider = new SearchFeatureProviderImpl();
|
||||
mPackageManager = Shadows.shadowOf(mActivity.getPackageManager());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowUtils.class)
|
||||
public void initSearchToolbar_shouldInitWithOnClickListener() {
|
||||
mProvider.initSearchToolbar(mActivity, null);
|
||||
public void initSearchToolbar_hasResolvedInfo_shouldStartCorrectIntent() {
|
||||
final Intent searchIntent = new Intent(SearchFeatureProvider.SEARCH_UI_INTENT)
|
||||
.setPackage(mActivity.getString(R.string.config_settingsintelligence_package_name));
|
||||
final ResolveInfo info = new ResolveInfo();
|
||||
info.activityInfo = new ActivityInfo();
|
||||
mPackageManager.addResolveInfoForIntent(searchIntent, info);
|
||||
|
||||
// Should not crash.
|
||||
mProvider.initSearchToolbar(mActivity, null);
|
||||
|
||||
final Toolbar toolbar = new Toolbar(mActivity);
|
||||
// This ensures navigationView is created.
|
||||
@@ -70,6 +80,21 @@ public class SearchFeatureProviderImplTest {
|
||||
.isEqualTo(Settings.ACTION_APP_SEARCH_SETTINGS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowUtils.class)
|
||||
public void initSearchToolbar_NotHaveResolvedInfo_shouldNotStartActivity() {
|
||||
final Toolbar toolbar = new Toolbar(mActivity);
|
||||
// This ensures navigationView is created.
|
||||
toolbar.setNavigationContentDescription("test");
|
||||
mProvider.initSearchToolbar(mActivity, toolbar);
|
||||
|
||||
toolbar.performClick();
|
||||
|
||||
final Intent launchIntent = Shadows.shadowOf(mActivity).getNextStartedActivity();
|
||||
|
||||
assertThat(launchIntent).isNull();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void verifyLaunchSearchResultPageCaller_nullCaller_shouldCrash() {
|
||||
mProvider.verifyLaunchSearchResultPageCaller(mActivity, null /* caller */);
|
||||
|
||||
@@ -25,6 +25,7 @@ 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;
|
||||
|
||||
@@ -59,41 +60,17 @@ public class ActionButtonPreferenceTest {
|
||||
mPref.setButton1Visible(false).setButton2Visible(false);
|
||||
mPref.onBindViewHolder(mHolder);
|
||||
|
||||
assertThat(mRootView.findViewById(R.id.button1_positive).getVisibility())
|
||||
.isEqualTo(View.INVISIBLE);
|
||||
assertThat(mRootView.findViewById(R.id.button1_negative).getVisibility())
|
||||
.isEqualTo(View.INVISIBLE);
|
||||
|
||||
assertThat(mRootView.findViewById(R.id.button2_positive).getVisibility())
|
||||
.isEqualTo(View.INVISIBLE);
|
||||
assertThat(mRootView.findViewById(R.id.button2_negative).getVisibility())
|
||||
.isEqualTo(View.INVISIBLE);
|
||||
assertThat(mRootView.findViewById(R.id.button1).getVisibility())
|
||||
.isEqualTo(View.GONE);
|
||||
assertThat(mRootView.findViewById(R.id.button2).getVisibility())
|
||||
.isEqualTo(View.GONE);
|
||||
|
||||
mPref.setButton1Visible(true).setButton2Visible(true);
|
||||
mPref.onBindViewHolder(mHolder);
|
||||
|
||||
assertThat(mRootView.findViewById(R.id.button1_positive).getVisibility())
|
||||
assertThat(mRootView.findViewById(R.id.button1).getVisibility())
|
||||
.isEqualTo(View.VISIBLE);
|
||||
assertThat(mRootView.findViewById(R.id.button1_negative).getVisibility())
|
||||
.isEqualTo(View.INVISIBLE);
|
||||
assertThat(mRootView.findViewById(R.id.button2_positive).getVisibility())
|
||||
.isEqualTo(View.VISIBLE);
|
||||
assertThat(mRootView.findViewById(R.id.button2_negative).getVisibility())
|
||||
.isEqualTo(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPositiveNegative_shouldHideOppositeButton() {
|
||||
mPref.setButton1Positive(true).setButton2Positive(false);
|
||||
mPref.onBindViewHolder(mHolder);
|
||||
|
||||
assertThat(mRootView.findViewById(R.id.button1_positive).getVisibility())
|
||||
.isEqualTo(View.VISIBLE);
|
||||
assertThat(mRootView.findViewById(R.id.button1_negative).getVisibility())
|
||||
.isEqualTo(View.INVISIBLE);
|
||||
assertThat(mRootView.findViewById(R.id.button2_positive).getVisibility())
|
||||
.isEqualTo(View.INVISIBLE);
|
||||
assertThat(mRootView.findViewById(R.id.button2_negative).getVisibility())
|
||||
assertThat(mRootView.findViewById(R.id.button2).getVisibility())
|
||||
.isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@@ -102,36 +79,69 @@ public class ActionButtonPreferenceTest {
|
||||
mPref.setButton1Enabled(true).setButton2Enabled(false);
|
||||
mPref.onBindViewHolder(mHolder);
|
||||
|
||||
assertThat(mRootView.findViewById(R.id.button1_positive).isEnabled()).isTrue();
|
||||
assertThat(mRootView.findViewById(R.id.button1_negative).isEnabled()).isTrue();
|
||||
assertThat(mRootView.findViewById(R.id.button2_positive).isEnabled()).isFalse();
|
||||
assertThat(mRootView.findViewById(R.id.button2_negative).isEnabled()).isFalse();
|
||||
assertThat(mRootView.findViewById(R.id.button1).isEnabled()).isTrue();
|
||||
assertThat(mRootView.findViewById(R.id.button2).isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setText() {
|
||||
public void setText_shouldShowSameText() {
|
||||
mPref.setButton1Text(R.string.settings_label);
|
||||
mPref.onBindViewHolder(mHolder);
|
||||
|
||||
assertThat(((Button) mRootView.findViewById(R.id.button1_positive)).getText())
|
||||
.isEqualTo(mContext.getText(R.string.settings_label));
|
||||
assertThat(((Button) mRootView.findViewById(R.id.button1_negative)).getText())
|
||||
assertThat(((Button) mRootView.findViewById(R.id.button1)).getText())
|
||||
.isEqualTo(mContext.getText(R.string.settings_label));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void 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.setButton1Positive(anyBoolean())).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.setButton2Positive(anyBoolean())).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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user