Merge "Delete Directory access Settings."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 362ca11..0e9b1b1 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1161,7 +1161,7 @@
<activity
android:name="Settings$LocationSettingsActivity"
android:label="@string/location_settings_title"
- android:icon="@drawable/ic_settings_location"
+ android:icon="@drawable/ic_homepage_location"
android:configChanges="orientation|keyboardHidden|screenSize"
android:parentActivityName="Settings">
<intent-filter android:priority="1">
@@ -1180,7 +1180,7 @@
<activity
android:name="Settings$ScanningSettingsActivity"
android:label="@string/location_scanning_screen_title"
- android:icon="@drawable/ic_settings_location"
+ android:icon="@drawable/ic_homepage_location"
android:configChanges="orientation|keyboardHidden|screenSize"
android:parentActivityName="Settings">
<intent-filter android:priority="1">
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 62c7915..d28f2d1 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -1221,11 +1221,27 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+ errorLine1=" <color name="homepage_location_background">#1A73E8</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="128"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="HardCodedColor"
+ severity="Error"
+ message="Avoid using hardcoded color"
+ category="Correctness"
+ priority="4"
+ summary="Using hardcoded color"
+ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" <color name="battery_good_color_light">#43a047</color> <!-- Material Green 600 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="132"
+ line="133"
column="5"/>
</issue>
@@ -1241,7 +1257,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="133"
+ line="134"
column="5"/>
</issue>
@@ -1257,7 +1273,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="134"
+ line="135"
column="5"/>
</issue>
@@ -1273,7 +1289,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="135"
+ line="136"
column="5"/>
</issue>
@@ -1289,7 +1305,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="136"
+ line="137"
column="5"/>
</issue>
@@ -1305,7 +1321,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="137"
+ line="138"
column="5"/>
</issue>
@@ -1321,7 +1337,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="140"
+ line="141"
column="5"/>
</issue>
@@ -1337,7 +1353,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="141"
+ line="142"
column="5"/>
</issue>
@@ -1353,7 +1369,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="142"
+ line="143"
column="5"/>
</issue>
@@ -1369,7 +1385,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="143"
+ line="144"
column="5"/>
</issue>
@@ -1385,7 +1401,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
- line="144"
+ line="145"
column="5"/>
</issue>
@@ -1861,6 +1877,38 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+ errorLine1=" android:color="@color/homepage_location_background" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/drawable/ic_homepage_location.xml"
+ line="23"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="HardCodedColor"
+ severity="Error"
+ message="Avoid using hardcoded color"
+ category="Correctness"
+ priority="4"
+ summary="Using hardcoded color"
+ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+ errorLine1=" android:color="@color/homepage_location_background" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/drawable/ic_preference_location.xml"
+ line="23"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="HardCodedColor"
+ severity="Error"
+ message="Avoid using hardcoded color"
+ category="Correctness"
+ priority="4"
+ summary="Using hardcoded color"
+ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" android:color="@color/homepage_support_background" />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
diff --git a/libs/contextualcards.aar b/libs/contextualcards.aar
index 5e855fa..892a6be 100755
--- a/libs/contextualcards.aar
+++ b/libs/contextualcards.aar
Binary files differ
diff --git a/proguard.flags b/proguard.flags
index 82e8e58..b66a786 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -60,4 +60,9 @@
# Keep classes that implements CustomSliceable, which are used by reflection.
-keepclasseswithmembers class * implements com.android.settings.slices.CustomSliceable {
public <init>(android.content.Context);
-}
\ No newline at end of file
+}
+
+# Keep classes that extends SliceBackgroundWorker, which are used by reflection.
+-keepclasseswithmembers class * extends com.android.settings.slices.SliceBackgroundWorker {
+ public <init>(android.content.Context, android.net.Uri);
+}
diff --git a/protos/contextual_card_list.proto b/protos/contextual_card_list.proto
index 89e6c13..ea82408 100644
--- a/protos/contextual_card_list.proto
+++ b/protos/contextual_card_list.proto
@@ -8,12 +8,24 @@
}
message ContextualCard {
- // Slice uri of the contextual card
+
+ /**
+ * The category of a card: this is a hint for how a card should be collected,
+ * ranked, and presented
+ */
+ enum Category {
+ DEFAULT = 0;
+ SUGGESTION = 1;
+ POSSIBLE = 2;
+ IMPORTANT = 3;
+ EXCLUSIVE = 4;
+ }
+
+ /** Slice uri of the contextual card */
optional string sliceUri = 1;
- // {@link ContextualCardCategory}.
- optional int32 category = 2;
-
- // Name of the card. It should be identical in every app
+ /** Name of the card. It should be identical in every app */
optional string cardName = 3;
-}
\ No newline at end of file
+
+ optional Category card_category = 4;
+}
diff --git a/res/drawable/ic_account_circle_24dp.xml b/res/drawable/ic_account_circle_24dp.xml
new file mode 100644
index 0000000..8445adc
--- /dev/null
+++ b/res/drawable/ic_account_circle_24dp.xml
@@ -0,0 +1,27 @@
+<!--
+ 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="32dp"
+ android:height="32dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#ff4285f4"
+ android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10c5.52,0 10,-4.48 10,-10C22,6.48 17.52,2 12,2zM7.07,18.28c0.43,-0.9 3.05,-1.78 4.93,-1.78s4.51,0.88 4.93,1.78C15.57,19.36 13.86,20 12,20S8.43,19.36 7.07,18.28zM18.36,16.83c-1.43,-1.74 -4.9,-2.33 -6.36,-2.33s-4.93,0.59 -6.36,2.33C4.62,15.49 4,13.82 4,12c0,-4.41 3.59,-8 8,-8c4.41,0 8,3.59 8,8C20,13.82 19.38,15.49 18.36,16.83z"/>
+ <path
+ android:fillColor="#ff4285f4"
+ android:pathData="M12,6c-1.94,0 -3.5,1.56 -3.5,3.5S10.06,13 12,13c1.94,0 3.5,-1.56 3.5,-3.5S13.94,6 12,6zM12,11c-0.83,0 -1.5,-0.67 -1.5,-1.5C10.5,8.67 11.17,8 12,8c0.83,0 1.5,0.67 1.5,1.5C13.5,10.33 12.83,11 12,11z"/>
+</vector>
diff --git a/res/drawable/ic_content_copy_grey600_24dp.xml b/res/drawable/ic_content_copy_grey600_24dp.xml
new file mode 100644
index 0000000..827c66e
--- /dev/null
+++ b/res/drawable/ic_content_copy_grey600_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"
+ android:fillColor="#757575"/>
+</vector>
diff --git a/res/drawable/ic_homepage_location.xml b/res/drawable/ic_homepage_location.xml
new file mode 100644
index 0000000..413801b
--- /dev/null
+++ b/res/drawable/ic_homepage_location.xml
@@ -0,0 +1,36 @@
+<?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.
+ -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item>
+ <shape android:shape="oval">
+ <solid
+ android:color="@color/homepage_location_background"/>
+ <size
+ android:width="@dimen/dashboard_tile_image_size"
+ android:height="@dimen/dashboard_tile_image_size"/>
+ </shape>
+ </item>
+
+ <item
+ android:width="@dimen/dashboard_tile_foreground_image_size"
+ android:height="@dimen/dashboard_tile_foreground_image_size"
+ android:start="@dimen/dashboard_tile_foreground_image_inset"
+ android:top="@dimen/dashboard_tile_foreground_image_inset"
+ android:drawable="@drawable/ic_settings_location"/>
+</layer-list>
diff --git a/res/drawable/ic_preference_location.xml b/res/drawable/ic_preference_location.xml
new file mode 100644
index 0000000..e37d629
--- /dev/null
+++ b/res/drawable/ic_preference_location.xml
@@ -0,0 +1,36 @@
+<?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.
+ -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item>
+ <shape android:shape="oval">
+ <solid
+ android:color="@color/homepage_location_background"/>
+ <size
+ android:width="@android:dimen/app_icon_size"
+ android:height="@android:dimen/app_icon_size"/>
+ </shape>
+ </item>
+
+ <item
+ android:width="@dimen/dashboard_tile_foreground_image_size"
+ android:height="@dimen/dashboard_tile_foreground_image_size"
+ android:start="@dimen/preference_icon_foreground_image_inset"
+ android:top="@dimen/preference_icon_foreground_image_inset"
+ android:drawable="@drawable/ic_settings_location"/>
+</layer-list>
diff --git a/res/drawable/ic_settings_location.xml b/res/drawable/ic_settings_location.xml
index 34bd4f0..b7cfd6f 100644
--- a/res/drawable/ic_settings_location.xml
+++ b/res/drawable/ic_settings_location.xml
@@ -17,8 +17,7 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
+ android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
diff --git a/res/layout/homepage_condition_full_tile.xml b/res/layout/homepage_condition_full_tile.xml
new file mode 100644
index 0000000..f00132b
--- /dev/null
+++ b/res/layout/homepage_condition_full_tile.xml
@@ -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.
+-->
+
+<androidx.cardview.widget.CardView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/ContextualCardStyle">
+
+ <LinearLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/homepage_condition_full_card_height"
+ android:paddingStart="@dimen/homepage_card_padding_start"
+ android:paddingEnd="@dimen/homepage_card_padding_end"
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="@dimen/suggestion_card_icon_size"
+ android:layout_height="@dimen/suggestion_card_icon_size"
+ android:tint="?android:attr/colorAccent"/>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingStart="@dimen/homepage_condition_full_card_padding_start"
+ android:paddingEnd="@dimen/homepage_condition_full_card_padding_end"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
+ style="@style/TextAppearance.ConditionCardTitle"/>
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@style/TextAppearance.ConditionCardSummary"/>
+
+ </LinearLayout>
+
+ <View
+ android:id="@+id/divider"
+ android:layout_width="@dimen/homepage_condition_full_card_divider_width"
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/homepage_condition_full_card_divider_padding_top"
+ android:layout_marginBottom="@dimen/homepage_condition_full_card_divider_padding_bottom"
+ android:background="?android:attr/dividerVertical" />
+
+ <Button
+ android:id="@+id/first_action"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@style/ConditionFullCardBorderlessButton"/>
+
+ </LinearLayout>
+
+</androidx.cardview.widget.CardView>
diff --git a/res/layout/homepage_condition_half_tile.xml b/res/layout/homepage_condition_half_tile.xml
new file mode 100644
index 0000000..9cde951
--- /dev/null
+++ b/res/layout/homepage_condition_half_tile.xml
@@ -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.
+-->
+
+<androidx.cardview.widget.CardView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/homepage_condition_half_card_height"
+ style="@style/ContextualCardStyle">
+
+ <LinearLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/homepage_card_padding_start"
+ android:paddingEnd="@dimen/homepage_card_padding_end"
+ android:paddingTop="@dimen/homepage_condition_half_card_padding_top"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="@dimen/suggestion_card_icon_size"
+ android:layout_height="@dimen/suggestion_card_icon_size"
+ android:tint="?android:attr/colorAccent"/>
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/homepage_condition_half_card_title_margin_top"
+ android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
+ style="@style/TextAppearance.ConditionCardTitle"/>
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/TextAppearance.ConditionCardSummary"/>
+
+ <include layout="@layout/horizontal_divider"/>
+
+ <Button
+ android:id="@+id/first_action"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/ConditionHalfCardBorderlessButton"/>
+
+ </LinearLayout>
+
+</androidx.cardview.widget.CardView>
\ No newline at end of file
diff --git a/res/layout/homepage_condition_tile.xml b/res/layout/homepage_condition_tile.xml
deleted file mode 100644
index ed76094..0000000
--- a/res/layout/homepage_condition_tile.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<!--
- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<androidx.cardview.widget.CardView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="@style/ContextualCardStyle">
-
- <LinearLayout
- android:id="@+id/content"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="@dimen/condition_header_height"
- android:background="?android:attr/selectableItemBackground"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@android:id/icon"
- android:layout_width="@dimen/suggestion_card_icon_size"
- android:layout_height="@dimen/suggestion_card_icon_size"
- android:layout_marginTop="12dp"
- android:layout_marginStart="14dp"
- android:layout_marginEnd="24dp"
- android:tint="?android:attr/colorAccent"/>
-
- <TextView
- android:id="@android:id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="14dp"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary"/>
-
- </LinearLayout>
-
- <TextView
- android:id="@android:id/summary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="62dp"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingBottom="8dp"
- android:textAppearance="?android:attr/textAppearanceListItemSecondary"
- android:alpha=".7"
- android:textColor="?android:attr/textColorPrimary"/>
-
- <androidx.appcompat.widget.ButtonBarLayout
- android:id="@+id/buttonBar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="62dp"
- android:paddingBottom="1dp"
- style="?android:attr/buttonBarStyle"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
-
- <Button
- android:id="@+id/first_action"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:paddingStart="0dp"
- android:alpha=".8"
- android:textAlignment="viewStart"
- android:textColor="?android:attr/textColorPrimary"
- style="?android:attr/buttonBarButtonStyle"/>
-
- <Space
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
-
- </androidx.appcompat.widget.ButtonBarLayout>
-
- <include layout="@layout/horizontal_divider"/>
-
- </LinearLayout>
-
-</androidx.cardview.widget.CardView>
diff --git a/res/layout/horizontal_divider.xml b/res/layout/horizontal_divider.xml
index e4a277d..a134423 100644
--- a/res/layout/horizontal_divider.xml
+++ b/res/layout/horizontal_divider.xml
@@ -19,5 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/divider"
android:layout_width="match_parent"
- android:layout_height=".75dp"
- android:background="?android:attr/dividerHorizontal" />
\ No newline at end of file
+ android:layout_height="@dimen/horizontal_divider_height"
+ android:layout_marginTop="@dimen/horizontal_divider_margin_top"
+ android:layout_marginBottom="@dimen/horizontal_divider_margin_bottom"
+ android:background="?android:attr/dividerHorizontal"/>
\ No newline at end of file
diff --git a/res/layout/search_bar.xml b/res/layout/search_bar.xml
index 9e64db7..1ba64ad 100644
--- a/res/layout/search_bar.xml
+++ b/res/layout/search_bar.xml
@@ -45,5 +45,12 @@
android:layout_height="wrap_content"
android:text="@string/search_menu"/>
</Toolbar>
+ <ImageView
+ android:id="@+id/account_avatar"
+ android:layout_marginStart="@dimen/search_bar_avatar_start_margin"
+ android:layout_marginEnd="@dimen/search_bar_avatar_end_margin"
+ android:layout_width="@dimen/search_bar_avatar_size"
+ android:layout_height="@dimen/search_bar_avatar_size"
+ android:layout_gravity="end|center_vertical"/>
</androidx.cardview.widget.CardView>
</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/settings_homepage.xml b/res/layout/settings_homepage.xml
index bd54717..0140ced 100644
--- a/res/layout/settings_homepage.xml
+++ b/res/layout/settings_homepage.xml
@@ -27,32 +27,5 @@
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_animation_fall_down"/>
- <RelativeLayout
- android:id="@+id/suggestion_footer"
- android:layout_width="match_parent"
- android:layout_height="@dimen/condition_header_height"
- android:layout_centerHorizontal="true">
-
- <ImageView
- android:id="@+id/expand_indicator"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_alignParentEnd="true"
- android:paddingTop="4dp"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"/>
-
- <TextView
- android:id="@+id/expand_summary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="8dp"
- android:layout_toStartOf="@id/expand_indicator"
- android:layout_centerVertical="true"
- android:gravity="end"
- android:textAppearance="@style/TextAppearance.SuggestionTitle"
- android:textColor="?android:attr/colorAccent"/>
-
- </RelativeLayout>
<include layout="@layout/horizontal_divider"/>
</LinearLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index f398d92..a00fd8a 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -125,6 +125,7 @@
<color name="homepage_system_background">#757575</color>
<color name="homepage_support_background">#26459C</color>
<color name="homepage_generic_icon_background">#1A73E8</color>
+ <color name="homepage_location_background">#2EC7DC</color>
<!-- End of dashboard/homepage icon background colors -->
<color name="glif_error_color">@*android:color/material_red_A700</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 9b33388..c91ffb5 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -88,6 +88,9 @@
<!-- Dashboard foreground image inset (from background edge to foreground edge) -->
<dimen name="dashboard_tile_foreground_image_inset">6dp</dimen>
+ <!-- Preference icon foreground image inset (from background edge to foreground edge) -->
+ <dimen name="preference_icon_foreground_image_inset">12dp</dimen>
+
<!-- SwitchBar sub settings margin start / end -->
<dimen name="switchbar_subsettings_margin_start">72dp</dimen>
<dimen name="switchbar_subsettings_margin_end">16dp</dimen>
@@ -103,6 +106,9 @@
<dimen name="search_bar_text_size">16dp</dimen>
<dimen name="search_bar_card_elevation">2dp</dimen>
<dimen name="search_bar_content_inset">64dp</dimen>
+ <dimen name="search_bar_avatar_size">32dp</dimen>
+ <dimen name="search_bar_avatar_start_margin">4dp</dimen>
+ <dimen name="search_bar_avatar_end_margin">16dp</dimen>
<!-- Dimensions for Wifi Assistant Card -->
<dimen name="wifi_assistant_padding_top_bottom">16dp</dimen>
@@ -327,14 +333,29 @@
<!-- Homepage cards size and padding -->
<dimen name="homepage_card_corner_radius">8dp</dimen>
<dimen name="homepage_card_elevation">2dp</dimen>
- <dimen name="homepage_card_vertical_margin">6dp</dimen>
- <dimen name="homepage_card_side_margin">16dp</dimen>
+ <dimen name="homepage_card_vertical_margin">4dp</dimen>
+ <dimen name="homepage_card_side_margin">8dp</dimen>
<dimen name="homepage_card_padding_start">16dp</dimen>
<dimen name="homepage_card_padding_end">16dp</dimen>
+ <!-- Horizontal divider size and margin -->
+ <dimen name="horizontal_divider_margin_top">4dp</dimen>
+ <dimen name="horizontal_divider_margin_bottom">8dp</dimen>
+ <dimen name="horizontal_divider_height">.75dp</dimen>
+
<!-- Signal icon in NetworkSelectSetting -->
<dimen name="signal_strength_icon_size">24dp</dimen>
-
+ <!-- Condition cards size and padding -->
+ <dimen name="homepage_condition_card_title_margin_bottom">2dp</dimen>
+ <dimen name="homepage_condition_half_card_height">150dp</dimen>
+ <dimen name="homepage_condition_half_card_padding_top">12dp</dimen>
+ <dimen name="homepage_condition_half_card_title_margin_top">12dp</dimen>
+ <dimen name="homepage_condition_full_card_height">72dp</dimen>
+ <dimen name="homepage_condition_full_card_padding_start">24dp</dimen>
+ <dimen name="homepage_condition_full_card_padding_end">24dp</dimen>
+ <dimen name="homepage_condition_full_card_divider_width">.75dp</dimen>
+ <dimen name="homepage_condition_full_card_divider_padding_top">12dp</dimen>
+ <dimen name="homepage_condition_full_card_divider_padding_bottom">12dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 65a2f43..4e07bad 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -814,11 +814,13 @@
<string name="location_settings_title">Location</string>
<!-- Used in the location settings to control turning on/off the feature entirely -->
<string name="location_settings_master_switch_title">Use location</string>
+ <!-- Summary for Location settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
+ <string name="location_settings_summary">Scanning, location history</string>
<!-- Main Settings screen setting option title for the item to take you to the accounts screen [CHAR LIMIT=22] -->
<string name="account_settings_title">Accounts</string>
<!-- Main Settings screen setting option title for the item to take you to the security screen -->
- <string name="security_settings_title">Security & location</string>
+ <string name="security_settings_title">Security</string>
<!-- Security Settings screen setting option title for the item to take you to the encryption and credential screen -->
<string name="encryption_and_credential_settings_title">Encryption & credentials</string>
<!-- Security Settings screen Encryption and crendential summary -->
@@ -5655,12 +5657,18 @@
<string name="remove_and_uninstall_device_admin">Deactivate & uninstall</string>
<!-- Label for screen showing to select device admin apps -->
<string name="select_device_admin_msg">Device admin apps</string>
+
<!-- Message when there are no available device admin apps to display -->
<string name="no_device_admins">No device admin apps available</string>
<!-- Title for personal device admin apps on the list [CHAR_LIMIT=25] -->
<string name="personal_device_admin_title">Personal</string>
<!-- Title for managed device admin apps on the list [CHAR_LIMIT=25] -->
<string name="managed_device_admin_title">Work</string>
+ <!-- Title for whether to enable SMS access restriction [CHAR LIMIT=50]-->
+ <string name="sms_access_restriction_enabled">Restrict SMS & call log access</string>
+ <!-- Summary for whether to enable SMS access restriction [CHAR LIMIT=NONE]-->
+ <string name="sms_access_restriction_enabled_summary">Only default phone and messaging apps have SMS & call log permissions</string>
+
<!-- Message when there are no available trust agents to display -->
<string name="no_trust_agents">No available trust agents</string>
@@ -7272,9 +7280,9 @@
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_peek">Don\'t pop notifications on screen</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
- <string name="zen_mode_block_effect_status">Hide status bar icons</string>
+ <string name="zen_mode_block_effect_status">Hide status bar icons at top of screen</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
- <string name="zen_mode_block_effect_badge">Hide notification dots</string>
+ <string name="zen_mode_block_effect_badge">Hide notification dots on app icons</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_ambient">Don\'t wake for notifications</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
@@ -8937,12 +8945,6 @@
<!-- Summary of payment screen [CHAR LIMIT=NONE] -->
<string name="payment_summary"><xliff:g id="app_name" example="Payment App">%1$s</xliff:g> is default</string>
- <!-- Summary of location on screen [CHAR LIMIT=NONE] -->
- <string name="location_on_summary">On</string>
-
- <!-- Location off [CHAR LIMIT=NONE] -->
- <string name="location_off_summary">Off</string>
-
<!-- Backup disabled summary [CHAR LIMIT=NONE] -->
<string name="backup_disabled">Back up disabled</string>
@@ -10049,7 +10051,7 @@
<!-- Title for prevent ringing gesture screen -->
<string name="gesture_prevent_ringing_screen_title">Prevent ringing</string>
<!-- Title for prevent ringing setting -->
- <string name="gesture_prevent_ringing_title">Press Power & Volume Up together</string>
+ <string name="gesture_prevent_ringing_title">Press Power & Volume Up together to</string>
<!-- Title for prevent ringing setting -->
<string name="gesture_prevent_ringing_sound_title">Shortcut to prevent ringing</string>
<!-- Option for prevent ringing setting -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 83971b6..70d8a93 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -308,6 +308,16 @@
<item name="android:textColor">?android:attr/colorAccent</item>
</style>
+ <style name="TextAppearance.ConditionCardTitle"
+ parent="@android:style/TextAppearance.Material.Body2">
+ <item name="android:textSize">16sp</item>
+ </style>
+
+ <style name="TextAppearance.ConditionCardSummary"
+ parent="@android:style/TextAppearance.Material.Body1">
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ </style>
+
<style name="TextAppearance.EntityHeaderTitle"
parent="@android:style/TextAppearance.Material.Subhead">
<item name="android:textColor">?android:attr/textColorPrimary</item>
@@ -463,4 +473,24 @@
<item name="cardElevation">@dimen/homepage_card_elevation</item>
</style>
+ <style name="ConditionCardBorderlessButton"
+ parent="android:Widget.DeviceDefault.Button.Borderless">
+ <item name="android:textColor">?android:attr/colorAccent</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textAllCaps">false</item>
+ <item name="android:fontFamily">sans-serif-medium</item>
+ </style>
+
+ <style name="ConditionHalfCardBorderlessButton"
+ parent="@style/ConditionCardBorderlessButton">
+ <item name="android:textAlignment">viewStart</item>
+ <item name="android:paddingStart">0dp</item>
+ </style>
+
+ <style name="ConditionFullCardBorderlessButton"
+ parent="@style/ConditionCardBorderlessButton">
+ <item name="android:textAlignment">viewEnd</item>
+ <item name="android:paddingEnd">0dp</item>
+ </style>
+
</resources>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 3d08cd8..6528cf7 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -513,6 +513,11 @@
<Preference
android:key="reset_shortcut_manager_throttling"
android:title="@string/reset_shortcut_manager_throttling" />
+
+ <SwitchPreference
+ android:key="sms_access_restriction_enabled"
+ android:title="@string/sms_access_restriction_enabled"
+ android:summary="@string/sms_access_restriction_enabled_summary" />
</PreferenceCategory>
<com.android.settings.development.autofill.AutofillPreferenceCategory
diff --git a/res/xml/installed_app_details.xml b/res/xml/installed_app_details.xml
deleted file mode 100644
index 42822c0..0000000
--- a/res/xml/installed_app_details.xml
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:key="installed_app_detail_settings_screen"
- app:initialExpandedChildrenCount="6">
-
- <com.android.settings.applications.LayoutPreference
- android:key="header_view"
- android:layout="@layout/settings_entity_header"
- android:selectable="false"
- android:order="-10000"/>
-
- <com.android.settings.applications.LayoutPreference
- android:key="instant_app_buttons"
- android:layout="@layout/instant_app_buttons"
- android:selectable="false"
- android:order="-9999"/>
-
- <com.android.settings.widget.ActionButtonPreference
- android:key="action_buttons"
- android:order="-9998" />
-
- <Preference
- android:key="notification_settings"
- android:title="@string/notifications_label"
- android:selectable="true"/>
-
- <com.android.settings.widget.FixedLineSummaryPreference
- android:key="permission_settings"
- android:title="@string/permissions_label"
- android:summary="@string/summary_placeholder"
- android:selectable="true"
- app:summaryLineCount="1" />
-
- <Preference
- android:key="storage_settings"
- android:title="@string/storage_settings"
- android:summary="@string/summary_placeholder"
- android:selectable="true"/>
-
- <com.android.settings.applications.AppDomainsPreference
- android:key="instant_app_launch_supported_domain_urls"
- android:title="@string/app_launch_supported_domain_urls_title"
- android:selectable="true" />
-
- <Preference
- android:key="data_settings"
- android:title="@string/data_usage_summary_title"
- android:summary="@string/summary_placeholder"
- android:selectable="true"/>
-
- <Preference
- android:key="battery"
- android:title="@string/power_usage_summary_title"
- android:summary="@string/summary_placeholder"
- android:selectable="true"/>
-
- <Preference
- android:key="preferred_settings"
- android:title="@string/launch_by_default"
- android:summary="@string/summary_placeholder"
- android:selectable="true"/>
-
- <Preference
- android:key="memory"
- android:title="@string/memory_settings_title"
- android:summary="@string/summary_placeholder"
- android:enabled="false"
- android:selectable="true"/>
-
- <Preference
- android:key="app_version"
- android:selectable="false"
- android:order="9999"/>
-
-</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/prevent_ringing_gesture_settings.xml b/res/xml/prevent_ringing_gesture_settings.xml
index 5135664..62f0223 100644
--- a/res/xml/prevent_ringing_gesture_settings.xml
+++ b/res/xml/prevent_ringing_gesture_settings.xml
@@ -26,13 +26,8 @@
app:animation="@raw/gesture_prevent_ringing"
app:preview="@drawable/gesture_prevent_ringing" />
- <ListPreference
- android:key="gesture_prevent_ringing"
- android:title="@string/gesture_prevent_ringing_title"
- android:entries="@array/gesture_prevent_ringing_entries"
- android:entryValues="@array/gesture_prevent_ringing_values"
- app:controller="com.android.settings.gestures.PreventRingingPreferenceController"
- app:keywords="@string/keywords_gesture"
- app:allowDividerAbove="true" />
-
+ <PreferenceCategory
+ android:key="gesture_prevent_ringing_category"
+ android:title="@string/gesture_prevent_ringing_title">
+ </PreferenceCategory>
</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml
index e543ad9..ce271cc 100644
--- a/res/xml/security_dashboard_settings.xml
+++ b/res/xml/security_dashboard_settings.xml
@@ -95,12 +95,6 @@
android:key="security_settings_misc_category"
android:title="@string/security_passwords_title">
- <Preference
- android:key="location"
- android:title="@string/location_settings_title"
- android:summary="@string/summary_placeholder"
- android:fragment="com.android.settings.location.LocationSettings" />
-
<SwitchPreference
android:key="show_password"
android:title="@string/show_password"
diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml
index e11d84a..b5930e4 100644
--- a/res/xml/top_level_settings.xml
+++ b/res/xml/top_level_settings.xml
@@ -26,7 +26,7 @@
android:title="@string/network_dashboard_title"
android:summary="@string/summary_placeholder"
android:icon="@drawable/ic_homepage_network"
- android:order="-110"
+ android:order="-120"
android:fragment="com.android.settings.network.NetworkDashboardFragment"
settings:controller="com.android.settings.network.TopLevelNetworkEntryPreferenceController"/>
@@ -35,7 +35,7 @@
android:title="@string/connected_devices_dashboard_title"
android:summary="@string/summary_placeholder"
android:icon="@drawable/ic_homepage_connected_device"
- android:order="-100"
+ android:order="-110"
android:fragment="com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment"
settings:controller="com.android.settings.connecteddevice.TopLevelConnectedDevicesPreferenceController"/>
@@ -44,7 +44,7 @@
android:title="@string/app_and_notification_dashboard_title"
android:summary="@string/app_and_notification_dashboard_summary"
android:icon="@drawable/ic_homepage_apps"
- android:order="-90"
+ android:order="-100"
android:fragment="com.android.settings.applications.AppAndNotificationDashboardFragment"/>
<Preference
@@ -53,7 +53,7 @@
android:summary="@string/summary_placeholder"
android:icon="@drawable/ic_homepage_battery"
android:fragment="com.android.settings.fuelgauge.PowerUsageSummary"
- android:order="-80"
+ android:order="-90"
settings:controller="com.android.settings.fuelgauge.TopLevelBatteryPreferenceController"/>
<Preference
@@ -61,7 +61,7 @@
android:title="@string/display_settings"
android:summary="@string/summary_placeholder"
android:icon="@drawable/ic_homepage_display"
- android:order="-70"
+ android:order="-80"
android:fragment="com.android.settings.DisplaySettings"
settings:controller="com.android.settings.display.TopLevelDisplayPreferenceController"/>
@@ -70,7 +70,7 @@
android:title="@string/sound_settings"
android:summary="@string/sound_dashboard_summary"
android:icon="@drawable/ic_homepage_sound"
- android:order="-60"
+ android:order="-70"
android:fragment="com.android.settings.notification.SoundSettings"/>
<Preference
@@ -78,11 +78,19 @@
android:title="@string/storage_settings"
android:summary="@string/summary_placeholder"
android:icon="@drawable/ic_homepage_storage"
- android:order="-50"
+ android:order="-60"
android:fragment="com.android.settings.deviceinfo.StorageSettings"
settings:controller="com.android.settings.deviceinfo.TopLevelStoragePreferenceController"/>
<Preference
+ android:key="top_level_location"
+ android:title="@string/location_settings_title"
+ android:summary="@string/location_settings_summary"
+ android:icon="@drawable/ic_homepage_location"
+ android:order="-50"
+ android:fragment="com.android.settings.location.LocationSettings"/>
+
+ <Preference
android:key="top_level_security"
android:title="@string/security_settings_title"
android:summary="@string/summary_placeholder"
diff --git a/res/xml/wifi_settings.xml b/res/xml/wifi_settings.xml
index 4ca9284..516ac0a 100644
--- a/res/xml/wifi_settings.xml
+++ b/res/xml/wifi_settings.xml
@@ -20,6 +20,9 @@
android:title="@string/wifi_settings"
settings:keywords="@string/keywords_wifi">
+ <com.android.settings.wifi.LinkablePreference
+ android:key="wifi_status_message"/>
+
<PreferenceCategory
android:key="connected_access_point"
android:layout="@layout/preference_category_no_label"/>
@@ -28,17 +31,14 @@
android:key="access_points"
android:layout="@layout/preference_category_no_label"/>
- <PreferenceCategory
- android:key="additional_settings"
- android:layout="@layout/preference_category_no_label">
- <Preference
- android:key="configure_settings"
- android:title="@string/wifi_configure_settings_preference_title"
- android:fragment="com.android.settings.wifi.ConfigureWifiSettings" />
+ <Preference
+ android:key="configure_settings"
+ android:title="@string/wifi_configure_settings_preference_title"
+ settings:allowDividerAbove="true"
+ android:fragment="com.android.settings.wifi.ConfigureWifiSettings"/>
- <Preference
- android:key="saved_networks"
- android:title="@string/wifi_saved_access_points_label"
- android:fragment="com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings" />
- </PreferenceCategory>
+ <Preference
+ android:key="saved_networks"
+ android:title="@string/wifi_saved_access_points_label"
+ android:fragment="com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings"/>
</PreferenceScreen>
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 14a9e83..79caefe 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -979,4 +979,14 @@
return packageManager.getDefaultActivityIcon();
}
}
+
+ /** Returns true if the current package is installed & enabled. */
+ public static boolean isPackageEnabled(Context context, String packageName) {
+ try {
+ return context.getPackageManager().getApplicationInfo(packageName, 0).enabled;
+ } catch (Exception e) {
+ Log.e(TAG, "Error while retrieving application info for package " + packageName, e);
+ }
+ return false;
+ }
}
diff --git a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
index 18e9906..78a8614 100644
--- a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
@@ -92,18 +92,18 @@
@VisibleForTesting
void finishIfAccountMissing() {
- AccountManager accountManager = (AccountManager) getContext().getSystemService(
- Context.ACCOUNT_SERVICE);
- boolean accountExists = false;
- for (Account account : accountManager.getAccountsByType(mAccount.type)) {
- if (account.equals(mAccount)) {
- accountExists = true;
- break;
+ final Context context = getContext();
+ final UserManager um = context.getSystemService(UserManager.class);
+ final AccountManager accountManager = (AccountManager) context.getSystemService(
+ AccountManager.class);
+ for (UserHandle userHandle : um.getUserProfiles()) {
+ for (Account account : accountManager.getAccountsAsUser(userHandle.getIdentifier())) {
+ if (account.equals(mAccount)) {
+ return;
+ }
}
}
- if (!accountExists) {
- finish();
- }
+ finish();
}
@Override
@@ -177,4 +177,4 @@
accountTypePreferenceLoader.updatePreferenceIntents(prefs, mAccountType, mAccount);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/accounts/AvatarViewMixin.java b/src/com/android/settings/accounts/AvatarViewMixin.java
new file mode 100644
index 0000000..d7f6f8a
--- /dev/null
+++ b/src/com/android/settings/accounts/AvatarViewMixin.java
@@ -0,0 +1,60 @@
+/*
+ * 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.accounts;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.widget.ImageView;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+
+import com.android.settings.R;
+import com.android.settings.homepage.SettingsHomepageActivity;
+import com.android.settings.overlay.FeatureFactory;
+
+/**
+ * Avatar related work to the onStart method of registered observable classes
+ * in {@link SettingsHomepageActivity}.
+ */
+public class AvatarViewMixin implements LifecycleObserver {
+ private Context mContext;
+ private ImageView mAvatarView;
+
+ public AvatarViewMixin(Context context, ImageView avatarView) {
+ mContext = context.getApplicationContext();
+ mAvatarView = avatarView;
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_START)
+ public void onStart() {
+ if (hasAccount()) {
+ //TODO(b/117509285): To migrate account icon on search bar
+ } else {
+ mAvatarView.setImageResource(R.drawable.ic_account_circle_24dp);
+ }
+ }
+
+ @VisibleForTesting
+ boolean hasAccount() {
+ final Account accounts[] = FeatureFactory.getFactory(
+ mContext).getAccountFeatureProvider().getAccounts(mContext);
+ return (accounts != null) && (accounts.length > 0);
+ }
+}
diff --git a/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java b/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
index a4cfebf..70ffcb3 100644
--- a/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
@@ -21,6 +21,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.provider.Settings;
import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
@@ -34,8 +35,7 @@
public class TimeSpentInAppPreferenceController extends BasePreferenceController {
@VisibleForTesting
- static final Intent SEE_TIME_IN_APP_TEMPLATE =
- new Intent("com.android.settings.action.TIME_SPENT_IN_APP");
+ static final Intent SEE_TIME_IN_APP_TEMPLATE = new Intent(Settings.ACTION_APP_USAGE_SETTINGS);
private final PackageManager mPackageManager;
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index dbcb389..82c9828 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -458,6 +458,7 @@
controllers.add(new AllowAppsOnExternalPreferenceController(context));
controllers.add(new ResizableActivityPreferenceController(context));
controllers.add(new FreeformWindowsPreferenceController(context));
+ controllers.add(new SmsAccessRestrictionPreferenceController(context));
controllers.add(new ShortcutManagerThrottlingPreferenceController(context));
controllers.add(new EnableGnssRawMeasFullTrackingPreferenceController(context));
controllers.add(new CbrsDataSwitchPreferenceController(context));
diff --git a/src/com/android/settings/development/SmsAccessRestrictionPreferenceController.java b/src/com/android/settings/development/SmsAccessRestrictionPreferenceController.java
new file mode 100644
index 0000000..b3f7b23
--- /dev/null
+++ b/src/com/android/settings/development/SmsAccessRestrictionPreferenceController.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+// STOPSHIP b/118694572: remove the kill switch once the feature is tested and stable
+public class SmsAccessRestrictionPreferenceController extends DeveloperOptionsPreferenceController
+ implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+ private static final String SMS_ACCESS_RESTRICTION_ENABLED_KEY
+ = "sms_access_restriction_enabled";
+
+ public SmsAccessRestrictionPreferenceController(Context context) {
+ super(context);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return SMS_ACCESS_RESTRICTION_ENABLED_KEY;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ writeSetting((boolean) newValue);
+ return true;
+ }
+
+ private void writeSetting(boolean isEnabled) {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED,
+ isEnabled ? 1 : 0);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0);
+ ((SwitchPreference) mPreference).setChecked(mode != 0);
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ writeSetting(false);
+ ((SwitchPreference) mPreference).setChecked(false);
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
index 2d95c31..65181c4 100644
--- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
@@ -63,7 +63,7 @@
implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy {
@VisibleForTesting
static final boolean USE_FAKE_DATA = false;
- private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10;
+ private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 20;
private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
private static final int STATS_TYPE = BatteryStats.STATS_SINCE_CHARGED;
diff --git a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
index 069085b..2e9b5a5 100644
--- a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
+++ b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
@@ -20,8 +20,6 @@
import android.content.Context;
import android.provider.Settings;
-import androidx.annotation.NonNull;
-
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
@@ -31,6 +29,8 @@
import java.util.ArrayList;
import java.util.List;
+import androidx.annotation.NonNull;
+
public class GesturesSettingPreferenceController extends BasePreferenceController {
private final AssistGestureFeatureProvider mFeatureProvider;
private List<AbstractPreferenceController> mGestureControllers;
@@ -76,7 +76,7 @@
.setConfig(ambientDisplayConfiguration));
controllers.add(new DoubleTapScreenPreferenceController(context, FAKE_PREF_KEY)
.setConfig(ambientDisplayConfiguration));
- controllers.add(new PreventRingingPreferenceController(context, FAKE_PREF_KEY));
+ controllers.add(new PreventRingingParentPreferenceController(context, FAKE_PREF_KEY));
return controllers;
}
diff --git a/src/com/android/settings/gestures/PreventRingingGesturePreferenceController.java b/src/com/android/settings/gestures/PreventRingingGesturePreferenceController.java
new file mode 100644
index 0000000..cb9bf4f
--- /dev/null
+++ b/src/com/android/settings/gestures/PreventRingingGesturePreferenceController.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.provider.Settings;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.widget.RadioButtonPreference;
+import com.android.settings.widget.VideoPreference;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnCreate;
+import com.android.settingslib.core.lifecycle.events.OnPause;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
+public class PreventRingingGesturePreferenceController extends AbstractPreferenceController
+ implements RadioButtonPreference.OnClickListener, LifecycleObserver, OnSaveInstanceState,
+ OnResume, OnPause, OnCreate, PreferenceControllerMixin {
+
+ @VisibleForTesting static final String KEY_VIBRATE = "prevent_ringing_option_vibrate";
+ @VisibleForTesting static final String KEY_NONE = "prevent_ringing_option_none";
+ @VisibleForTesting static final String KEY_MUTE = "prevent_ringing_option_mute";
+
+ private final String KEY_VIDEO_PAUSED = "key_video_paused";
+ private final String PREF_KEY_VIDEO = "gesture_prevent_ringing_video";
+ private final String KEY = "gesture_prevent_ringing_category";
+ private final Context mContext;
+
+ private VideoPreference mVideoPreference;
+ private boolean mVideoPaused;
+
+ private PreferenceCategory mPreferenceCategory;
+ @VisibleForTesting RadioButtonPreference mVibratePref;
+ @VisibleForTesting RadioButtonPreference mNonePref;
+ @VisibleForTesting RadioButtonPreference mMutePref;
+
+ private SettingObserver mSettingObserver;
+
+ public PreventRingingGesturePreferenceController(Context context, Lifecycle lifecycle) {
+ super(context);
+ mContext = context;
+
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ if (isAvailable()) {
+ mPreferenceCategory = (PreferenceCategory) screen.findPreference(getPreferenceKey());
+ mVibratePref = makeRadioPreference(KEY_VIBRATE, R.string.prevent_ringing_option_vibrate);
+ mMutePref = makeRadioPreference(KEY_MUTE, R.string.prevent_ringing_option_mute);
+ mNonePref = makeRadioPreference(KEY_NONE, R.string.prevent_ringing_option_none);
+
+ if (mPreferenceCategory != null) {
+ mSettingObserver = new SettingObserver(mPreferenceCategory);
+ }
+
+ mVideoPreference = (VideoPreference) screen.findPreference(getVideoPrefKey());
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_volumeHushGestureEnabled);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ public String getVideoPrefKey() {
+ return PREF_KEY_VIDEO;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putBoolean(KEY_VIDEO_PAUSED, mVideoPaused);
+ }
+
+ @Override
+ public void onRadioButtonClicked(RadioButtonPreference preference) {
+ int preventRingingSetting = keyToSetting(preference.getKey());
+ if (preventRingingSetting != Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_VIBRATE)) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.VOLUME_HUSH_GESTURE, preventRingingSetting);
+ }
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ int preventRingingSetting = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_VIBRATE);
+
+ final boolean isVibrate = preventRingingSetting == Settings.Secure.VOLUME_HUSH_VIBRATE;
+ final boolean isMute = preventRingingSetting == Settings.Secure.VOLUME_HUSH_MUTE;
+ final boolean isOff = preventRingingSetting == Settings.Secure.VOLUME_HUSH_OFF
+ || (!isVibrate && !isMute);
+ if (mVibratePref != null && mVibratePref.isChecked() != isVibrate) {
+ mVibratePref.setChecked(isVibrate);
+ }
+ if (mMutePref != null && mMutePref.isChecked() != isMute) {
+ mMutePref.setChecked(isMute);
+ }
+ if (mNonePref != null && mNonePref.isChecked() != isOff) {
+ mNonePref.setChecked(isOff);
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ if (savedInstanceState != null) {
+ mVideoPaused = savedInstanceState.getBoolean(KEY_VIDEO_PAUSED, false);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ if (mSettingObserver != null) {
+ mSettingObserver.register(mContext.getContentResolver());
+ mSettingObserver.onChange(false, null);
+ }
+
+ if (mVideoPreference != null) {
+ mVideoPreference.onViewVisible(mVideoPaused);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ if (mSettingObserver != null) {
+ mSettingObserver.unregister(mContext.getContentResolver());
+ }
+
+ if (mVideoPreference != null) {
+ mVideoPaused = mVideoPreference.isVideoPaused();
+ mVideoPreference.onViewInvisible();
+ }
+ }
+
+ private int keyToSetting(String key) {
+ switch (key) {
+ case KEY_NONE:
+ return Settings.Secure.VOLUME_HUSH_OFF;
+ case KEY_MUTE:
+ return Settings.Secure.VOLUME_HUSH_MUTE;
+ case KEY_VIBRATE:
+ default:
+ return Settings.Secure.VOLUME_HUSH_VIBRATE;
+ }
+ }
+
+ private RadioButtonPreference makeRadioPreference(String key, int titleId) {
+ RadioButtonPreference pref = new RadioButtonPreference(mPreferenceCategory.getContext());
+ pref.setKey(key);
+ pref.setTitle(titleId);
+ pref.setOnClickListener(this);
+ mPreferenceCategory.addPreference(pref);
+ return pref;
+ }
+
+ private class SettingObserver extends ContentObserver {
+ private final Uri VOLUME_HUSH_GESTURE = Settings.Secure.getUriFor(
+ Settings.Secure.VOLUME_HUSH_GESTURE);
+
+ private final Preference mPreference;
+
+ public SettingObserver(Preference preference) {
+ super(new Handler());
+ mPreference = preference;
+ }
+
+ public void register(ContentResolver cr) {
+ cr.registerContentObserver(VOLUME_HUSH_GESTURE, false, this);
+ }
+
+ public void unregister(ContentResolver cr) {
+ cr.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ if (uri == null || VOLUME_HUSH_GESTURE.equals(uri)) {
+ updateState(mPreference);
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/gestures/PreventRingingGestureSettings.java b/src/com/android/settings/gestures/PreventRingingGestureSettings.java
index 84b4e16..3e8ae85 100644
--- a/src/com/android/settings/gestures/PreventRingingGestureSettings.java
+++ b/src/com/android/settings/gestures/PreventRingingGestureSettings.java
@@ -23,8 +23,11 @@
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
+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;
@@ -40,6 +43,18 @@
}
@Override
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, getSettingsLifecycle());
+ }
+
+ private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
+ Lifecycle lifecycle) {
+ List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new PreventRingingGesturePreferenceController(context, lifecycle));
+ return controllers;
+ }
+
+ @Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.SETTINGS_PREVENT_RINGING;
}
@@ -68,6 +83,12 @@
sir.xmlResId = R.xml.prevent_ringing_gesture_settings;
return Arrays.asList(sir);
}
+
+ @Override
+ public List<AbstractPreferenceController> createPreferenceControllers(
+ Context context) {
+ return buildPreferenceControllers(context, null);
+ }
};
}
diff --git a/src/com/android/settings/gestures/PreventRingingPreferenceController.java b/src/com/android/settings/gestures/PreventRingingPreferenceController.java
deleted file mode 100644
index 570c1c6..0000000
--- a/src/com/android/settings/gestures/PreventRingingPreferenceController.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
-import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
-import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.provider.Settings;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.widget.VideoPreference;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnCreate;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
-import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
-
-public class PreventRingingPreferenceController extends PreventRingingParentPreferenceController
- implements Preference.OnPreferenceChangeListener,
- LifecycleObserver, OnResume, OnPause, OnCreate, OnSaveInstanceState {
-
- private static final String PREF_KEY_VIDEO = "gesture_prevent_ringing_video";
- @VisibleForTesting
- static final String KEY_VIDEO_PAUSED = "key_video_paused";
-
- private VideoPreference mVideoPreference;
- @VisibleForTesting
- boolean mVideoPaused;
-
- public PreventRingingPreferenceController(Context context, String key) {
- super(context, key);
- }
-
- @Override
- public int getAvailabilityStatus() {
- final int status = super.getAvailabilityStatus();
- if (status == AVAILABLE_UNSEARCHABLE) {
- return AVAILABLE;
- }
- return status;
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- if (isAvailable()) {
- mVideoPreference = (VideoPreference) screen.findPreference(getVideoPrefKey());
- }
- }
-
- @Override
- public void updateState(Preference preference) {
- super.updateState(preference);
- if (preference != null) {
- if (preference instanceof ListPreference) {
- ListPreference pref = (ListPreference) preference;
- int value = Settings.Secure.getInt(
- mContext.getContentResolver(), SECURE_KEY, VOLUME_HUSH_VIBRATE);
- switch (value) {
- case VOLUME_HUSH_VIBRATE:
- pref.setValue(String.valueOf(value));
- break;
- case VOLUME_HUSH_MUTE:
- pref.setValue(String.valueOf(value));
- break;
- default:
- pref.setValue(String.valueOf(VOLUME_HUSH_OFF));
- }
- }
- }
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- if (savedInstanceState != null) {
- mVideoPaused = savedInstanceState.getBoolean(KEY_VIDEO_PAUSED, false);
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- outState.putBoolean(KEY_VIDEO_PAUSED, mVideoPaused);
- }
-
- @Override
- public void onPause() {
- if (mVideoPreference != null) {
- mVideoPaused = mVideoPreference.isVideoPaused();
- mVideoPreference.onViewInvisible();
- }
- }
-
- @Override
- public void onResume() {
- if (mVideoPreference != null) {
- mVideoPreference.onViewVisible(mVideoPaused);
- }
- }
-
- protected String getVideoPrefKey() {
- return PREF_KEY_VIDEO;
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- int value = Integer.parseInt((String) newValue);
- Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY, value);
- preference.setSummary(getSummary());
- return true;
- }
-}
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index c10543d..d3f11a0 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -19,6 +19,7 @@
import android.content.Intent;
import android.os.Bundle;
import android.util.FeatureFlagUtils;
+import android.widget.ImageView;
import android.widget.Toolbar;
import androidx.fragment.app.Fragment;
@@ -27,6 +28,7 @@
import com.android.settings.R;
import com.android.settings.SettingsActivity;
+import com.android.settings.accounts.AvatarViewMixin;
import com.android.settings.core.FeatureFlags;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
@@ -51,6 +53,10 @@
FeatureFactory.getFactory(this).getSearchFeatureProvider()
.initSearchToolbar(this, toolbar);
+ final ImageView avatarView = findViewById(R.id.account_avatar);
+ final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);
+ getLifecycle().addObserver(avatarViewMixin);
+
showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
showFragment(new TopLevelSettings(), R.id.main_content);
}
diff --git a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
index 11ab8d8..0065f5c 100644
--- a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
+++ b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
@@ -16,6 +16,7 @@
package com.android.settings.homepage.contextualcards;
+import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
@@ -30,7 +31,7 @@
public class CardDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "CardDatabaseHelper";
private static final String DATABASE_NAME = "homepage_cards.db";
- private static final int DATABASE_VERSION = 3;
+ private static final int DATABASE_VERSION = 5;
public static final String CARD_TABLE = "cards";
@@ -56,7 +57,7 @@
String SLICE_URI = "slice_uri";
/**
- * Category of the card. The value is between 0 to 3.
+ * Category of the card.
*/
String CATEGORY = "category";
@@ -119,6 +120,11 @@
* Decide the card display full-length width or half-width in screen.
*/
String SUPPORT_HALF_WIDTH = "support_half_width";
+
+ /**
+ * Decide the card is dismissed or not.
+ */
+ String CARD_DISMISSED = "card_dismissed";
}
private static final String CREATE_CARD_TABLE =
@@ -133,11 +139,7 @@
CardColumns.SLICE_URI +
" TEXT, " +
CardColumns.CATEGORY +
- " INTEGER DEFAULT 0 CHECK (" +
- CardColumns.CATEGORY +
- " >= 0 AND " +
- CardColumns.CATEGORY +
- " <= 3), " +
+ " INTEGER DEFAULT 0, " +
CardColumns.LOCALIZED_TO_LOCALE +
" TEXT, " +
CardColumns.PACKAGE_NAME +
@@ -161,6 +163,8 @@
CardColumns.EXPIRE_TIME_MS +
" INTEGER, " +
CardColumns.SUPPORT_HALF_WIDTH +
+ " INTEGER DEFAULT 0, " +
+ CardColumns.CARD_DISMISSED +
" INTEGER DEFAULT 0 " +
");";
@@ -194,9 +198,27 @@
Cursor getContextualCards() {
final SQLiteDatabase db = this.getReadableDatabase();
- Cursor cursor = db.query(CARD_TABLE, null /* columns */, null /* selection */,
+ final String selection = CardColumns.CARD_DISMISSED + "=0";
+ Cursor cursor = db.query(CARD_TABLE, null /* columns */, selection,
null /* selectionArgs */, null /* groupBy */, null /* having */,
null /* orderBy */);
return cursor;
}
+
+ /**
+ * Mark a specific ContextualCard with dismissal flag in the database to indicate that the
+ * card has been dismissed.
+ *
+ * @param cardName the card name of the ContextualCard which is dismissed by user.
+ * @return updated row number
+ */
+ public int markContextualCardAsDismissed(String cardName) {
+ final SQLiteDatabase database = this.getWritableDatabase();
+ final ContentValues values = new ContentValues();
+ values.put(CardColumns.CARD_DISMISSED, 1);
+ final String selection = CardColumns.NAME + "=?";
+ final String[] selectionArgs = {cardName};
+ final int rowsUpdated = database.update(CARD_TABLE, values, selection, selectionArgs);
+ return rowsUpdated;
+ }
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCard.java b/src/com/android/settings/homepage/contextualcards/ContextualCard.java
index 996c2dd..b0dfad8 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCard.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCard.java
@@ -42,6 +42,7 @@
int CONDITIONAL = 3;
}
+ private final Builder mBuilder;
private final String mName;
@CardType
private final int mCardType;
@@ -142,7 +143,12 @@
return TextUtils.isEmpty(mSliceUri);
}
+ public Builder mutate() {
+ return mBuilder;
+ }
+
public ContextualCard(Builder builder) {
+ mBuilder = builder;
mName = builder.mName;
mCardType = builder.mCardType;
mRankingScore = builder.mRankingScore;
@@ -164,28 +170,47 @@
}
ContextualCard(Cursor c) {
+ mBuilder = new Builder();
mName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.NAME));
+ mBuilder.setName(mName);
mCardType = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.TYPE));
+ mBuilder.setCardType(mCardType);
mRankingScore = c.getDouble(c.getColumnIndex(CardDatabaseHelper.CardColumns.SCORE));
+ mBuilder.setRankingScore(mRankingScore);
mSliceUri = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.SLICE_URI));
+ mBuilder.setSliceUri(Uri.parse(mSliceUri));
mCategory = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.CATEGORY));
+ mBuilder.setCategory(mCategory);
mLocalizedToLocale = c.getString(
c.getColumnIndex(CardDatabaseHelper.CardColumns.LOCALIZED_TO_LOCALE));
+ mBuilder.setLocalizedToLocale(mLocalizedToLocale);
mPackageName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.PACKAGE_NAME));
+ mBuilder.setPackageName(mPackageName);
mAppVersion = c.getLong(c.getColumnIndex(CardDatabaseHelper.CardColumns.APP_VERSION));
+ mBuilder.setAppVersion(mAppVersion);
mTitleResName = c.getString(
c.getColumnIndex(CardDatabaseHelper.CardColumns.TITLE_RES_NAME));
+ mBuilder.setTitleResName(mTitleResName);
mTitleText = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.TITLE_TEXT));
+ mBuilder.setTitleText(mTitleText);
mSummaryResName = c.getString(
c.getColumnIndex(CardDatabaseHelper.CardColumns.SUMMARY_RES_NAME));
+ mBuilder.setSummaryResName(mSummaryResName);
mSummaryText = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.SUMMARY_TEXT));
+ mBuilder.setSummaryText(mSummaryText);
mIconResName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.ICON_RES_NAME));
+ mBuilder.setIconResName(mIconResName);
mIconResId = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.ICON_RES_ID));
+ mBuilder.setIconResId(mIconResId);
mCardAction = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.CARD_ACTION));
+ mBuilder.setCardAction(mCardAction);
mExpireTimeMS = c.getLong(c.getColumnIndex(CardDatabaseHelper.CardColumns.EXPIRE_TIME_MS));
+ mBuilder.setExpireTimeMS(mExpireTimeMS);
mIsHalfWidth = (c.getInt(
c.getColumnIndex(CardDatabaseHelper.CardColumns.SUPPORT_HALF_WIDTH)) == 1);
+ mBuilder.setIsHalfWidth(mIsHalfWidth);
mIconDrawable = null;
+ mBuilder.setIconDrawable(mIconDrawable);
}
@Override
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java
index 0268fb0..2253a2f 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java
@@ -16,43 +16,61 @@
package com.android.settings.homepage.contextualcards;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
import com.android.settings.homepage.contextualcards.ContextualCard.CardType;
import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardController;
import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer;
import com.android.settings.homepage.contextualcards.slices.SliceContextualCardController;
import com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer;
+import java.util.Comparator;
+import java.util.List;
import java.util.Set;
import java.util.TreeSet;
+import java.util.stream.Collectors;
public class ContextualCardLookupTable {
-
+ private static final String TAG = "ContextualCardLookup";
static class ControllerRendererMapping implements Comparable<ControllerRendererMapping> {
@CardType
- private final int mCardType;
- private final Class<? extends ContextualCardController> mControllerClass;
- private final Class<? extends ContextualCardRenderer> mRendererClass;
+ final int mCardType;
+ final int mViewType;
+ final Class<? extends ContextualCardController> mControllerClass;
+ final Class<? extends ContextualCardRenderer> mRendererClass;
- private ControllerRendererMapping(@CardType int cardType,
+ ControllerRendererMapping(@CardType int cardType, int viewType,
Class<? extends ContextualCardController> controllerClass,
Class<? extends ContextualCardRenderer> rendererClass) {
mCardType = cardType;
+ mViewType = viewType;
mControllerClass = controllerClass;
mRendererClass = rendererClass;
}
@Override
public int compareTo(ControllerRendererMapping other) {
- return Integer.compare(this.mCardType, other.mCardType);
+ return Comparator.comparingInt((ControllerRendererMapping mapping) -> mapping.mCardType)
+ .thenComparingInt(mapping -> mapping.mViewType)
+ .compare(this, other);
}
}
- private static final Set<ControllerRendererMapping> LOOKUP_TABLE =
+ @VisibleForTesting
+ static final Set<ControllerRendererMapping> LOOKUP_TABLE =
new TreeSet<ControllerRendererMapping>() {{
add(new ControllerRendererMapping(CardType.CONDITIONAL,
+ ConditionContextualCardRenderer.HALF_WIDTH_VIEW_TYPE,
+ ConditionContextualCardController.class,
+ ConditionContextualCardRenderer.class));
+ add(new ControllerRendererMapping(CardType.CONDITIONAL,
+ ConditionContextualCardRenderer.FULL_WIDTH_VIEW_TYPE,
ConditionContextualCardController.class,
ConditionContextualCardRenderer.class));
add(new ControllerRendererMapping(CardType.SLICE,
+ SliceContextualCardRenderer.VIEW_TYPE,
SliceContextualCardController.class,
SliceContextualCardRenderer.class));
}};
@@ -67,14 +85,27 @@
return null;
}
- //TODO(b/112578070): Implement multi renderer cases.
- public static Class<? extends ContextualCardRenderer> getCardRendererClasses(
+ public static Class<? extends ContextualCardRenderer> getCardRendererClassByCardType(
@CardType int cardType) {
- for (ControllerRendererMapping mapping : LOOKUP_TABLE) {
- if (mapping.mCardType == cardType) {
- return mapping.mRendererClass;
- }
+ return LOOKUP_TABLE.stream()
+ .filter(m -> m.mCardType == cardType)
+ .findFirst()
+ .map(mapping -> mapping.mRendererClass)
+ .orElse(null);
+ }
+
+ public static Class<? extends ContextualCardRenderer> getCardRendererClassByViewType(
+ int viewType) throws IllegalStateException {
+ List<ControllerRendererMapping> validMappings = LOOKUP_TABLE.stream()
+ .filter(m -> m.mViewType == viewType).collect(Collectors.toList());
+ if (validMappings == null || validMappings.isEmpty()) {
+ Log.w(TAG, "No matching mapping");
+ return null;
}
- return null;
+ if (validMappings.size() != 1) {
+ throw new IllegalStateException("Have duplicate VIEW_TYPE in lookup table.");
+ }
+
+ return validMappings.get(0).mRendererClass;
}
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 51bef87..9bd08c8 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -84,7 +84,7 @@
final CardContentLoaderCallbacks cardContentLoaderCallbacks =
new CardContentLoaderCallbacks(mContext);
cardContentLoaderCallbacks.setListener(this);
- LoaderManager.getInstance(fragment).initLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
+ LoaderManager.getInstance(fragment).restartLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
cardContentLoaderCallbacks);
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/ContextualCardRenderer.java
index 689b572..bb85bd2 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardRenderer.java
@@ -26,9 +26,9 @@
public interface ContextualCardRenderer {
/**
- * The layout type of the controller.
+ * The layout type of the renderer.
*/
- int getViewType();
+ int getViewType(boolean isHalfWidth);
/**
* When {@link ContextualCardsAdapter} calls {@link ContextualCardsAdapter#onCreateViewHolder},
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
index 865d242..0a8749d 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
@@ -61,26 +61,26 @@
@Override
public int getItemViewType(int position) {
- return mContextualCards.get(position).getCardType();
+ final ContextualCard card = mContextualCards.get(position);
+ final ContextualCardRenderer renderer = mControllerRendererPool.getRendererByCardType(
+ mContext, mLifecycleOwner, card.getCardType());
+ return renderer.getViewType(card.isHalfWidth());
}
@Override
- public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int cardType) {
- final ContextualCardRenderer renderer = mControllerRendererPool.getRenderer(mContext,
- mLifecycleOwner, cardType);
- final int viewType = renderer.getViewType();
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ final ContextualCardRenderer renderer = mControllerRendererPool.getRendererByViewType(
+ mContext, mLifecycleOwner, viewType);
final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
-
return renderer.createViewHolder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
- final int cardType = mContextualCards.get(position).getCardType();
- final ContextualCardRenderer renderer = mControllerRendererPool.getRenderer(mContext,
- mLifecycleOwner, cardType);
-
- renderer.bindView(holder, mContextualCards.get(position));
+ final ContextualCard card = mContextualCards.get(position);
+ final ContextualCardRenderer renderer = mControllerRendererPool.getRendererByCardType(
+ mContext, mLifecycleOwner, card.getCardType());
+ renderer.bindView(holder, card);
}
@Override
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
index d82fdfe..29eea4b 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
@@ -43,6 +43,11 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContextualCardManager = new ContextualCardManager(getContext(), getSettingsLifecycle());
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
mContextualCardManager.loadContextualCards(this);
}
diff --git a/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java b/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java
index 212b6be..8e59f46 100644
--- a/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java
+++ b/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java
@@ -16,12 +16,14 @@
package com.android.settings.homepage.contextualcards;
+import android.annotation.NonNull;
import android.content.Context;
import android.util.Log;
import androidx.collection.ArraySet;
import androidx.lifecycle.LifecycleOwner;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardController;
import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer;
import com.android.settings.homepage.contextualcards.slices.SliceContextualCardController;
@@ -63,14 +65,32 @@
return (T) controller;
}
- public Set<ContextualCardController> getControllers() {
+ @VisibleForTesting
+ Set<ContextualCardController> getControllers() {
return mControllers;
}
- public ContextualCardRenderer getRenderer(Context context, LifecycleOwner lifecycleOwner,
- @ContextualCard.CardType int cardType) {
+ @VisibleForTesting
+ Set<ContextualCardRenderer> getRenderers() {
+ return mRenderers;
+ }
+
+ public ContextualCardRenderer getRendererByViewType(Context context,
+ LifecycleOwner lifecycleOwner, int viewType) {
final Class<? extends ContextualCardRenderer> clz =
- ContextualCardLookupTable.getCardRendererClasses(cardType);
+ ContextualCardLookupTable.getCardRendererClassByViewType(viewType);
+ return getRenderer(context, lifecycleOwner, clz);
+ }
+
+ public ContextualCardRenderer getRendererByCardType(Context context,
+ LifecycleOwner lifecycleOwner, @ContextualCard.CardType int cardType) {
+ final Class<? extends ContextualCardRenderer> clz =
+ ContextualCardLookupTable.getCardRendererClassByCardType(cardType);
+ return getRenderer(context, lifecycleOwner, clz);
+ }
+
+ private ContextualCardRenderer getRenderer(Context context, LifecycleOwner lifecycleOwner,
+ @NonNull Class<? extends ContextualCardRenderer> clz) {
for (ContextualCardRenderer renderer : mRenderers) {
if (renderer.getClass() == clz) {
Log.d(TAG, "Renderer is already there.");
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index 59c9ba9..c736c4d 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -26,7 +26,6 @@
import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
import com.android.settings.wifi.WifiSlice;
-import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardCategory;
import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
/** Provides dynamic card for SettingsIntelligence. */
@@ -41,19 +40,19 @@
ContextualCard.newBuilder()
.setSliceUri(WifiSlice.WIFI_URI.toString())
.setCardName(KEY_WIFI)
- .setCategory(ContextualCardCategory.IMPORTANT)
+ .setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard batteryInfoCard =
ContextualCard.newBuilder()
.setSliceUri(BatterySlice.BATTERY_CARD_URI.toString())
.setCardName(BatterySlice.PATH_BATTERY_INFO)
- .setCategory(ContextualCardCategory.DEFAULT)
+ .setCardCategory(ContextualCard.Category.DEFAULT)
.build();
final ContextualCard connectedDeviceCard =
ContextualCard.newBuilder()
.setSliceUri(ConnectedDeviceSlice.CONNECTED_DEVICE_URI.toString())
.setCardName(ConnectedDeviceSlice.PATH_CONNECTED_DEVICE)
- .setCategory(ContextualCardCategory.IMPORTANT)
+ .setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCardList cards = ContextualCardList.newBuilder()
.addCard(wifiCard)
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/AirplaneModeConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/AirplaneModeConditionController.java
index b6bb05a..f33633e 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/AirplaneModeConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/AirplaneModeConditionController.java
@@ -79,6 +79,7 @@
.setTitleText(mAppContext.getText(R.string.condition_airplane_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_airplane_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_airplanemode_active))
+ .setIsHalfWidth(true)
.build();
}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/BackgroundDataConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/BackgroundDataConditionController.java
index 8b0ee42..4e40556 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/BackgroundDataConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/BackgroundDataConditionController.java
@@ -73,6 +73,7 @@
.setTitleText(mAppContext.getText(R.string.condition_bg_data_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_bg_data_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_data_saver))
+ .setIsHalfWidth(true)
.build();
}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java
index 66901f3..bce7c5d 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java
@@ -82,6 +82,7 @@
.setTitleText(mAppContext.getText(R.string.condition_battery_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_battery_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_battery_saver_accent_24dp))
+ .setIsHalfWidth(true)
.build();
}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/CellularDataConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/CellularDataConditionController.java
index b2fbbcb..05199ba 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/CellularDataConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/CellularDataConditionController.java
@@ -89,6 +89,7 @@
.setTitleText(mAppContext.getText(R.string.condition_cellular_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_cellular_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_cellular_off))
+ .setIsHalfWidth(true)
.build();
}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java
index eb65819..10881d9 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java
@@ -85,6 +85,14 @@
public void onConditionsChanged() {
final List<ContextualCard> conditionCards = mConditionManager.getDisplayableCards();
+ final boolean isOddNumber = conditionCards.size() % 2 == 1;
+ if (isOddNumber) {
+ final int lastIndex = conditionCards.size() - 1;
+ final ConditionalContextualCard card = (ConditionalContextualCard) conditionCards.get(
+ lastIndex);
+ conditionCards.set(lastIndex, card.mutate().setIsHalfWidth(false).build());
+ }
+
if (mListener != null) {
final Map<Integer, List<ContextualCard>> conditionalCards = new ArrayMap<>();
conditionalCards.put(ContextualCard.CardType.CONDITIONAL, conditionCards);
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java
index 8a3635b..41c540c 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java
@@ -37,6 +37,8 @@
* Card renderer for {@link ConditionalContextualCard}.
*/
public class ConditionContextualCardRenderer implements ContextualCardRenderer {
+ public static final int HALF_WIDTH_VIEW_TYPE = R.layout.homepage_condition_half_tile;
+ public static final int FULL_WIDTH_VIEW_TYPE = R.layout.homepage_condition_full_tile;
private final Context mContext;
private final ControllerRendererPool mControllerRendererPool;
@@ -48,8 +50,12 @@
}
@Override
- public int getViewType() {
- return R.layout.homepage_condition_tile;
+ public int getViewType(boolean isHalfWidth) {
+ if (isHalfWidth) {
+ return HALF_WIDTH_VIEW_TYPE;
+ } else {
+ return FULL_WIDTH_VIEW_TYPE;
+ }
}
@Override
@@ -87,15 +93,12 @@
view.icon.setImageDrawable(card.getIconDrawable());
view.title.setText(card.getTitleText());
view.summary.setText(card.getSummaryText());
-
- setViewVisibility(view.itemView, R.id.divider, false);
}
private void initializeActionButton(ConditionalCardHolder view, ConditionalContextualCard card,
MetricsFeatureProvider metricsFeatureProvider) {
final CharSequence action = card.getActionText();
final boolean hasButtons = !TextUtils.isEmpty(action);
- setViewVisibility(view.itemView, R.id.buttonBar, hasButtons);
final Button button = view.itemView.findViewById(R.id.first_action);
if (hasButtons) {
@@ -114,13 +117,6 @@
}
}
- private void setViewVisibility(View containerView, int viewId, boolean visible) {
- View view = containerView.findViewById(viewId);
- if (view != null) {
- view.setVisibility(visible ? View.VISIBLE : View.GONE);
- }
- }
-
public static class ConditionalCardHolder extends RecyclerView.ViewHolder {
public final ImageView icon;
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java b/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
index 21cb6c0..706b50e 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
@@ -100,6 +100,7 @@
.setTitleText(mAppContext.getText(R.string.condition_zen_title).toString())
.setSummaryText(getSummary().toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp))
+ .setIsHalfWidth(true)
.build();
}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/HotspotConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/HotspotConditionController.java
index eec7e4a..862f828 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/HotspotConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/HotspotConditionController.java
@@ -99,6 +99,7 @@
.setTitleText(mAppContext.getText(R.string.condition_hotspot_title).toString())
.setSummaryText(getSummary().toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_hotspot))
+ .setIsHalfWidth(true)
.build();
}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/NightDisplayConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/NightDisplayConditionController.java
index d8d5f79..249e4a0 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/NightDisplayConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/NightDisplayConditionController.java
@@ -78,6 +78,7 @@
.setSummaryText(
mAppContext.getText(R.string.condition_night_display_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_settings_night_display))
+ .setIsHalfWidth(true)
.build();
}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/RingerMutedConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/RingerMutedConditionController.java
index 75a72fd..09b75eb 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/RingerMutedConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/RingerMutedConditionController.java
@@ -72,6 +72,7 @@
.setSummaryText(
mAppContext.getText(R.string.condition_device_muted_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_notifications_off_24dp))
+ .setIsHalfWidth(true)
.build();
}
}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/RingerVibrateConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/RingerVibrateConditionController.java
index 4c355a3..d8084b5 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/RingerVibrateConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/RingerVibrateConditionController.java
@@ -60,6 +60,7 @@
.setSummaryText(
mAppContext.getText(R.string.condition_device_vibrate_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_volume_ringer_vibrate))
+ .setIsHalfWidth(true)
.build();
}
}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/WorkModeConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/WorkModeConditionController.java
index c508403f..44b21bf 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/WorkModeConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/WorkModeConditionController.java
@@ -93,6 +93,7 @@
.setTitleText(mAppContext.getText(R.string.condition_work_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_work_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_signal_workmode_enable))
+ .setIsHalfWidth(true)
.build();
}
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
index c2bf536..5fc4473 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -45,6 +45,7 @@
*/
public class SliceContextualCardRenderer implements ContextualCardRenderer,
SliceView.OnSliceActionListener {
+ public static final int VIEW_TYPE = R.layout.homepage_slice_tile;
private static final String TAG = "SliceCardRenderer";
@@ -61,8 +62,8 @@
}
@Override
- public int getViewType() {
- return R.layout.homepage_slice_tile;
+ public int getViewType(boolean isHalfWidth) {
+ return VIEW_TYPE;
}
@Override
diff --git a/src/com/android/settings/location/LocationPreferenceController.java b/src/com/android/settings/location/LocationPreferenceController.java
deleted file mode 100644
index 0efc2b1..0000000
--- a/src/com/android/settings/location/LocationPreferenceController.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.location;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.location.LocationManager;
-import android.provider.Settings.Secure;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
-
-public class LocationPreferenceController extends AbstractPreferenceController
- implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
-
- private static final String KEY_LOCATION = "location";
- private Context mContext;
- private Preference mPreference;
-
- @VisibleForTesting
- BroadcastReceiver mLocationProvidersChangedReceiver;
-
- public LocationPreferenceController(Context context, Lifecycle lifecycle) {
- super(context);
- mContext = context;
- mLocationProvidersChangedReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(LocationManager.PROVIDERS_CHANGED_ACTION)) {
- updateSummary();
- }
- }
- };
- if (lifecycle != null) {
- lifecycle.addObserver(this);
- }
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreference = screen.findPreference(KEY_LOCATION);
- }
-
- @Override
- public void onResume() {
- if (mLocationProvidersChangedReceiver != null) {
- mContext.registerReceiver(mLocationProvidersChangedReceiver, new IntentFilter(
- LocationManager.PROVIDERS_CHANGED_ACTION));
- }
- }
-
- @Override
- public void onPause() {
- if (mLocationProvidersChangedReceiver != null) {
- mContext.unregisterReceiver(mLocationProvidersChangedReceiver);
- }
- }
-
- @Override
- public void updateState(Preference preference) {
- preference.setSummary(getLocationSummary(mContext));
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY_LOCATION;
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- public void updateSummary() {
- updateState(mPreference);
- }
-
- public static String getLocationSummary(Context context) {
- int mode = Secure.getInt(context.getContentResolver(),
- Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF);
- if (mode != Secure.LOCATION_MODE_OFF) {
- return context.getString(R.string.location_on_summary);
- }
- return context.getString(R.string.location_off_summary);
- }
-}
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 758ca57..53076e8 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -133,34 +133,6 @@
return controllers;
}
- private static class SummaryProvider implements SummaryLoader.SummaryProvider {
-
- private final Context mContext;
- private final SummaryLoader mSummaryLoader;
-
- public SummaryProvider(Context context, SummaryLoader summaryLoader) {
- mContext = context;
- mSummaryLoader = summaryLoader;
- }
-
- @Override
- public void setListening(boolean listening) {
- if (listening) {
- mSummaryLoader.setSummary(
- this, LocationPreferenceController.getLocationSummary(mContext));
- }
- }
- }
-
- public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
- = new SummaryLoader.SummaryProviderFactory() {
- @Override
- public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
- SummaryLoader summaryLoader) {
- return new SummaryProvider(activity, summaryLoader);
- }
- };
-
/**
* For Search.
*/
diff --git a/src/com/android/settings/network/telephony/ApnPreferenceController.java b/src/com/android/settings/network/telephony/ApnPreferenceController.java
index e02d9d4..f5cd140 100644
--- a/src/com/android/settings/network/telephony/ApnPreferenceController.java
+++ b/src/com/android/settings/network/telephony/ApnPreferenceController.java
@@ -62,12 +62,13 @@
public int getAvailabilityStatus() {
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
final boolean isCdmaApn = MobileNetworkUtils.isCdmaOptions(mContext, mSubId)
+ && carrierConfig != null
&& carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL);
final boolean isGsmApn = MobileNetworkUtils.isGsmOptions(mContext, mSubId)
+ && carrierConfig != null
&& carrierConfig.getBoolean(CarrierConfigManager.KEY_APN_EXPAND_BOOL);
- return carrierConfig != null
- && (isCdmaApn || isGsmApn)
+ return isCdmaApn || isGsmApn
? AVAILABLE
: CONDITIONALLY_UNAVAILABLE;
}
diff --git a/src/com/android/settings/network/telephony/CdmaOptions.java b/src/com/android/settings/network/telephony/CdmaOptions.java
deleted file mode 100644
index c573128..0000000
--- a/src/com/android/settings/network/telephony/CdmaOptions.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.network.telephony;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-
-/**
- * List of Phone-specific settings screens.
- */
-public class CdmaOptions {
- private static final String LOG_TAG = "CdmaOptions";
-
- private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
- private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
-
- private PreferenceFragmentCompat mPrefFragment;
-
- public CdmaOptions(PreferenceFragmentCompat prefFragment, PreferenceScreen prefScreen,
- int subId) {
- mPrefFragment = prefFragment;
- }
-
- public boolean preferenceTreeClick(Preference preference) {
- //TODO(b/114749736): handle it in preferenceController and remove this file
- if (preference.getKey().equals(BUTTON_CDMA_SYSTEM_SELECT_KEY)) {
- log("preferenceTreeClick: return BUTTON_CDMA_ROAMING_KEY true");
- return true;
- }
- if (preference.getKey().equals(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
- log("preferenceTreeClick: return CDMA_SUBSCRIPTION_KEY true");
- return true;
- }
- return false;
- }
-
- protected void log(String s) {
- android.util.Log.d(LOG_TAG, s);
- }
-}
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index 46773dc..b077dd5 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -45,7 +45,8 @@
private PersistableBundle mPersistableBundle;
private int mSubId;
private boolean mIsGlobalCdma;
- private boolean mShow4GForLTE;
+ @VisibleForTesting
+ boolean mShow4GForLTE;
public EnabledNetworkModePreferenceController(Context context, String key) {
super(context, key);
@@ -111,12 +112,10 @@
mTelephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE;
mIsGlobalCdma = isLteOnCdma
&& mPersistableBundle.getBoolean(CarrierConfigManager.KEY_SHOW_CDMA_CHOICES_BOOL);
- initShow4GForLTE();
- }
-
- @VisibleForTesting
- void initShow4GForLTE() {
- mShow4GForLTE = MobileNetworkUtils.isShow4GForLTE(mContext);
+ mShow4GForLTE = mPersistableBundle != null
+ ? mPersistableBundle.getBoolean(
+ CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL)
+ : false;
}
private int getPreferredNetworkMode() {
diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
index e85c917..689799e 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
@@ -386,19 +386,6 @@
return false;
}
- public static boolean isShow4GForLTE(Context context) {
- //TODO(b/117882862): move this to framework
- try {
- Context con = context.createPackageContext("com.android.systemui", 0);
- int id = con.getResources().getIdentifier("config_show4GForLTE",
- "bool", "com.android.systemui");
- return con.getResources().getBoolean(id);
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "NameNotFoundException for show4GFotLTE");
- return false;
- }
- }
-
/**
* Return {@code true} if Tdscdma is supported in current subscription
*/
diff --git a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
index 18415c7..41eb111 100644
--- a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
+++ b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
@@ -24,13 +24,10 @@
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.service.notification.ZenModeConfig;
+import android.text.TextUtils;
import android.util.Slog;
import android.view.View;
-import androidx.fragment.app.Fragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceFragmentCompat;
-
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
@@ -38,6 +35,10 @@
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+
public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModePreferenceController
implements PreferenceControllerMixin {
@@ -128,9 +129,13 @@
@Override
public void onOk(String ruleName, Fragment parent) {
+ if (TextUtils.equals(ruleName, mRule.getName())) {
+ return;
+ }
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
mRule.setName(ruleName);
+ mRule.setModified(true);
mBackend.setZenRule(mId, mRule);
}
}
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index b2eb8bb..9c1f07c 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -25,9 +25,11 @@
import android.content.Intent;
import android.provider.Settings;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.Toolbar;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.Utils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.search.SearchIndexableResources;
@@ -64,6 +66,13 @@
if (activity == null || toolbar == null) {
return;
}
+ if (!Utils.isPackageEnabled(activity, getSettingsIntelligencePkgName())) {
+ final ViewGroup parent = (ViewGroup)toolbar.getParent();
+ if (parent != null) {
+ parent.setVisibility(View.GONE);
+ }
+ return;
+ }
// Please forgive me for what I am about to do.
//
// Need to make the navigation icon non-clickable so that the entire card is clickable
diff --git a/src/com/android/settings/search/actionbar/SearchMenuController.java b/src/com/android/settings/search/actionbar/SearchMenuController.java
index 81e9e60..0caa308 100644
--- a/src/com/android/settings/search/actionbar/SearchMenuController.java
+++ b/src/com/android/settings/search/actionbar/SearchMenuController.java
@@ -56,9 +56,15 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ final Context context = mHost.getContext();
+ final String SettingsIntelligencePkgName = FeatureFactory.getFactory(context)
+ .getSearchFeatureProvider().getSettingsIntelligencePkgName();
if (!Utils.isDeviceProvisioned(mHost.getContext())) {
return;
}
+ if (!Utils.isPackageEnabled(mHost.getContext(), SettingsIntelligencePkgName)) {
+ return;
+ }
if (menu == null) {
return;
}
@@ -72,10 +78,8 @@
searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
searchItem.setOnMenuItemClickListener(target -> {
- final Context context = mHost.getContext();
final Intent intent = SearchFeatureProvider.SEARCH_UI_INTENT;
- intent.setPackage(FeatureFactory.getFactory(mHost.getContext())
- .getSearchFeatureProvider().getSettingsIntelligencePkgName());
+ intent.setPackage(SettingsIntelligencePkgName);
FeatureFactory.getFactory(context).getMetricsFeatureProvider()
.action(context, MetricsProto.MetricsEvent.ACTION_SEARCH_RESULTS);
mHost.startActivityForResult(intent, 0 /* requestCode */);
diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java
index eb0d6f1..e00d387 100644
--- a/src/com/android/settings/security/SecuritySettings.java
+++ b/src/com/android/settings/security/SecuritySettings.java
@@ -29,7 +29,6 @@
import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.enterprise.EnterprisePrivacyPreferenceController;
-import com.android.settings.location.LocationPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.security.trustagent.ManageTrustAgentsPreferenceController;
import com.android.settings.security.trustagent.TrustAgentListPreferenceController;
@@ -105,7 +104,6 @@
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle, SecuritySettings host) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new LocationPreferenceController(context, lifecycle));
controllers.add(new EnterprisePrivacyPreferenceController(context));
controllers.add(new ManageTrustAgentsPreferenceController(context));
controllers.add(new ScreenPinningPreferenceController(context));
diff --git a/src/com/android/settings/slices/CopyableSlice.java b/src/com/android/settings/slices/CopyableSlice.java
new file mode 100644
index 0000000..31fc151
--- /dev/null
+++ b/src/com/android/settings/slices/CopyableSlice.java
@@ -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.
+ */
+
+package com.android.settings.slices;
+
+/**
+ * Provide the copy ability for preference controller to copy the data to the clipboard.
+ */
+public interface CopyableSlice {
+ /**
+ * Copy the key slice information to the clipboard.
+ * It is highly recommended to show the toast to notify users when implemented this function.
+ */
+ void copy();
+}
diff --git a/src/com/android/settings/slices/CustomSliceable.java b/src/com/android/settings/slices/CustomSliceable.java
index e09cc73..b538b89 100644
--- a/src/com/android/settings/slices/CustomSliceable.java
+++ b/src/com/android/settings/slices/CustomSliceable.java
@@ -91,11 +91,12 @@
/**
* Settings Slices which can represent component lists that are updatable by the
- * {@link SliceBackgroundWorker} returned here.
+ * {@link SliceBackgroundWorker} class returned here.
*
- * @return a {@link SliceBackgroundWorker} for fetching the list of results in the background.
+ * @return a {@link SliceBackgroundWorker} class for fetching the list of results in the
+ * background.
*/
- default SliceBackgroundWorker getBackgroundWorker() {
+ default Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
return null;
}
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 3911603..fa669bb 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -52,7 +52,6 @@
import com.android.settingslib.SliceBroadcastRelay;
import com.android.settingslib.utils.ThreadUtils;
-import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -108,6 +107,12 @@
"com.android.settings.slice.action.SLIDER_CHANGED";
/**
+ * Action passed for copy data for the Copyable Slices.
+ */
+ public static final String ACTION_COPY =
+ "com.android.settings.slice.action.COPY";
+
+ /**
* Intent Extra passed for the key identifying the Setting Slice.
*/
public static final String EXTRA_SLICE_KEY = "com.android.settings.slice.extra.key";
@@ -134,8 +139,7 @@
final Set<Uri> mRegisteredUris = new ArraySet<>();
- final Map<Uri, SliceBackgroundWorker> mWorkerMap = new ArrayMap<>();
- final Set<SliceBackgroundWorker> mLiveWorkers = new ArraySet<>();
+ final Map<Uri, SliceBackgroundWorker> mPinnedWorkers = new ArrayMap<>();
public SettingsSliceProvider() {
super(READ_SEARCH_INDEXABLES);
@@ -365,45 +369,37 @@
}
private void startBackgroundWorker(CustomSliceable sliceable) {
- final SliceBackgroundWorker worker = sliceable.getBackgroundWorker();
- if (worker == null) {
+ final Class workerClass = sliceable.getBackgroundWorkerClass();
+ if (workerClass == null) {
return;
}
final Uri uri = sliceable.getUri();
- if (mWorkerMap.containsKey(uri)) {
+ if (mPinnedWorkers.containsKey(uri)) {
return;
}
Log.d(TAG, "Starting background worker for: " + uri);
- mWorkerMap.put(uri, worker);
- if (!mLiveWorkers.contains(worker)) {
- mLiveWorkers.add(worker);
- }
+ final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(
+ getContext(), sliceable);
+ mPinnedWorkers.put(uri, worker);
worker.onSlicePinned();
}
private void stopBackgroundWorker(Uri uri) {
- final SliceBackgroundWorker worker = mWorkerMap.get(uri);
+ final SliceBackgroundWorker worker = mPinnedWorkers.get(uri);
if (worker != null) {
Log.d(TAG, "Stopping background worker for: " + uri);
worker.onSliceUnpinned();
- mWorkerMap.remove(uri);
+ mPinnedWorkers.remove(uri);
}
}
@Override
public void shutdown() {
- for (SliceBackgroundWorker worker : mLiveWorkers) {
- ThreadUtils.postOnMainThread(() -> {
- try {
- worker.close();
- } catch (IOException e) {
- Log.w(TAG, "Exception when shutting down worker", e);
- }
- });
- }
- mLiveWorkers.clear();
+ ThreadUtils.postOnMainThread(() -> {
+ SliceBackgroundWorker.shutdown();
+ });
}
private List<Uri> buildUrisFromKeys(List<String> keys, String authority) {
@@ -532,4 +528,4 @@
}
return new String[0];
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/slices/SliceBackgroundWorker.java b/src/com/android/settings/slices/SliceBackgroundWorker.java
index 422fcc7..a663ece 100644
--- a/src/com/android/settings/slices/SliceBackgroundWorker.java
+++ b/src/com/android/settings/slices/SliceBackgroundWorker.java
@@ -17,36 +17,87 @@
package com.android.settings.slices;
import android.annotation.MainThread;
-import android.content.ContentResolver;
+import android.content.Context;
import android.net.Uri;
+import android.util.ArrayMap;
+import android.util.Log;
import java.io.Closeable;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
/**
* The Slice background worker is used to make Settings Slices be able to work with data that is
* changing continuously, e.g. available Wi-Fi networks.
*
- * The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, and be
- * stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}.
+ * The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, be
+ * stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}, and be closed at {@link
+ * SettingsSliceProvider#shutdown()}.
*
* {@link SliceBackgroundWorker} caches the results, uses the cache to compare if there is any data
* changed, and then notifies the Slice {@link Uri} to update.
+ *
+ * It also stores all instances of all workers to ensure each worker is a Singleton.
*/
public abstract class SliceBackgroundWorker<E> implements Closeable {
- private final ContentResolver mContentResolver;
+ private static final String TAG = "SliceBackgroundWorker";
+
+ private static final Map<Uri, SliceBackgroundWorker> LIVE_WORKERS = new ArrayMap<>();
+
+ private final Context mContext;
private final Uri mUri;
private List<E> mCachedResults;
- protected SliceBackgroundWorker(ContentResolver cr, Uri uri) {
- mContentResolver = cr;
+ protected SliceBackgroundWorker(Context context, Uri uri) {
+ mContext = context;
mUri = uri;
}
/**
+ * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link
+ * CustomSliceable}
+ */
+ public static SliceBackgroundWorker getInstance(Context context, CustomSliceable sliceable) {
+ final Uri uri = sliceable.getUri();
+ final Class<? extends SliceBackgroundWorker> workerClass =
+ sliceable.getBackgroundWorkerClass();
+ SliceBackgroundWorker worker = LIVE_WORKERS.get(uri);
+ if (worker == null) {
+ worker = createInstance(context, uri, workerClass);
+ LIVE_WORKERS.put(uri, worker);
+ }
+ return worker;
+ }
+
+ private static SliceBackgroundWorker createInstance(Context context, Uri uri,
+ Class<? extends SliceBackgroundWorker> clazz) {
+ Log.d(TAG, "create instance: " + clazz);
+ try {
+ return clazz.getConstructor(Context.class, Uri.class).newInstance(context, uri);
+ } catch (NoSuchMethodException | IllegalAccessException | InstantiationException |
+ InvocationTargetException e) {
+ throw new IllegalStateException(
+ "Invalid slice background worker: " + clazz, e);
+ }
+ }
+
+ static void shutdown() {
+ for (SliceBackgroundWorker worker : LIVE_WORKERS.values()) {
+ try {
+ worker.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Shutting down worker failed", e);
+ }
+ }
+ LIVE_WORKERS.clear();
+ }
+
+ /**
* Called when the Slice is pinned. This is the place to register callbacks or initialize scan
* tasks.
*/
@@ -83,7 +134,7 @@
if (needNotify) {
mCachedResults = results;
- mContentResolver.notifyChange(mUri, null);
+ mContext.getContentResolver().notifyChange(mUri, null);
}
}
}
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index e9e9d2c..4b86f33 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -24,6 +24,7 @@
import static com.android.settings.notification.ZenModeSliceBuilder.ACTION_ZEN_MODE_SLICE_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_SLIDER_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_TOGGLE_CHANGED;
+import static com.android.settings.slices.SettingsSliceProvider.ACTION_COPY;
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED;
import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED;
@@ -115,6 +116,9 @@
case ACTION_FLASHLIGHT_SLICE_CHANGED:
FlashlightSliceBuilder.handleUriChange(context, intent);
break;
+ case ACTION_COPY:
+ handleCopyAction(context, key, isPlatformSlice);
+ break;
}
}
@@ -184,6 +188,29 @@
updateUri(context, key, isPlatformSlice);
}
+ private void handleCopyAction(Context context, String key, boolean isPlatformSlice) {
+ if (TextUtils.isEmpty(key)) {
+ throw new IllegalArgumentException("No key passed to Intent for controller");
+ }
+
+ final BasePreferenceController controller = getPreferenceController(context, key);
+
+ if (!(controller instanceof CopyableSlice)) {
+ throw new IllegalArgumentException(
+ "Copyable action passed for a non-copyable key:" + key);
+ }
+
+ if (!controller.isAvailable()) {
+ Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
+ if (!controller.hasAsyncUpdate()) {
+ updateUri(context, key, isPlatformSlice);
+ }
+ return;
+ }
+
+ ((CopyableSlice) controller).copy();
+ }
+
/**
* Log Slice value update events into MetricsFeatureProvider. The logging schema generally
* follows the pattern in SharedPreferenceLogger.
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index 2432cc6..f6cc57f 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -93,6 +93,10 @@
return buildUnavailableSlice(context, sliceData);
}
+ if (controller instanceof CopyableSlice) {
+ return buildCopyableSlice(context, sliceData, controller);
+ }
+
switch (sliceData.getSliceType()) {
case SliceData.SliceType.INTENT:
return buildIntentSlice(context, sliceData, controller);
@@ -324,6 +328,28 @@
.build();
}
+ private static Slice buildCopyableSlice(Context context, SliceData sliceData,
+ BasePreferenceController controller) {
+ final SliceAction copyableAction = getCopyableAction(context, sliceData);
+ final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
+ final IconCompat icon = getSafeIcon(context, sliceData);
+ final SliceAction primaryAction = new SliceAction(contentIntent, icon,
+ sliceData.getTitle());
+ final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
+ @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
+ final Set<String> keywords = buildSliceKeywords(sliceData);
+
+ return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
+ .setAccentColor(color)
+ .addRow(new RowBuilder()
+ .setTitle(sliceData.getTitle())
+ .setSubtitle(subtitleText)
+ .setPrimaryAction(primaryAction)
+ .addEndItem(copyableAction))
+ .setKeywords(keywords)
+ .build();
+ }
+
private static BasePreferenceController getPreferenceController(Context context,
String controllerClassName, String controllerKey) {
try {
@@ -346,6 +372,14 @@
return getActionIntent(context, SettingsSliceProvider.ACTION_SLIDER_CHANGED, sliceData);
}
+ private static SliceAction getCopyableAction(Context context, SliceData sliceData) {
+ final PendingIntent intent = getActionIntent(context,
+ SettingsSliceProvider.ACTION_COPY, sliceData);
+ final IconCompat icon = IconCompat.createWithResource(context,
+ R.drawable.ic_content_copy_grey600_24dp);
+ return new SliceAction(intent, icon, sliceData.getTitle());
+ }
+
private static boolean isValidSummary(Context context, CharSequence summary) {
if (summary == null || TextUtils.isEmpty(summary.toString().trim())) {
return false;
diff --git a/src/com/android/settings/tts/TextToSpeechSettings.java b/src/com/android/settings/tts/TextToSpeechSettings.java
index 866e5a8..cce871b 100644
--- a/src/com/android/settings/tts/TextToSpeechSettings.java
+++ b/src/com/android/settings/tts/TextToSpeechSettings.java
@@ -251,15 +251,20 @@
mTts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
+ updateWidgetState(false);
}
@Override
public void onDone(String utteranceId) {
+ updateWidgetState(true);
}
@Override
public void onError(String utteranceId) {
Log.e(TAG, "Error while trying to synthesize sample text");
+ // Re-enable just in case, although there isn't much hope that following synthesis
+ // requests are going to succeed.
+ updateWidgetState(true);
}
});
}
@@ -696,9 +701,11 @@
}
private void updateWidgetState(boolean enable) {
- mActionButtons.setButton1Enabled(enable);
- mDefaultRatePref.setEnabled(enable);
- mDefaultPitchPref.setEnabled(enable);
+ getActivity().runOnUiThread(() -> {
+ mActionButtons.setButton1Enabled(enable);
+ mDefaultRatePref.setEnabled(enable);
+ mDefaultPitchPref.setEnabled(enable);
+ });
}
private void displayNetworkAlert() {
diff --git a/src/com/android/settings/users/AppRestrictionsFragment.java b/src/com/android/settings/users/AppRestrictionsFragment.java
index a4e0cff..5f899eb 100644
--- a/src/com/android/settings/users/AppRestrictionsFragment.java
+++ b/src/com/android/settings/users/AppRestrictionsFragment.java
@@ -450,7 +450,7 @@
private void addLocationAppRestrictionsPreference(AppRestrictionsHelper.SelectableAppInfo app,
AppRestrictionsPreference p) {
String packageName = app.packageName;
- p.setIcon(R.drawable.ic_settings_location);
+ p.setIcon(R.drawable.ic_preference_location);
p.setKey(getKeyForPackage(packageName));
ArrayList<RestrictionEntry> restrictions = RestrictionUtils.getRestrictions(
getActivity(), mUser);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 4837a88..f097d5b 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -112,9 +112,9 @@
private static final String PREF_KEY_EMPTY_WIFI_LIST = "wifi_empty_list";
private static final String PREF_KEY_CONNECTED_ACCESS_POINTS = "connected_access_point";
private static final String PREF_KEY_ACCESS_POINTS = "access_points";
- private static final String PREF_KEY_ADDITIONAL_SETTINGS = "additional_settings";
private static final String PREF_KEY_CONFIGURE_WIFI_SETTINGS = "configure_settings";
private static final String PREF_KEY_SAVED_NETWORKS = "saved_networks";
+ private static final String PREF_KEY_STATUS_MESSAGE = "wifi_status_message";
private static boolean isVerboseLoggingEnabled() {
return WifiTracker.sVerboseLogging || Log.isLoggable(TAG, Log.VERBOSE);
@@ -167,17 +167,19 @@
private Bundle mAccessPointSavedState;
private Bundle mWifiNfcDialogSavedState;
- private WifiTracker mWifiTracker;
+ @VisibleForTesting
+ WifiTracker mWifiTracker;
private String mOpenSsid;
private AccessPointPreference.UserBadgeCache mUserBadgeCache;
private PreferenceCategory mConnectedAccessPointPreferenceCategory;
private PreferenceCategory mAccessPointsPreferenceCategory;
- private PreferenceCategory mAdditionalSettingsPreferenceCategory;
private Preference mAddPreference;
- private Preference mConfigureWifiSettingsPreference;
- private Preference mSavedNetworksPreference;
+ @VisibleForTesting
+ Preference mConfigureWifiSettingsPreference;
+ @VisibleForTesting
+ Preference mSavedNetworksPreference;
private LinkablePreference mStatusMessagePreference;
// For Search
@@ -229,8 +231,6 @@
(PreferenceCategory) findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS);
mAccessPointsPreferenceCategory =
(PreferenceCategory) findPreference(PREF_KEY_ACCESS_POINTS);
- mAdditionalSettingsPreferenceCategory =
- (PreferenceCategory) findPreference(PREF_KEY_ADDITIONAL_SETTINGS);
mConfigureWifiSettingsPreference = findPreference(PREF_KEY_CONFIGURE_WIFI_SETTINGS);
mSavedNetworksPreference = findPreference(PREF_KEY_SAVED_NETWORKS);
@@ -238,7 +238,7 @@
mAddPreference = new Preference(prefContext);
mAddPreference.setIcon(R.drawable.ic_menu_add);
mAddPreference.setTitle(R.string.wifi_add_network);
- mStatusMessagePreference = new LinkablePreference(prefContext);
+ mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE);
mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
}
@@ -692,14 +692,14 @@
case WifiManager.WIFI_STATE_ENABLING:
removeConnectedAccessPointPreference();
- mAccessPointsPreferenceCategory.removeAll();
+ removeAccessPointPreference();
addMessagePreference(R.string.wifi_starting);
setProgressBarVisible(true);
break;
case WifiManager.WIFI_STATE_DISABLING:
removeConnectedAccessPointPreference();
- mAccessPointsPreferenceCategory.removeAll();
+ removeAccessPointPreference();
addMessagePreference(R.string.wifi_stopping);
break;
@@ -746,7 +746,10 @@
}
boolean hasAvailableAccessPoints = false;
- mAccessPointsPreferenceCategory.removePreference(mStatusMessagePreference);
+ mStatusMessagePreference.setVisible(false);
+ mConnectedAccessPointPreferenceCategory.setVisible(true);
+ mAccessPointsPreferenceCategory.setVisible(true);
+
cacheRemoveAllPrefs(mAccessPointsPreferenceCategory);
int index =
@@ -960,26 +963,28 @@
unregisterCaptivePortalNetworkCallback();
}
- private void setAdditionalSettingsSummaries() {
- mAdditionalSettingsPreferenceCategory.addPreference(mConfigureWifiSettingsPreference);
+ private void removeAccessPointPreference() {
+ mAccessPointsPreferenceCategory.removeAll();
+ mAccessPointsPreferenceCategory.setVisible(false);
+ }
+
+ @VisibleForTesting
+ void setAdditionalSettingsSummaries() {
mConfigureWifiSettingsPreference.setSummary(getString(
isWifiWakeupEnabled()
? R.string.wifi_configure_settings_preference_summary_wakeup_on
: R.string.wifi_configure_settings_preference_summary_wakeup_off));
- int numSavedNetworks = mWifiTracker.getNumSavedNetworks();
- if (numSavedNetworks > 0) {
- mAdditionalSettingsPreferenceCategory.addPreference(mSavedNetworksPreference);
- mSavedNetworksPreference.setSummary(
- getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary,
- numSavedNetworks, numSavedNetworks));
- } else {
- mAdditionalSettingsPreferenceCategory.removePreference(mSavedNetworksPreference);
- }
+ final int numSavedNetworks = mWifiTracker.getNumSavedNetworks();
+ mSavedNetworksPreference.setVisible(numSavedNetworks > 0);
+ mSavedNetworksPreference.setSummary(
+ getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary,
+ numSavedNetworks, numSavedNetworks));
}
private boolean isWifiWakeupEnabled() {
- PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
- ContentResolver contentResolver = getContentResolver();
+ final Context context = getContext();
+ final PowerManager powerManager = context.getSystemService(PowerManager.class);
+ final ContentResolver contentResolver = context.getContentResolver();
return Settings.Global.getInt(contentResolver,
Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1
&& Settings.Global.getInt(contentResolver,
@@ -1006,15 +1011,14 @@
.launch();
mStatusMessagePreference.setText(title, description, clickListener);
removeConnectedAccessPointPreference();
- mAccessPointsPreferenceCategory.removeAll();
- mAccessPointsPreferenceCategory.addPreference(mStatusMessagePreference);
+ removeAccessPointPreference();
+ mStatusMessagePreference.setVisible(true);
}
private void addMessagePreference(int messageId) {
mStatusMessagePreference.setTitle(messageId);
- removeConnectedAccessPointPreference();
- mAccessPointsPreferenceCategory.removeAll();
- mAccessPointsPreferenceCategory.addPreference(mStatusMessagePreference);
+ mStatusMessagePreference.setVisible(true);
+
}
protected void setProgressBarVisible(boolean visible) {
diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/WifiSlice.java
index 43f5372..d06d830 100644
--- a/src/com/android/settings/wifi/WifiSlice.java
+++ b/src/com/android/settings/wifi/WifiSlice.java
@@ -121,7 +121,7 @@
return listBuilder.build();
}
- List<AccessPoint> results = getBackgroundWorker().getResults();
+ List<AccessPoint> results = SliceBackgroundWorker.getInstance(mContext, this).getResults();
if (results == null) {
results = new ArrayList<>();
}
@@ -264,36 +264,27 @@
}
@Override
- public SliceBackgroundWorker getBackgroundWorker() {
- return WifiScanWorker.getInstance(mContext, WIFI_URI);
+ public Class getBackgroundWorkerClass() {
+ return WifiScanWorker.class;
}
- private static class WifiScanWorker extends SliceBackgroundWorker<AccessPoint>
+ public static class WifiScanWorker extends SliceBackgroundWorker<AccessPoint>
implements WifiTracker.WifiListener {
- // TODO: enforce all the SliceBackgroundWorkers being singletons at syntax level
- private static WifiScanWorker mWifiScanWorker;
-
private final Context mContext;
private WifiTracker mWifiTracker;
- private WifiScanWorker(Context context, Uri uri) {
- super(context.getContentResolver(), uri);
+ public WifiScanWorker(Context context, Uri uri) {
+ super(context, uri);
mContext = context;
}
- public static WifiScanWorker getInstance(Context context, Uri uri) {
- if (mWifiScanWorker == null) {
- mWifiScanWorker = new WifiScanWorker(context, uri);
- }
- return mWifiScanWorker;
- }
-
@Override
protected void onSlicePinned() {
if (mWifiTracker == null) {
- mWifiTracker = new WifiTracker(mContext, this, true, true);
+ mWifiTracker = new WifiTracker(mContext, this /* wifiListener */,
+ true /* includeSaved */, true /* includeScans */);
}
mWifiTracker.onStart();
onAccessPointsChanged();
@@ -307,7 +298,6 @@
@Override
public void close() {
mWifiTracker.onDestroy();
- mWifiScanWorker = null;
}
@Override
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
index 6b368c5..0de5c77 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
@@ -401,6 +401,7 @@
// Build and return intent
Intent intent = new Intent();
intent.setComponent(componentName);
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, mSubId);
return intent;
}
diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
index af25f48..2c98f70 100644
--- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
@@ -38,6 +38,7 @@
import com.android.settings.core.OnActivityResultListener;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowUtils;
import org.junit.Before;
import org.junit.Test;
@@ -46,6 +47,7 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
@@ -69,6 +71,7 @@
}
@Test
+ @Config(shadows = ShadowUtils.class)
public void onCreate_deviceNotProvisioned_shouldDisableSearch() {
Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 0);
final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class)
@@ -80,6 +83,7 @@
}
@Test
+ @Config(shadows = ShadowUtils.class)
public void onCreate_deviceProvisioned_shouldEnableSearch() {
Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class)
diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java
index 5f2abba..77cbae2 100644
--- a/tests/robotests/src/com/android/settings/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/UtilsTest.java
@@ -93,6 +93,7 @@
when(mContext.getSystemService(WifiManager.class)).thenReturn(wifiManager);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(connectivityManager);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
}
@Test
@@ -200,4 +201,27 @@
verify(mPackageManager).getApplicationInfoAsUser(eq(PACKAGE_NAME), anyInt(), eq(USER_ID));
verify(mIconDrawableFactory).getBadgedIcon(mApplicationInfo, USER_ID);
}
+
+ @Test
+ public void isPackageEnabled_appEnabled_returnTrue()
+ throws PackageManager.NameNotFoundException{
+ mApplicationInfo.enabled = true;
+ when(mPackageManager.getApplicationInfo(PACKAGE_NAME, 0)).thenReturn(mApplicationInfo);
+
+ assertThat(Utils.isPackageEnabled(mContext, PACKAGE_NAME)).isTrue();
+ }
+
+ @Test
+ public void isPackageEnabled_appDisabled_returnTrue()
+ throws PackageManager.NameNotFoundException{
+ mApplicationInfo.enabled = false;
+ when(mPackageManager.getApplicationInfo(PACKAGE_NAME, 0)).thenReturn(mApplicationInfo);
+
+ assertThat(Utils.isPackageEnabled(mContext, PACKAGE_NAME)).isFalse();
+ }
+
+ @Test
+ public void isPackageEnabled_noApp_returnFalse() {
+ assertThat(Utils.isPackageEnabled(mContext, PACKAGE_NAME)).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
index a4d1567..2648916 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
@@ -35,8 +35,10 @@
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
import android.os.Bundle;
import android.os.UserHandle;
+import android.os.UserManager;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
@@ -44,9 +46,12 @@
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.dashboard.DashboardFeatureProviderImpl;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowAccountManager;
+import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.drawer.CategoryKey;
import com.android.settingslib.drawer.Tile;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -54,10 +59,11 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowAccountManager;
+import org.robolectric.shadow.api.Shadow;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowAccountManager.class, ShadowUserManager.class})
public class AccountDetailDashboardFragmentTest {
private static final String METADATA_CATEGORY = "com.android.settings.category";
@@ -86,6 +92,11 @@
when(mFragment.getContext()).thenReturn(mContext);
}
+ @After
+ public void tearDown() {
+ ShadowAccountManager.reset();
+ }
+
@Test
public void testCategory_isAccountDetail() {
assertThat(new AccountDetailDashboardFragment().getCategoryKey())
@@ -152,17 +163,45 @@
}
@Test
- @Config(shadows = {ShadowAccountManager.class})
public void onResume_accountMissing_shouldFinish() {
+ ShadowUserManager userManager = Shadow.extract(
+ mContext.getSystemService(UserManager.class));
+ ShadowAccountManager acctMgr = Shadow.extract(
+ mContext.getSystemService(AccountManager.class));
+
+ userManager.addProfile(new UserInfo(1, null, 0));
+ acctMgr.addAccountForUser(1, new Account("test@test.com", "com.test"));
+
mFragment.finishIfAccountMissing();
verify(mFragment).finish();
}
@Test
- @Config(shadows = {ShadowAccountManager.class})
- public void onResume_accountPresent_shouldNotFinish() {
- AccountManager mgr = mContext.getSystemService(AccountManager.class);
- Shadows.shadowOf(mgr).addAccount(mFragment.mAccount);
+ public void onResume_accountPresentOneProfile_shouldNotFinish() {
+ ShadowUserManager userManager = Shadow.extract(
+ mContext.getSystemService(UserManager.class));
+ ShadowAccountManager acctMgr = Shadow.extract(
+ mContext.getSystemService(AccountManager.class));
+
+ userManager.addProfile(new UserInfo(1, null, 0));
+ acctMgr.addAccountForUser(1, mFragment.mAccount);
+
+ mFragment.finishIfAccountMissing();
+ verify(mFragment, never()).finish();
+ }
+
+ @Test
+ public void onResume_accountPresentTwoProfiles_shouldNotFinish() {
+ ShadowUserManager userManager = Shadow.extract(
+ mContext.getSystemService(UserManager.class));
+ ShadowAccountManager acctMgr = Shadow.extract(
+ mContext.getSystemService(AccountManager.class));
+
+ userManager.addProfile(new UserInfo(1, null, 0));
+ userManager.addProfile(new UserInfo(2, null, 0));
+ acctMgr.addAccountForUser(1, new Account("test@test.com", "com.test"));
+ acctMgr.addAccountForUser(2, mFragment.mAccount);
+
mFragment.finishIfAccountMissing();
verify(mFragment, never()).finish();
}
diff --git a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
new file mode 100644
index 0000000..c72561e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.accounts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.widget.ImageView;
+
+import com.android.settings.homepage.SettingsHomepageActivity;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AvatarViewMixinTest {
+ private static final String DUMMY_ACCOUNT = "test@domain.com";
+ private static final String DUMMY_DOMAIN = "domain.com";
+
+ private Context mContext;
+ private ImageView mImageView;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mImageView = new ImageView(mContext);
+ }
+
+ @Test
+ public void hasAccount_useDefaultAccountData_returnFalse() {
+ final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mContext, mImageView);
+ assertThat(avatarViewMixin.hasAccount()).isFalse();
+ }
+
+ @Test
+ @Config(shadows = ShadowAccountFeatureProviderImpl.class)
+ public void hasAccount_useShadowAccountData_returnTrue() {
+ final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mContext, mImageView);
+ assertThat(avatarViewMixin.hasAccount()).isTrue();
+ }
+
+ @Test
+ public void onStart_useMockAvatarViewMixin_shouldBeExecuted() {
+ final AvatarViewMixin mockAvatar = spy(new AvatarViewMixin(mContext, mImageView));
+
+ final ActivityController controller = Robolectric.buildActivity(
+ SettingsHomepageActivity.class).create();
+ final SettingsHomepageActivity settingsHomepageActivity =
+ (SettingsHomepageActivity) controller.get();
+ settingsHomepageActivity.getLifecycle().addObserver(mockAvatar);
+ controller.start();
+
+ verify(mockAvatar).onStart();
+ }
+
+ @Implements(AccountFeatureProviderImpl.class)
+ public static class ShadowAccountFeatureProviderImpl {
+
+ @Implementation
+ public Account[] getAccounts(Context context) {
+ Account[] accounts = {new Account(DUMMY_ACCOUNT, DUMMY_DOMAIN)};
+ return accounts;
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
index 22c2cdb..241765e 100644
--- a/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
@@ -76,7 +76,7 @@
@After
public void tearDown() {
ShadowContentResolver.reset();
- ShadowAccountManager.resetAuthenticator();
+ ShadowAccountManager.reset();
ShadowRestrictedLockUtilsInternal.clearDisabledTypes();
}
diff --git a/tests/robotests/src/com/android/settings/development/SmsAccessRestrictionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/SmsAccessRestrictionPreferenceControllerTest.java
new file mode 100644
index 0000000..7a0dd68
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/SmsAccessRestrictionPreferenceControllerTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SmsAccessRestrictionPreferenceControllerTest {
+
+ @Mock
+ private SwitchPreference mPreference;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+
+ private Context mContext;
+ private SmsAccessRestrictionPreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new SmsAccessRestrictionPreferenceController(mContext);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreference);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void onPreferenceChange_settingEnabled_enableSmsRestrictionShouldBeOn() {
+ mController.onPreferenceChange(mPreference, true /* new value */);
+
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, -1 /* default */);
+
+ assertThat(mode).isEqualTo(1);
+ }
+
+ @Test
+ public void onPreferenceChange_settingDisabled_enableSmsRestrictionShouldBeOff() {
+ mController.onPreferenceChange(mPreference, false /* new value */);
+
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, -1 /* default */);
+
+ assertThat(mode).isEqualTo(0);
+ }
+
+ @Test
+ public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0);
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(false);
+ }
+
+ @Test
+ public void updateState_settingEnabled_preferenceShouldBeChecked() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 1);
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(true);
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
+ mController.onDeveloperOptionsSwitchDisabled();
+
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, -1 /* default */);
+
+ assertThat(mode).isEqualTo(0);
+ verify(mPreference).setChecked(false);
+ verify(mPreference).setEnabled(false);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/PreventRingingGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/PreventRingingGesturePreferenceControllerTest.java
new file mode 100644
index 0000000..6d77d77
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/PreventRingingGesturePreferenceControllerTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.gestures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.preference.PreferenceCategory;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.widget.RadioButtonPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class PreventRingingGesturePreferenceControllerTest {
+
+ private Context mContext;
+ private Resources mResources;
+ private PreventRingingGesturePreferenceController mController;
+
+ @Before
+ public void setUp() {
+ mContext = spy(RuntimeEnvironment.application);
+ mResources = mock(Resources.class);
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled))
+ .thenReturn(true);
+ mController = new PreventRingingGesturePreferenceController(mContext, null);
+ mController.mVibratePref = new RadioButtonPreference(mContext);
+ mController.mNonePref = new RadioButtonPreference(mContext);
+ mController.mMutePref = new RadioButtonPreference(mContext);
+ }
+
+ @Test
+ public void testIsAvailable_configIsTrue_shouldReturnTrue() {
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_volumeHushGestureEnabled)).thenReturn(true);
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void testIsAvailable_configIsFalse_shouldReturnFalse() {
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_volumeHushGestureEnabled)).thenReturn(false);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void testUpdateState_mute() {
+ Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+ Settings.Secure.VOLUME_HUSH_MUTE);
+ mController.updateState(null);
+ assertThat(mController.mVibratePref.isChecked()).isFalse();
+ assertThat(mController.mNonePref.isChecked()).isFalse();
+ assertThat(mController.mMutePref.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_vibrate() {
+ Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+ Settings.Secure.VOLUME_HUSH_VIBRATE);
+ mController.updateState(null);
+ assertThat(mController.mVibratePref.isChecked()).isTrue();
+ assertThat(mController.mNonePref.isChecked()).isFalse();
+ assertThat(mController.mMutePref.isChecked()).isFalse();
+ }
+
+ @Test
+ public void testUpdateState_other() {
+ Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+ 7);
+ mController.updateState(null);
+ assertThat(mController.mVibratePref.isChecked()).isFalse();
+ assertThat(mController.mNonePref.isChecked()).isTrue();
+ assertThat(mController.mMutePref.isChecked()).isFalse();
+ }
+
+ @Test
+ public void testRadioButtonClicked_mute() {
+ RadioButtonPreference rbPref = new RadioButtonPreference(mContext);
+ rbPref.setKey(PreventRingingGesturePreferenceController.KEY_MUTE);
+
+ Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+ Settings.Secure.VOLUME_HUSH_OFF);
+ mController.onRadioButtonClicked(rbPref);
+
+ assertThat(Settings.Secure.VOLUME_HUSH_MUTE).isEqualTo(
+ Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_OFF));
+ }
+
+ @Test
+ public void testRadioButtonClicked_vibrate() {
+ RadioButtonPreference rbPref = new RadioButtonPreference(mContext);
+ rbPref.setKey(PreventRingingGesturePreferenceController.KEY_VIBRATE);
+
+ Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+ Settings.Secure.VOLUME_HUSH_OFF);
+ mController.onRadioButtonClicked(rbPref);
+
+ assertThat(Settings.Secure.VOLUME_HUSH_VIBRATE).isEqualTo(
+ Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_OFF));
+ }
+
+ @Test
+ public void testRadioButtonClicked_off() {
+ RadioButtonPreference rbPref = new RadioButtonPreference(mContext);
+ rbPref.setKey(PreventRingingGesturePreferenceController.KEY_NONE);
+
+ Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+ Settings.Secure.VOLUME_HUSH_MUTE);
+
+ mController.onRadioButtonClicked(rbPref);
+
+ assertThat(Settings.Secure.VOLUME_HUSH_OFF).isEqualTo(
+ Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_VIBRATE));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/PreventRingingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/PreventRingingPreferenceControllerTest.java
deleted file mode 100644
index 65c3b5d..0000000
--- a/tests/robotests/src/com/android/settings/gestures/PreventRingingPreferenceControllerTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import static android.provider.Settings.Secure.VOLUME_HUSH_GESTURE;
-import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
-import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.provider.Settings;
-
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class PreventRingingPreferenceControllerTest {
-
- private static final String KEY_PICK_UP = "gesture_prevent_ringing";
-
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Context mContext;
-
- private PreventRingingPreferenceController mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mController = new PreventRingingPreferenceController(mContext, KEY_PICK_UP);
- }
-
- @Test
- public void testIsAvailable_configIsTrue_shouldReturnTrue() {
- when(mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_volumeHushGestureEnabled)).thenReturn(true);
-
- assertThat(mController.isAvailable()).isTrue();
- }
-
- @Test
- public void testIsAvailable_configIsFalse_shouldReturnFalse() {
- when(mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_volumeHushGestureEnabled)).thenReturn(false);
-
- assertThat(mController.isAvailable()).isFalse();
- }
-
- @Test
- public void testUpdateState_mute() {
- ListPreference pref = mock(ListPreference.class);
- Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
- Settings.Secure.VOLUME_HUSH_MUTE);
- mController.updateState(pref);
- verify(pref).setValue(String.valueOf(Settings.Secure.VOLUME_HUSH_MUTE));
- }
-
- @Test
- public void testUpdateState_vibrate() {
- ListPreference pref = mock(ListPreference.class);
- Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
- Settings.Secure.VOLUME_HUSH_VIBRATE);
- mController.updateState(pref);
- verify(pref).setValue(String.valueOf(Settings.Secure.VOLUME_HUSH_VIBRATE));
- }
-
- @Test
- public void testUpdateState_other() {
- ListPreference pref = mock(ListPreference.class);
- Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
- 7);
- mController.updateState(pref);
- verify(pref).setValue(String.valueOf(Settings.Secure.VOLUME_HUSH_OFF));
- }
-
- @Test
- public void testUpdateState_parentPage() {
- Preference pref = mock(Preference.class);
- // verify no exception
- mController.updateState(pref);
- }
-
- @Test
- public void testOnPreferenceChange() {
- Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
- 7);
-
- mController.onPreferenceChange(mock(Preference.class), String.valueOf(VOLUME_HUSH_MUTE));
-
- assertEquals(VOLUME_HUSH_MUTE, Settings.Secure.getInt(mContext.getContentResolver(),
- VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF));
- }
-}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java
index 4ef982f..b25508b 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java
@@ -74,6 +74,7 @@
CardDatabaseHelper.CardColumns.CARD_ACTION,
CardDatabaseHelper.CardColumns.EXPIRE_TIME_MS,
CardDatabaseHelper.CardColumns.SUPPORT_HALF_WIDTH,
+ CardDatabaseHelper.CardColumns.CARD_DISMISSED,
};
assertThat(columnNames).isEqualTo(expectedNames);
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTableTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTableTest.java
new file mode 100644
index 0000000..4724500
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTableTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.homepage.contextualcards;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.settings.homepage.contextualcards.ContextualCardLookupTable
+ .ControllerRendererMapping;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ContextualCardLookupTableTest {
+
+ private static final int UNSUPPORTED_CARD_TYPE = -99999;
+ private static final int UNSUPPORTED_VIEW_TYPE = -99999;
+
+ private List<ControllerRendererMapping> mOriginalLookupTable;
+
+ @Before
+ public void setUp() {
+ mOriginalLookupTable = new ArrayList<>();
+ ContextualCardLookupTable.LOOKUP_TABLE.stream()
+ .forEach(mapping -> mOriginalLookupTable.add(mapping));
+ }
+
+ @After
+ public void reset() {
+ ContextualCardLookupTable.LOOKUP_TABLE.clear();
+ ContextualCardLookupTable.LOOKUP_TABLE.addAll(mOriginalLookupTable);
+ }
+
+ @Test
+ public void getCardControllerClass_hasSupportedCardType_shouldGetCorrespondingController() {
+ for (ControllerRendererMapping mapping : ContextualCardLookupTable.LOOKUP_TABLE) {
+ assertThat(ContextualCardLookupTable.getCardControllerClass(mapping.mCardType))
+ .isEqualTo(mapping.mControllerClass);
+ }
+ }
+
+ @Test
+ public void getCardControllerClass_hasUnsupportedCardType_shouldAlwaysGetNull() {
+ assertThat(ContextualCardLookupTable.getCardControllerClass(UNSUPPORTED_CARD_TYPE))
+ .isNull();
+ }
+
+ @Test
+ public void
+ getCardRendererClassByViewType_hasSupportedViewType_shouldGetCorrespondingRenderer() {
+ for (ControllerRendererMapping mapping : ContextualCardLookupTable.LOOKUP_TABLE) {
+ assertThat(ContextualCardLookupTable.getCardRendererClassByViewType(mapping.mViewType))
+ .isEqualTo(mapping.mRendererClass);
+ }
+ }
+
+ @Test
+ public void getCardRendererClassByViewType_hasUnsupportedViewType_shouldAlwaysGetNull() {
+ assertThat(ContextualCardLookupTable.getCardRendererClassByViewType(
+ UNSUPPORTED_VIEW_TYPE)).isNull();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void
+ getCardRendererClassByViewType_hasDuplicateViewType_shouldThrowsIllegalStateException() {
+ final ControllerRendererMapping mapping1 =
+ new ControllerRendererMapping(
+ 1111 /* cardType */, UNSUPPORTED_VIEW_TYPE /* viewType */,
+ ContextualCardController.class, ContextualCardRenderer.class
+ );
+ final ControllerRendererMapping mapping2 =
+ new ControllerRendererMapping(
+ 2222 /* cardType */, UNSUPPORTED_VIEW_TYPE /* viewType */,
+ ContextualCardController.class, ContextualCardRenderer.class
+ );
+ ContextualCardLookupTable.LOOKUP_TABLE.add(mapping1);
+ ContextualCardLookupTable.LOOKUP_TABLE.add(mapping2);
+
+ ContextualCardLookupTable.getCardRendererClassByViewType(UNSUPPORTED_VIEW_TYPE);
+ }
+
+ @Test
+ public void getRendererClassByCardType_hasSupportedCardType_shouldGetCorrespondingRenderer() {
+ for (ControllerRendererMapping mapping : ContextualCardLookupTable.LOOKUP_TABLE) {
+ assertThat(ContextualCardLookupTable.getCardRendererClassByCardType(mapping.mCardType))
+ .isEqualTo(mapping.mRendererClass);
+ }
+ }
+
+ @Test
+ public void getCardRendererClassByCardType_hasUnsupportedCardType_shouldAlwaysGetNull() {
+ assertThat(ContextualCardLookupTable.getCardRendererClassByCardType(UNSUPPORTED_CARD_TYPE))
+ .isNull();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ControllerRendererPoolTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ControllerRendererPoolTest.java
new file mode 100644
index 0000000..e51169e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ControllerRendererPoolTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.homepage.contextualcards;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.lifecycle.LifecycleOwner;
+
+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.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ControllerRendererPoolTest {
+
+ private static final int UNSUPPORTED_CARD_TYPE = -99999;
+ private static final int UNSUPPORTED_VIEW_TYPE = -99999;
+
+ private ControllerRendererPool mPool;
+ private Context mContext;
+ private Lifecycle mLifecycle;
+ private LifecycleOwner mLifecycleOwner;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+
+ mPool = new ControllerRendererPool();
+ }
+
+ @Test
+ public void getController_hasSupportedCardType_shouldReturnCorrespondingController() {
+ ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(mapping -> assertThat(
+ mPool.getController(mContext, mapping.mCardType).getClass()).isEqualTo(
+ mapping.mControllerClass));
+ }
+
+ @Test
+ public void getController_hasSupportedCardType_shouldHaveTwoControllersInPool() {
+ final long count = ContextualCardLookupTable.LOOKUP_TABLE.stream().map(
+ mapping -> mapping.mControllerClass).distinct().count();
+
+ ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(
+ mapping -> mPool.getController(mContext, mapping.mCardType));
+
+ assertThat(mPool.getControllers()).hasSize((int) count);
+ }
+
+ @Test
+ public void getController_hasUnsupportedCardType_shouldReturnNullAndPoolIsEmpty() {
+ final ContextualCardController controller = mPool.getController(mContext,
+ UNSUPPORTED_CARD_TYPE);
+
+ assertThat(controller).isNull();
+ assertThat(mPool.getControllers()).isEmpty();
+ }
+
+ @Test
+ public void getRenderer_hasSupportedViewType_shouldReturnCorrespondingRenderer() {
+ ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(mapping -> assertThat(
+ mPool.getRendererByViewType(mContext, mLifecycleOwner,
+ mapping.mViewType).getClass()).isEqualTo(mapping.mRendererClass));
+ }
+
+ @Test
+ public void getRenderer_hasSupportedViewType_shouldHaveDistinctRenderersInPool() {
+ final long count = ContextualCardLookupTable.LOOKUP_TABLE.stream().map(
+ mapping -> mapping.mRendererClass).distinct().count();
+
+ ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(
+ mapping -> mPool.getRendererByViewType(mContext, mLifecycleOwner,
+ mapping.mViewType));
+
+ assertThat(mPool.getRenderers()).hasSize((int) count);
+ }
+
+ @Test
+ public void getRenderer_hasUnsupportedViewType_shouldReturnNullAndPoolIsEmpty() {
+ final ContextualCardRenderer renderer = mPool.getRendererByViewType(mContext,
+ mLifecycleOwner,
+ UNSUPPORTED_VIEW_TYPE);
+
+ assertThat(renderer).isNull();
+ assertThat(mPool.getRenderers()).isEmpty();
+ }
+
+ @Test
+ public void getRenderer_hasSupportedCardTypeAndWidth_shouldReturnCorrespondingRenderer() {
+ ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(mapping -> assertThat(
+ mPool.getRendererByCardType(mContext, mLifecycleOwner,
+ mapping.mCardType).getClass()).isEqualTo(mapping.mRendererClass));
+ }
+
+ @Test
+ public void getRenderer_hasSupportedCardTypeAndWidth_shouldHaveDistinctRenderersInPool() {
+ final long count = ContextualCardLookupTable.LOOKUP_TABLE.stream().map(
+ mapping -> mapping.mRendererClass).distinct().count();
+
+ ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(
+ mapping -> mPool.getRendererByCardType(mContext, mLifecycleOwner,
+ mapping.mCardType));
+
+ assertThat(mPool.getRenderers()).hasSize((int) count);
+ }
+
+ @Test
+ public void getRenderer_hasUnsupportedCardType_shouldReturnNullAndPoolIsEmpty() {
+ final ContextualCardRenderer renderer = mPool.getRendererByCardType(mContext,
+ mLifecycleOwner,
+ UNSUPPORTED_CARD_TYPE);
+
+ assertThat(renderer).isNull();
+ assertThat(mPool.getRenderers()).isEmpty();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
index 8b541c6..6b1f8b1 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
@@ -19,7 +19,12 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.app.slice.SliceManager;
import android.content.ContentResolver;
+import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
@@ -28,30 +33,37 @@
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wifi.WifiSlice;
-import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardCategory;
import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class SettingsContextualCardProviderTest {
+ @Mock
+ private SliceManager mSliceManager;
private ContentResolver mResolver;
private Uri mUri;
private SettingsContextualCardProvider mProvider;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mResolver = RuntimeEnvironment.application.getContentResolver();
mUri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsContextualCardProvider.CARD_AUTHORITY)
.build();
- mProvider = Robolectric.setupContentProvider(SettingsContextualCardProvider.class);
+ mProvider = spy(Robolectric.setupContentProvider(SettingsContextualCardProvider.class));
+ final Context context = spy(RuntimeEnvironment.application);
+ doReturn(mSliceManager).when(context).getSystemService(SliceManager.class);
+ doReturn(context).when(mProvider).getContext();
}
@Test
@@ -59,7 +71,7 @@
final int actualNo = mProvider.getContextualCards().getCardCount();
final Bundle returnValue =
- mResolver.call(mUri, ContextualCardProvider.METHOD_GET_CARD_LIST, "", null);
+ mProvider.call(ContextualCardProvider.METHOD_GET_CARD_LIST, "", null);
final ContextualCardList cards =
ContextualCardList.parseFrom(
returnValue.getByteArray(ContextualCardProvider.BUNDLE_CARD_LIST));
@@ -76,6 +88,6 @@
}
}
- assertThat(wifiCard.getCategory()).isEqualTo(ContextualCardCategory.IMPORTANT);
+ assertThat(wifiCard.getCardCategory()).isEqualTo(ContextualCard.Category.IMPORTANT);
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
index ccfbbfb..376042d 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
@@ -61,7 +61,7 @@
@Test
public void bindView_shouldSetListener() {
- final int viewType = mRenderer.getViewType();
+ final int viewType = mRenderer.getViewType(false /* isHalfWidth */);
final RecyclerView recyclerView = new RecyclerView(mContext);
recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false);
@@ -78,7 +78,7 @@
@Test
public void viewClick_shouldInvokeControllerPrimaryClick() {
- final int viewType = mRenderer.getViewType();
+ final int viewType = mRenderer.getViewType(false /* isHalfWidth */);
final RecyclerView recyclerView = new RecyclerView(mContext);
recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false);
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
index 025f262..7a07d35 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
@@ -113,7 +113,7 @@
}
private RecyclerView.ViewHolder getSliceViewHolder() {
- final int viewType = mRenderer.getViewType();
+ final int viewType = mRenderer.getViewType(false /* isHalfWidth */);
final RecyclerView recyclerView = new RecyclerView(mContext);
recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false);
diff --git a/tests/robotests/src/com/android/settings/location/LocationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationPreferenceControllerTest.java
deleted file mode 100644
index c12fdc9..0000000
--- a/tests/robotests/src/com/android/settings/location/LocationPreferenceControllerTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.location;
-
-import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
-import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.location.LocationManager;
-import android.provider.Settings.Secure;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-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.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class LocationPreferenceControllerTest {
- @Mock
- private Preference mPreference;
- @Mock
- private PreferenceScreen mScreen;
-
- private LifecycleOwner mLifecycleOwner;
- private Lifecycle mLifecycle;
- private LocationPreferenceController mController;
-
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Context mContext;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mLifecycleOwner = () -> mLifecycle;
- mLifecycle = new Lifecycle(mLifecycleOwner);
- mController = new LocationPreferenceController(mContext, mLifecycle);
- when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
- }
-
- @Test
- public void isAvailable_shouldReturnTrue() {
- assertThat(mController.isAvailable()).isTrue();
- }
-
- @Test
- public void updateState_shouldSetSummary() {
- mController.updateState(mPreference);
-
- verify(mPreference).setSummary(nullable(String.class));
- }
-
- @Test
- public void updateSummary_shouldSetSummary() {
- mController.displayPreference(mScreen);
- mController.updateSummary();
-
- verify(mPreference).setSummary(nullable(String.class));
- }
-
- @Test
- public void getLocationSummary_locationOff_shouldSetSummaryOff() {
- final ContentResolver contentResolver = mContext.getContentResolver();
- Secure.putInt(contentResolver, Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF);
-
- final String locationSummary = mController.getLocationSummary(mContext);
- assertThat(locationSummary).isEqualTo(mContext.getString(R.string.location_off_summary));
- }
-
- @Test
- public void getLocationSummary_sensorsOnly_shouldSetSummaryOn() {
- final ContentResolver contentResolver = mContext.getContentResolver();
- Secure.putInt(contentResolver, Secure.LOCATION_MODE, Secure.LOCATION_MODE_SENSORS_ONLY);
-
- final String locationSummary = mController.getLocationSummary(mContext);
- assertThat(locationSummary).isEqualTo(mContext.getString(R.string.location_on_summary));
- }
-
- @Test
- public void getLocationSummary_highAccuracy_shouldSetSummaryOn() {
- final ContentResolver contentResolver = mContext.getContentResolver();
- Secure.putInt(contentResolver, Secure.LOCATION_MODE, Secure.LOCATION_MODE_HIGH_ACCURACY);
-
- final String locationSummary = mController.getLocationSummary(mContext);
- assertThat(locationSummary).isEqualTo(mContext.getString(R.string.location_on_summary));
- }
-
- @Test
- public void getLocationSummary_batterySaving_shouldSetSummaryOn() {
- final ContentResolver contentResolver = mContext.getContentResolver();
- Secure.putInt(contentResolver, Secure.LOCATION_MODE, Secure.LOCATION_MODE_BATTERY_SAVING);
-
- final String locationSummary = mController.getLocationSummary(mContext);
- assertThat(locationSummary).isEqualTo(mContext.getString(R.string.location_on_summary));
- }
-
- @Test
- public void onResume_shouldRegisterObserver() {
- mLifecycle.handleLifecycleEvent(ON_RESUME);
- verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
- }
-
- @Test
- public void onPause_shouldUnregisterObserver() {
- mLifecycle.handleLifecycleEvent(ON_RESUME);
- mLifecycle.handleLifecycleEvent(ON_PAUSE);
- verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
- }
-
- @Test
- public void locationProvidersChangedReceiver_updatesPreferenceSummary() {
- mController.displayPreference(mScreen);
- mController.onResume();
-
- mController.mLocationProvidersChangedReceiver
- .onReceive(mContext, new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
-
- verify(mPreference).setSummary(any());
- }
-}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java
index dc277d2..9664428 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
@@ -115,6 +116,14 @@
}
@Test
+ public void getAvailabilityStatus_carrierConfigNull_returnUnavailable() {
+ doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mTelephonyManager).getPhoneType();
+ when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(null);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
public void handPreferenceTreeClick_fireIntent() {
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
index 71df401..02710fb 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
@@ -23,7 +23,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -80,8 +79,7 @@
mPreference = new ListPreference(mContext);
mPreference.setEntries(R.array.enabled_networks_choices);
mPreference.setEntryValues(R.array.enabled_networks_values);
- mController = spy(new EnabledNetworkModePreferenceController(mContext, "enabled_network"));
- doNothing().when(mController).initShow4GForLTE();
+ mController = new EnabledNetworkModePreferenceController(mContext, "enabled_network");
mController.init(SUB_ID);
mPreference.setKey(mController.getPreferenceKey());
}
@@ -104,6 +102,16 @@
}
@Test
+ public void init_initShow4GForLTE() {
+ mPersistableBundle.putBoolean(CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL,
+ true);
+
+ mController.init(SUB_ID);
+
+ assertThat(mController.mShow4GForLTE).isTrue();
+ }
+
+ @Test
public void updateState_updateByNetworkMode() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID,
diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
index ba29ea1..d0546b6 100644
--- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
@@ -29,12 +29,14 @@
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
public class SearchFeatureProviderImplTest {
@@ -50,6 +52,7 @@
}
@Test
+ @Config(shadows = ShadowUtils.class)
public void initSearchToolbar_shouldInitWithOnClickListener() {
mProvider.initSearchToolbar(mActivity, null);
// Should not crash.
diff --git a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
index 3ab4ab4..b4076b5 100644
--- a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
+++ b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
@@ -30,6 +30,7 @@
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settingslib.core.lifecycle.ObservableFragment;
import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
@@ -39,8 +40,10 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowUtils.class)
public class SearchMenuControllerTest {
@Mock
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index a0fd21b..3c2cbdb 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -60,6 +61,7 @@
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settings.wifi.WifiSlice;
+import com.android.settingslib.wifi.WifiTracker;
import org.junit.After;
import org.junit.Before;
@@ -75,7 +77,6 @@
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowAccessibilityManager;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -91,7 +92,8 @@
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {ShadowUserManager.class, ShadowThreadUtils.class, ShadowUtils.class,
SlicesDatabaseAccessorTest.ShadowApplicationPackageManager.class,
- ShadowBluetoothAdapter.class, ShadowLockPatternUtils.class})
+ ShadowBluetoothAdapter.class, ShadowLockPatternUtils.class,
+ SettingsSliceProviderTest.ShadowWifiScanWorker.class})
public class SettingsSliceProviderTest {
private static final String KEY = "KEY";
@@ -135,7 +137,7 @@
mProvider.mSliceWeakDataCache = new HashMap<>();
mProvider.mSliceDataCache = new HashMap<>();
mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
- mProvider.mCustomSliceManager = spy(new CustomSliceManager(mContext));
+ mProvider.mCustomSliceManager = new CustomSliceManager(mContext);
when(mProvider.getContext()).thenReturn(mContext);
SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
@@ -497,57 +499,52 @@
mProvider.onSlicePinned(uri);
}
- private SliceBackgroundWorker initBackgroundWorker(Uri uri) {
- final SliceBackgroundWorker worker = spy(new SliceBackgroundWorker(
- mContext.getContentResolver(), uri) {
- @Override
- protected void onSlicePinned() {
- }
+ @Implements(WifiSlice.WifiScanWorker.class)
+ public static class ShadowWifiScanWorker {
+ private static WifiTracker mWifiTracker;
- @Override
- protected void onSliceUnpinned() {
- }
+ @Implementation
+ protected void onSlicePinned() {
+ mWifiTracker = mock(WifiTracker.class);
+ mWifiTracker.onStart();
+ }
- @Override
- public void close() {
- }
- });
- final WifiSlice wifiSlice = spy(new WifiSlice(mContext));
- when(wifiSlice.getBackgroundWorker()).thenReturn(worker);
- when(mProvider.mCustomSliceManager.getSliceableFromUri(uri)).thenReturn(wifiSlice);
- return worker;
+ @Implementation
+ protected void onSliceUnpinned() {
+ mWifiTracker.onStop();
+ }
+
+ @Implementation
+ public void close() {
+ mWifiTracker.onDestroy();
+ }
+
+ static WifiTracker getWifiTracker() {
+ return mWifiTracker;
+ }
}
@Test
public void onSlicePinned_backgroundWorker_started() {
- final Uri uri = WifiSlice.WIFI_URI;
- final SliceBackgroundWorker worker = initBackgroundWorker(uri);
+ mProvider.onSlicePinned(WifiSlice.WIFI_URI);
- mProvider.onSlicePinned(uri);
-
- verify(worker).onSlicePinned();
+ verify(ShadowWifiScanWorker.getWifiTracker()).onStart();
}
@Test
public void onSlicePinned_backgroundWorker_stopped() {
- final Uri uri = WifiSlice.WIFI_URI;
- final SliceBackgroundWorker worker = initBackgroundWorker(uri);
+ mProvider.onSlicePinned(WifiSlice.WIFI_URI);
+ mProvider.onSliceUnpinned(WifiSlice.WIFI_URI);
- mProvider.onSlicePinned(uri);
- mProvider.onSliceUnpinned(uri);
-
- verify(worker).onSliceUnpinned();
+ verify(ShadowWifiScanWorker.getWifiTracker()).onStop();
}
@Test
- public void shutdown_backgroundWorker_closed() throws IOException {
- final Uri uri = WifiSlice.WIFI_URI;
- final SliceBackgroundWorker worker = initBackgroundWorker(uri);
-
- mProvider.onSlicePinned(uri);
+ public void shutdown_backgroundWorker_closed() {
+ mProvider.onSlicePinned(WifiSlice.WIFI_URI);
mProvider.shutdown();
- verify(worker).close();
+ verify(ShadowWifiScanWorker.getWifiTracker()).onDestroy();
}
@Test
@@ -630,4 +627,4 @@
return sSetThreadPolicyCount != 0;
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 1055667..4371278 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -41,6 +41,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.FakeCopyableController;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.FakeSliderController;
import com.android.settings.testutils.FakeToggleController;
@@ -67,6 +68,7 @@
private final Uri URI = Uri.parse("content://com.android.settings.slices/test");
private final Class TOGGLE_CONTROLLER = FakeToggleController.class;
private final Class SLIDER_CONTROLLER = FakeSliderController.class;
+ private final Class COPYABLE_CONTROLLER = FakeCopyableController.class;
private final Class CONTEXT_CONTROLLER = FakeContextOnlyPreferenceController.class;
private final boolean IS_DYNAMIC_SUMMARY_ALLOWED = false;
@@ -116,7 +118,6 @@
public void buildSliderSlice_returnsMatchingSlice() {
final SliceData data = getDummyData(SLIDER_CONTROLLER, SliceData.SliceType.SLIDER);
-
final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
verify(mFeatureFactory.metricsFeatureProvider)
.action(eq(mContext), eq(MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED),
@@ -131,6 +132,23 @@
}
@Test
+ public void buildCopyableSlice_returnsMatchingSlice() {
+ final SliceData dummyData = getDummyData(COPYABLE_CONTROLLER, -1);
+
+ final Slice slice = SliceBuilderUtils.buildSlice(mContext, dummyData);
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(eq(mContext), eq(MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED),
+ mLoggingArgumentCatpor.capture());
+ final Pair<Integer, Object> capturedLoggingPair = mLoggingArgumentCatpor.getValue();
+
+ assertThat(capturedLoggingPair.first)
+ .isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME);
+ assertThat(capturedLoggingPair.second)
+ .isEqualTo(dummyData.getKey());
+ SliceTester.testSettingsCopyableSlice(mContext, slice, dummyData);
+ }
+
+ @Test
public void testUriBuilder_oemAuthority_intentPath_returnsValidSliceUri() {
final Uri expectedUri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java b/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java
new file mode 100644
index 0000000..a02377c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.testutils;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.slices.CopyableSlice;
+
+public class FakeCopyableController extends BasePreferenceController implements
+ CopyableSlice {
+
+ public FakeCopyableController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return true;
+ }
+
+ @Override
+ public void copy() {
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index 892f948..be4199d 100644
--- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -169,6 +169,43 @@
}
/**
+ * Test the copyable slice, including:
+ * - No intent
+ * - Correct title
+ * - Correct intent
+ * - Correct keywords
+ * - TTL
+ * - Color
+ */
+ public static void testSettingsCopyableSlice(Context context, Slice slice,
+ SliceData sliceData) {
+ final SliceMetadata metadata = SliceMetadata.from(context, slice);
+
+ final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
+ final int color = colorItem.getInt();
+ assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context));
+
+ final SliceAction primaryAction = metadata.getPrimaryAction();
+
+ final IconCompat expectedIcon = IconCompat.createWithResource(context,
+ sliceData.getIconResource());
+ assertThat(expectedIcon.toString()).isEqualTo(primaryAction.getIcon().toString());
+
+ final long sliceTTL = metadata.getExpiry();
+ assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
+
+ // Check primary intent
+ final PendingIntent primaryPendingIntent = primaryAction.getAction();
+ assertThat(primaryPendingIntent).isEqualTo(
+ SliceBuilderUtils.getContentPendingIntent(context, sliceData));
+
+ final List<SliceItem> sliceItems = slice.getItems();
+ assertTitle(sliceItems, sliceData.getTitle());
+
+ assertKeywords(metadata, sliceData);
+ }
+
+ /**
* Test the contents of an unavailable slice, including:
* - No toggles
* - Correct title
@@ -229,4 +266,4 @@
expectedKeywords.add(data.getScreenTitle().toString());
assertThat(keywords).containsExactlyElementsIn(expectedKeywords);
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java
index 03aabb5..4401926 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java
@@ -16,19 +16,24 @@
package com.android.settings.testutils.shadow;
+import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
+import android.annotation.NonNull;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
@Implements(AccountManager.class)
public class ShadowAccountManager{
private static final Map<String, AuthenticatorDescription> sAuthenticators = new HashMap<>();
+ private static final Map<Integer, List<Account>> sAccountsByUserId = new HashMap<>();
@Implementation
public AuthenticatorDescription[] getAuthenticatorTypesAsUser(int userId) {
@@ -39,7 +44,24 @@
sAuthenticators.put(authenticator.type, authenticator);
}
- public static void resetAuthenticator() {
+ public static void reset() {
sAuthenticators.clear();
+ sAccountsByUserId.clear();
+ }
+
+ @Implementation @NonNull
+ public Account[] getAccountsAsUser(int userId) {
+ if (sAccountsByUserId.containsKey(userId)) {
+ return sAccountsByUserId.get(userId).toArray(new Account[0]);
+ } else {
+ return new Account[0];
+ }
+ }
+
+ public static void addAccountForUser(int userId, Account account) {
+ if (!sAccountsByUserId.containsKey(userId)) {
+ sAccountsByUserId.put(userId, new ArrayList<>());
+ }
+ sAccountsByUserId.get(userId).add(account);
}
}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
index b09bc74..0927956 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
@@ -21,9 +21,13 @@
import android.hardware.fingerprint.FingerprintManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Log;
import com.android.settings.Utils;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.search.SearchFeatureProviderImpl;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@@ -102,6 +106,11 @@
return null;
}
+ @Implementation
+ public static boolean isPackageEnabled(Context context, String packageName) {
+ return true;
+ }
+
public static void setApplicationLabel(String packageName, String appLabel) {
if (sAppNameMap == null) {
sAppNameMap = new HashMap<>();
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
index e9daec3..c9e6c1e 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
@@ -20,20 +20,31 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.Activity;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.os.PowerManager;
+import android.provider.Settings;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.wifi.WifiTracker;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@@ -42,18 +53,33 @@
@RunWith(SettingsRobolectricTestRunner.class)
public class WifiSettingsTest {
+ private static final int NUM_NETWORKS = 4;
+
+ @Mock
+ private WifiTracker mWifiTracker;
+ @Mock
+ private PowerManager mPowerManager;
private Context mContext;
+ private WifiSettings mWifiSettings;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
+
+ mWifiSettings = spy(new WifiSettings());
+ doReturn(mContext).when(mWifiSettings).getContext();
+ doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+ mWifiSettings.mSavedNetworksPreference = new Preference(mContext);
+ mWifiSettings.mConfigureWifiSettingsPreference = new Preference(mContext);
+ mWifiSettings.mWifiTracker = mWifiTracker;
}
@Test
public void testSearchIndexProvider_shouldIndexFragmentTitle() {
final List<SearchIndexableRaw> indexRes =
- WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, true /* enabled */);
+ WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext,
+ true /* enabled */);
assertThat(indexRes).isNotNull();
assertThat(indexRes.get(0).key).isEqualTo(WifiSettings.DATA_KEY_REFERENCE);
@@ -63,7 +89,8 @@
@Config(qualifiers = "mcc999")
public void testSearchIndexProvider_ifWifiSettingsNotVisible_shouldNotIndexFragmentTitle() {
final List<SearchIndexableRaw> indexRes =
- WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, true /* enabled */);
+ WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext,
+ true /* enabled */);
assertThat(indexRes).isEmpty();
}
@@ -78,4 +105,51 @@
verify(wifiSettings).handleAddNetworkRequest(anyInt(), any(Intent.class));
}
+
+ @Test
+ public void setAdditionalSettingsSummaries_hasSavedNetwork_preferenceVisible() {
+ when(mWifiTracker.getNumSavedNetworks()).thenReturn(NUM_NETWORKS);
+
+ mWifiSettings.setAdditionalSettingsSummaries();
+
+ assertThat(mWifiSettings.mSavedNetworksPreference.isVisible()).isTrue();
+ assertThat(mWifiSettings.mSavedNetworksPreference.getSummary()).isEqualTo(
+ mContext.getResources().getQuantityString(
+ R.plurals.wifi_saved_access_points_summary,
+ NUM_NETWORKS, NUM_NETWORKS));
+ }
+
+ @Test
+ public void setAdditionalSettingsSummaries_noSavedNetwork_preferenceInvisible() {
+ when(mWifiTracker.getNumSavedNetworks()).thenReturn(0);
+
+ mWifiSettings.setAdditionalSettingsSummaries();
+
+ assertThat(mWifiSettings.mSavedNetworksPreference.isVisible()).isFalse();
+ }
+
+ @Test
+ public void setAdditionalSettingsSummaries_wifiWakeupEnabled_displayOn() {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putInt(contentResolver, Settings.Global.WIFI_WAKEUP_ENABLED, 1);
+ Settings.Global.putInt(contentResolver, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 1);
+ Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
+ when(mPowerManager.isPowerSaveMode()).thenReturn(false);
+
+ mWifiSettings.setAdditionalSettingsSummaries();
+
+ assertThat(mWifiSettings.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
+ mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_on));
+ }
+
+ @Test
+ public void setAdditionalSettingsSummaries_wifiWakeupDisabled_displayOff() {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putInt(contentResolver, Settings.Global.WIFI_WAKEUP_ENABLED, 0);
+
+ mWifiSettings.setAdditionalSettingsSummaries();
+
+ assertThat(mWifiSettings.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
+ mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_off));
+ }
}
\ No newline at end of file