Snap for 5138341 from b4dcebec03 to qt-release

Change-Id: I735aca69d09042e089b615beaf681646f5cd1602
This commit is contained in:
android-build-team Robot
2018-11-18 04:01:57 +00:00
81 changed files with 2731 additions and 468 deletions

View File

@@ -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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;switch_bar_background&quot;>#dadce0&lt;/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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;switchbar_switch_track_tint&quot;>#82000000&lt;/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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;homepage_location_background&quot;>#1A73E8&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
errorLine1=" &lt;color name=&quot;homepage_location_background&quot;>#2EC7DC&lt;/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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;homepage_about_background&quot;>#9FA8DA&lt;/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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;homepage_privacy_background&quot;>#1A73E8&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
errorLine1=" &lt;color name=&quot;homepage_privacy_background&quot;>#5E97F6&lt;/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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;switchbar_switch_track_tint&quot;>#BFFFFFFF&lt;/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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;battery_good_color_light&quot;>#43a047&lt;/color> &lt;!-- Material Green 600 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;battery_maybe_color_light&quot;>#ef6c00&lt;/color> &lt;!-- 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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;battery_bad_color_light&quot;>#f44336&lt;/color> &lt;!-- Material Red 500 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="137"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;battery_good_color_dark&quot;>#4caf50&lt;/color> &lt;!-- 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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;battery_maybe_color_dark&quot;>#fdd835&lt;/color> &lt;!-- Material Yellow 600 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;battery_maybe_color_light&quot;>#ef6c00&lt;/color> &lt;!-- 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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;battery_bad_color_light&quot;>#f44336&lt;/color> &lt;!-- Material Red 500 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;battery_good_color_dark&quot;>#4caf50&lt;/color> &lt;!-- Material Green 500 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;battery_maybe_color_dark&quot;>#fdd835&lt;/color> &lt;!-- Material Yellow 600 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/homepage_about_background&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/homepage_location_background&quot;/>"
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/homepage_privacy_background&quot;/>"
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/homepage_location_background&quot; />"
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/homepage_location_background&quot; />"
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/homepage_location_background&quot; />"
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color=&quot;@color/homepage_location_background&quot;/>"
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item name=&quot;android:statusBarColor&quot;>#00000000&lt;/item>"
errorLine2=" ^">
errorLine1=" &lt;item name=&quot;switchBarBackgroundColor&quot;>@color/switch_bar_background&lt;/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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item name=&quot;android:navigationBarColor&quot;>#00000000&lt;/item>"
errorLine2=" ^">
errorLine1=" &lt;item name=&quot;android:trackTint&quot;>@color/switchbar_switch_track_tint&lt;/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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item name=&quot;android:trackTint&quot;>@color/switchbar_switch_track_tint&lt;/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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item name=&quot;android:navigationBarDividerColor&quot;>#1f000000&lt;/item>"
errorLine2=" ^">
errorLine1=" &lt;item name=&quot;android:statusBarColor&quot;>#00000000&lt;/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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item name=&quot;android:navigationBarColor&quot;>#00000000&lt;/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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View 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>

View 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>

View 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>

View File

@@ -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>

View 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>

View 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>

View File

@@ -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"

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View 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>

View 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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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] -->

View File

@@ -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>

View File

@@ -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 -->

View File

@@ -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 -->

View File

@@ -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 &amp; 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>

View File

@@ -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>

View File

@@ -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>

View 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>

View 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>

View File

@@ -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"

View File

@@ -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"

View File

@@ -16,12 +16,14 @@
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/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" />

View File

@@ -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

View 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" />

View File

@@ -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>

View File

@@ -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())

View File

@@ -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);
}
};
}

View File

@@ -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);
}
};
}

View File

@@ -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);
}
}

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -63,7 +63,7 @@ public class ContextualCard {
private final boolean mIsHalfWidth;
private final Drawable mIconDrawable;
String getName() {
public String getName() {
return mName;
}

View File

@@ -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(

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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();
}
};
}

View File

@@ -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);
}
}

View File

@@ -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);
}
};
}

View File

@@ -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;
}

View File

@@ -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() {

View File

@@ -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;

View File

@@ -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()

View File

@@ -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 */);

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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 =

View File

@@ -0,0 +1,136 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.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();
}
}

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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");
}
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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();
}
}

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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";

View File

@@ -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");
}
}

View File

@@ -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")

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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());
}
}

View File

@@ -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();
}
}

View File

@@ -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 */);

View File

@@ -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;
}
}
}