Merge "Import translations. DO NOT MERGE"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 970ee76..b04c8ab 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -166,8 +166,6 @@
android:value="com.android.settings.category.ia.homepage"/>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.network.NetworkDashboardFragment"/>
- <meta-data android:name="com.android.settings.summary"
- android:resource="@string/network_dashboard_summary"/>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
@@ -193,8 +191,6 @@
android:value="com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment"/>
<meta-data android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.homepage"/>
- <meta-data android:name="com.android.settings.summary"
- android:resource="@string/connected_devices_dashboard_summary"/>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
diff --git a/res/drawable-hdpi/empty_search_results.png b/res/drawable-hdpi/empty_search_results.png
new file mode 100644
index 0000000..290f0ed
--- /dev/null
+++ b/res/drawable-hdpi/empty_search_results.png
Binary files differ
diff --git a/res/drawable-mdpi/empty_search_results.png b/res/drawable-mdpi/empty_search_results.png
new file mode 100644
index 0000000..9ef49a6
--- /dev/null
+++ b/res/drawable-mdpi/empty_search_results.png
Binary files differ
diff --git a/res/drawable-xhdpi/empty_search_results.png b/res/drawable-xhdpi/empty_search_results.png
new file mode 100644
index 0000000..92a9392
--- /dev/null
+++ b/res/drawable-xhdpi/empty_search_results.png
Binary files differ
diff --git a/res/drawable-xxhdpi/empty_search_results.png b/res/drawable-xxhdpi/empty_search_results.png
new file mode 100644
index 0000000..894ed7b
--- /dev/null
+++ b/res/drawable-xxhdpi/empty_search_results.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/empty_search_results.png b/res/drawable-xxxhdpi/empty_search_results.png
new file mode 100644
index 0000000..8f12e96
--- /dev/null
+++ b/res/drawable-xxxhdpi/empty_search_results.png
Binary files differ
diff --git a/res/drawable/no_search_results.xml b/res/drawable/no_search_results.xml
deleted file mode 100644
index a75a443..0000000
--- a/res/drawable/no_search_results.xml
+++ /dev/null
@@ -1,59 +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.
-
- -->
-
-<vector android:height="24dp" android:viewportHeight="267.9"
- android:viewportWidth="236.3" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillAlpha="0.9" android:fillColor="#00000000"
- android:pathData="M18,-19c0,-0.4 0,-0.5 -0.3,-0.3l-12,7c-0.3,0.2 -0.2,0.5 0.1,0.6l11.9,7C18,-4.5 18,-4.7 18,-5V-19z"
- android:strokeColor="#FFFFFF" android:strokeWidth="2"/>
- <path android:fillAlpha="0.9" android:fillColor="#00000000"
- android:pathData="M18.9,-12c0,-3.8 -3.1,-6.9 -6.9,-6.9c-3.8,0 -6.9,3.1 -6.9,6.9c0,3.8 3.1,6.9 6.9,6.9C15.8,-5.1 18.9,-8.2 18.9,-12z"
- android:strokeColor="#FFFFFF" android:strokeWidth="1.8033"/>
- <path android:fillAlpha="0.9" android:fillColor="#00000000"
- android:pathData="M19,-5.7C19,-5.4 18.6,-5 18.2,-5H5.8C5.4,-5 5,-5.4 5,-5.7v-12.6C5,-18.6 5.4,-19 5.8,-19h12.4c0.4,0 0.8,0.4 0.8,0.7V-5.7z"
- android:strokeColor="#FFFFFF" android:strokeWidth="2"/>
- <path android:fillColor="#FAFAFA" android:pathData="M118.2,134.4m-118.2,0a118.2,118.2 0,1 1,236.4 0a118.2,118.2 0,1 1,-236.4 0"/>
- <path android:fillColor="#F5F5F5" android:pathData="M22.8,239L96,206.2c0.2,-0.1 0.3,-0.1 0.5,-0.1l117.3,23c0.7,0.2 0.9,1.2 0.2,1.5l-75.9,37.2c-0.2,0.1 -0.3,0.1 -0.5,0.1L23,240.5C22.2,240.3 22.1,239.3 22.8,239z"/>
- <path android:fillColor="#E8E8E8" android:pathData="M35.6,76.5l102,17.3l0,167.4l-102,-23.2z"/>
- <path android:fillColor="#E8E8E8" android:pathData="M35.7,19.6l102,17.3l0,79.2l-102,-23.2z"/>
- <path android:fillColor="#EFEFEF" android:pathData="M35.7,19.6l66.6,-19.6l100.5,19.1l-65.1,18.5z"/>
- <path android:fillColor="#00000000"
- android:pathData="M37.6,131.9L135.2,150"
- android:strokeColor="#E0E0E0" android:strokeWidth="0.1816"/>
- <path android:fillAlpha="0.5" android:fillColor="#00000000"
- android:pathData="M39.1,185.3L132.3,204.8"
- android:strokeColor="#C1C1C1" android:strokeWidth="0.1816"/>
- <path android:fillColor="#00000000"
- android:pathData="M137.7,147.6L116.5,154.5"
- android:strokeColor="#E0E0E0" android:strokeWidth="0.1816"/>
- <path android:fillColor="#00000000" android:pathData="M35.7,142.2"
- android:strokeColor="#E0E0E0" android:strokeWidth="0.1816"/>
- <path android:fillAlpha="5.000000e-02" android:fillColor="#FF000000" android:pathData="M35.7,140.9l101.7,9.2l0,33.1l-101.8,-21.3z"/>
- <path android:fillColor="#CECECE" android:pathData="M71,36.9l28.8,5l0,5.8l-28.8,-5.3z"/>
- <path android:fillAlpha="0.1" android:fillColor="#1F1F1F" android:pathData="M71,36.9l28.8,5l0,1.7l-28.8,-5.3z"/>
- <path android:fillAlpha="0.5" android:fillColor="#CECECE" android:pathData="M68.4,147.3l28.8,5.1l0,5.8l-28.8,-5.4z"/>
- <path android:fillAlpha="0.1" android:fillColor="#1F1F1F" android:pathData="M68.4,147.3l28.8,5.1l0,1.7l-28.8,-5.4z"/>
- <path android:fillAlpha="0.7" android:fillColor="#CECECE" android:pathData="M68.4,201.2l28.8,5.4l0,5.8l-28.8,-5.7z"/>
- <path android:fillAlpha="0.1" android:fillColor="#1F1F1F" android:pathData="M68.4,201.2l28.8,5.4l0,1.6l-28.8,-5.6z"/>
- <path android:fillColor="#EAEAEA" android:pathData="M16.2,80.3l100.3,18.1l0,58.5l-100.3,-20.2z"/>
- <path android:fillColor="#EFEFEF" android:pathData="M137.7,37.6l0,53.9l-21.2,6.9l0,58.5l21.2,-6.9l0,111.1l65.1,-30l0,-212z"/>
- <path android:fillColor="#E57373" android:pathData="M16.2,80.3l19.5,-8.2l0,11.7z"/>
- <path android:fillAlpha="0.6" android:fillColor="#E57373" android:pathData="M137.7,91.5l-102,-19.4l0,11.7l80.8,14.6z"/>
- <path android:fillColor="#CECECE" android:pathData="M47.2,95.5l28.8,5l0,5.8l-28.8,-5.2z"/>
- <path android:fillAlpha="0.1" android:fillColor="#1F1F1F" android:pathData="M47.2,95.5l28.8,5l0,1.7l-28.8,-5.2z"/>
- <path android:fillColor="#EAEAEA" android:pathData="M35.7,72.1L35.7,72.1l-19.6,8.1l0,0.1l0,0l100.3,18.1l0,0l0,0l21.6,-7L35.7,72.1zM116.5,97.5L19.4,80l16.4,-6.8L134,91.8L116.5,97.5z"/>
-</vector>
diff --git a/res/layout/account_header.xml b/res/layout/account_header.xml
deleted file mode 100755
index 818d47c..0000000
--- a/res/layout/account_header.xml
+++ /dev/null
@@ -1,53 +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.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/EntityHeader"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:gravity="center_vertical"
- android:paddingTop="24dip"
- android:paddingBottom="24dip"
- android:orientation="horizontal">
-
- <LinearLayout
- android:id="@+id/icon_container"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minWidth="56dp"
- android:orientation="horizontal"
- android:paddingEnd="12dp"
- android:paddingTop="12dp"
- android:paddingBottom="12dp">
- <ImageView
- android:id="@android:id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxWidth="48dp"
- android:maxHeight="48dp"/>
- </LinearLayout>
-
- <TextView
- android:id="@android:id/title"
- style="@style/TextAppearance.EntityHeaderTitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"/>
-
-</LinearLayout>
diff --git a/res/layout/app_details.xml b/res/layout/app_details.xml
deleted file mode 100644
index 2db23e4..0000000
--- a/res/layout/app_details.xml
+++ /dev/null
@@ -1,116 +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.
- -->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <!-- App snippet with buttons -->
- <RelativeLayout
- android:id="@+id/app_snippet"
- style="@style/EntityHeader"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="0dp"
- android:paddingTop="24dp"
- android:paddingBottom="24dp">
- <ImageView
- android:id="@+id/app_detail_icon"
- android:layout_width="56dp"
- android:layout_height="56dp"
- android:scaleType="fitXY"
- android:layout_gravity="center_horizontal"
- android:antialias="true"/>
-
- <LinearLayout
- android:id="@+id/app_detail_links"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_alignParentEnd="true"
- android:orientation="vertical">
-
- <ImageButton
- android:id="@+id/right_button"
- style="?android:attr/actionOverflowButtonStyle"
- android:layout_width="wrap_content"
- android:layout_weight="1"
- android:layout_height="0dp"
- android:minWidth="@dimen/min_tap_target_size"
- android:src="@drawable/ic_settings_24dp"
- android:tint="?android:attr/colorAccent"/>
-
- <ImageButton
- android:id="@+id/left_button"
- style="?android:attr/actionOverflowButtonStyle"
- android:layout_width="wrap_content"
- android:layout_weight="1"
- android:layout_height="0dp"
- android:minWidth="@dimen/min_tap_target_size"
- android:src="@null"
- android:tint="?android:attr/colorAccent"/>
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_toEndOf="@id/app_detail_icon"
- android:layout_toStartOf="@id/app_detail_links"
- android:paddingStart="24dp"
- android:paddingEnd="24dp"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/app_detail_title"
- style="@style/TextAppearance.EntityHeaderTitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="false"
- android:ellipsize="marquee"
- android:gravity="start"
- android:textDirection="locale"
- android:paddingTop="8dp"/>
-
- <TextView
- android:id="@+id/install_type"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="start"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="@android:style/TextAppearance.Material.Body1"
- android:textColor="?android:attr/textColorSecondary"/>
-
- <TextView
- android:id="@+id/app_detail_summary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="start"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="@android:style/TextAppearance.Material.Body1"
- android:textColor="?android:attr/textColorSecondary"/>
-
- </LinearLayout>
-
- </RelativeLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/choose_lock_password.xml b/res/layout/choose_lock_password.xml
index b0ba043..988f331 100644
--- a/res/layout/choose_lock_password.xml
+++ b/res/layout/choose_lock_password.xml
@@ -43,11 +43,13 @@
android:textAppearance="?android:attr/textAppearanceMedium"/>
<LinearLayout
+ android:id="@+id/password_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
+ android:layoutMode="opticalBounds"
android:paddingBottom="8dp">
<!-- Password entry field -->
@@ -68,6 +70,15 @@
android:layout_height="wrap_content"/>
</LinearLayout>
+
+ <Button
+ android:id="@+id/screen_lock_options"
+ style="@style/SuwGlifButton.Tertiary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/setup_lock_settings_options_button_label"
+ android:visibility="gone" />
+
</LinearLayout>
</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/password_requirement_item.xml b/res/layout/password_requirement_item.xml
index df7f45c..8080f10 100644
--- a/res/layout/password_requirement_item.xml
+++ b/res/layout/password_requirement_item.xml
@@ -15,8 +15,8 @@
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/description_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingStart="4dp"
- android:textSize="14sp"/>
\ No newline at end of file
+ android:id="@+id/description_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="?attr/suwGlifHeaderGravity"
+ android:textSize="14sp"/>
diff --git a/res/layout/search_panel.xml b/res/layout/search_panel.xml
index 8f72847..9445e0c 100644
--- a/res/layout/search_panel.xml
+++ b/res/layout/search_panel.xml
@@ -61,18 +61,20 @@
android:id="@+id/no_results_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:gravity="center"
+ android:paddingTop="80dp"
android:orientation="vertical"
android:visibility="gone">
<ImageView
- android:layout_height="112dp"
- android:layout_width="112dp"
- android:src="@drawable/no_search_results"/>
+ android:layout_height="160dp"
+ android:layout_width="160dp"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/empty_search_results"/>
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
+ android:paddingTop="24dp"
android:textSize="18sp"
android:text="@string/search_settings_no_results"
android:gravity="center"/>
diff --git a/res/layout/settings_entity_header.xml b/res/layout/settings_entity_header.xml
new file mode 100644
index 0000000..ce81b49
--- /dev/null
+++ b/res/layout/settings_entity_header.xml
@@ -0,0 +1,110 @@
+<?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.
+ -->
+
+<!-- Entity header -->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/entity_header"
+ style="@style/EntityHeader"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="0dp"
+ android:paddingTop="24dp"
+ android:paddingBottom="24dp">
+
+ <ImageView
+ android:id="@+id/entity_header_icon"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:scaleType="fitXY"
+ android:layout_gravity="center_horizontal"
+ android:antialias="true" />
+
+ <LinearLayout
+ android:id="@+id/entity_header_links"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentEnd="true"
+ android:orientation="vertical">
+
+ <ImageButton
+ android:id="@android:id/button1"
+ style="?android:attr/actionOverflowButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_weight="1"
+ android:layout_height="0dp"
+ android:minWidth="@dimen/min_tap_target_size"
+ android:src="@drawable/ic_settings_24dp"
+ android:tint="?android:attr/colorAccent" />
+
+ <ImageButton
+ android:id="@android:id/button2"
+ style="?android:attr/actionOverflowButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_weight="1"
+ android:layout_height="0dp"
+ android:minWidth="@dimen/min_tap_target_size"
+ android:src="@null"
+ android:tint="?android:attr/colorAccent" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_toEndOf="@id/entity_header_icon"
+ android:layout_toStartOf="@id/entity_header_links"
+ android:paddingStart="24dp"
+ android:paddingEnd="24dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/entity_header_title"
+ style="@style/TextAppearance.EntityHeaderTitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="false"
+ android:ellipsize="marquee"
+ android:gravity="start"
+ android:textDirection="locale"
+ android:paddingTop="8dp" />
+
+ <TextView
+ android:id="@+id/install_type"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <TextView
+ android:id="@+id/entity_header_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ </LinearLayout>
+
+</RelativeLayout>
diff --git a/res/values-mcc262-mnc02/strings.xml b/res/values-mcc262-mnc02/strings.xml
new file mode 100644
index 0000000..17f9272
--- /dev/null
+++ b/res/values-mcc262-mnc02/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Wi-Fi Calling settings. Additional text displayed when Wi-Fi Calling is off. Default empty. [CHAR LIMIT=NONE] -->
+ <string name="wifi_calling_off_explanation_2">\n\nYou can\u2019t make emergency calls through Wi-Fi calling. If you try to make an emergency call, your device will automatically use the mobile network. Emergency calls can only be made in areas with mobile network coverage.</string>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6b12237..038b184 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1091,6 +1091,9 @@
<!-- Message shown in screen lock picker while setting up the backup/fallback screen lock method for fingerprint. Users can choose to use this method to unlock the screen instead of fingerprint, or when fingerprint is not accepted. [CHAR LIMIT=80] [BACKUP_MESSAGE_ID=2799884038398627882] -->
<string name="lock_settings_picker_fingerprint_message">Choose your backup screen lock method</string>
+ <!-- Label for button in screen lock settings, allowing users to choose other types of screen locks. [CHAR LIMIT=40] -->
+ <string name="setup_lock_settings_options_button_label">Screen lock options</string>
+
<!-- Main Security lock settings --><skip />
<!-- Title for PreferenceScreen to launch picker for security method when there is none [CHAR LIMIT=22] -->
<string name="unlock_set_unlock_launch_picker_title">Screen lock</string>
@@ -2124,6 +2127,8 @@
</string-array>
<!-- Wi-Fi Calling settings. Text displayed when Wi-Fi Calling is off -->
<string name="wifi_calling_off_explanation">When Wi-Fi calling is on, your phone can route calls via Wi-Fi networks or your carrier\u2019s network, depending on your preference and which signal is stronger. Before turning on this feature, check with your carrier regarding fees and other details.</string>
+ <!-- Wi-Fi Calling settings. Additional text displayed when Wi-Fi Calling is off. Default empty. [CHAR LIMIT=NONE] -->
+ <string name="wifi_calling_off_explanation_2"></string>
<!-- Title of a preference for updating emergency address [CHAR LIMIT=40] -->
<string name="emergency_address_title">Update Emergency Address</string>
<!-- Summary of Update Emergency Address preference, explaining usage of emergency address [CHAR LIMIT=NONE] -->
@@ -4720,6 +4725,8 @@
<!-- Description for battery usage time for an app, i.e. Used for 30min. Note: ^1 should be used in all translations [CHAR LIMIT=60] -->
<string name="battery_used_for">Used for <xliff:g id="time">^1</xliff:g></string>
+ <!-- Description for battery screen usage time for an app, i.e. Screen usage 30min. Note: ^1 should be used in all translations [CHAR LIMIT=60] -->
+ <string name="battery_screen_usage">Screen usage <xliff:g id="time">^1</xliff:g></string>
<!-- Description for battery usage info for an app, i.e. 60% used by facebook. [CHAR LIMIT=60] -->
<string name="battery_used_by"><xliff:g id="percent">%1$s</xliff:g> used by <xliff:g id="app">%2$s</xliff:g></string>
<!-- Description for percentage of battery usage for an app, i.e. Screen: 30% of overall battery. [CHAR LIMIT=60] -->
@@ -6273,12 +6280,19 @@
<!-- Title for setting tile leading to network and Internet settings [CHAR LIMIT=40]-->
<string name="network_dashboard_title">Network & Internet</string>
- <!-- Summary for Network and Internet settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
- <string name="network_dashboard_summary">Wi-Fi, mobile, data usage, hotspot</string>
+ <!-- Summary for Network and Internet settings, explaining it contains mobile network setting [CHAR LIMIT=NONE]-->
+ <string name="network_dashboard_summary_mobile">mobile</string>
+ <!-- Summary for Network and Internet settings, explaining it contains network data usage setting [CHAR LIMIT=NONE]-->
+ <string name="network_dashboard_summary_data_usage">data usage</string>
+ <!-- Summary for Network and Internet settings, explaining it contains hotspot (tethering) setting [CHAR LIMIT=NONE]-->
+ <string name="network_dashboard_summary_hotspot">hotspot</string>
+
<!-- Title for setting tile leading to Connected devices settings [CHAR LIMIT=40]-->
<string name="connected_devices_dashboard_title">Connected devices</string>
<!-- Summary for Connected devices settings, explaning a few important settings under it [CHAR LIMIT=NONE]-->
<string name="connected_devices_dashboard_summary">Bluetooth, Cast, NFC</string>
+ <!-- Summary for Connected devices settings, explaning a few important settings under it [CHAR LIMIT=NONE]-->
+ <string name="connected_devices_dashboard_no_nfc_summary">Bluetooth, Cast</string>
<!-- Title for setting tile leading to Apps & Notification settings [CHAR LIMIT=40]-->
<string name="app_and_notification_dashboard_title">Apps & notifications</string>
<!-- Summary for Apps & Notification settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
@@ -8651,10 +8665,6 @@
<!-- Preference label for the Files storage section. [CHAR LIMIT=50] -->
<string name="storage_files">Files</string>
- <!-- Main settings screen item's title to go into the storage settings screen [CHAR LIMIT=25] -->
- <string name="storage_settings_2" product="tablet">Tablet storage</string>
- <string name="storage_settings_2" product="default">Phone storage</string>
-
<!-- Summary of a single storage volume used space. [CHAR LIMIT=24] -->
<string name="storage_size_large_alternate"><xliff:g id="number" example="128">^1</xliff:g><small> <xliff:g id="unit" example="KB">^2</xliff:g></small></string>
<!-- Summary of a single storage volume total space. [CHAR LIMIT=48]-->
diff --git a/res/xml/account_type_settings.xml b/res/xml/account_type_settings.xml
index ab997a5..0ba961f 100644
--- a/res/xml/account_type_settings.xml
+++ b/res/xml/account_type_settings.xml
@@ -19,11 +19,11 @@
android:title="@string/account_settings_title"
settings:keywords="@string/keywords_accounts">
- <Preference
- android:key="account_header"
- android:layout="@layout/account_header"
- android:selectable="false"
- android:order="-10000"/>
+ <com.android.settings.applications.LayoutPreference
+ android:key="account_header"
+ android:layout="@layout/settings_entity_header"
+ android:selectable="false"
+ android:order="-10000"/>
<Preference
android:key="account_sync"
diff --git a/res/xml/app_list_disclosure_settings.xml b/res/xml/app_list_disclosure_settings.xml
index 2aae95e..1daf15d 100644
--- a/res/xml/app_list_disclosure_settings.xml
+++ b/res/xml/app_list_disclosure_settings.xml
@@ -21,7 +21,7 @@
<PreferenceCategory
android:key="dashboard_tile_placeholder"/>
- <com.android.settings.widget.FooterPreference
+ <com.android.settingslib.widget.FooterPreference
android:title="@string/enterprise_privacy_apps_count_estimation_info"
android:selectable="false"/>
</PreferenceScreen>
diff --git a/res/xml/assist_gesture_settings.xml b/res/xml/assist_gesture_settings.xml
index 2cc5189..0dbf9c7 100644
--- a/res/xml/assist_gesture_settings.xml
+++ b/res/xml/assist_gesture_settings.xml
@@ -32,7 +32,7 @@
<com.android.settings.widget.SeekBarPreference
android:key="gesture_assist_sensitivity"
android:title="@string/assist_gesture_sensitivity_title"
- android:defaultValue="2"
- android:max="4" />
+ android:defaultValue="5"
+ android:max="10" />
</PreferenceScreen>
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index bed3aa6..718bb23 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -39,7 +39,7 @@
android:summary="@string/summary_placeholder"/>
<SwitchPreference
- android:key="gesture_swipe_down_fingerprint"
+ android:key="gesture_swipe_down_fingerprint_notifications"
android:title="@string/fingerprint_swipe_for_notifications_title"
android:summary="@string/fingerprint_swipe_for_notifications_summary"/>
diff --git a/res/xml/data_usage_metered_prefs.xml b/res/xml/data_usage_metered_prefs.xml
index a1f3110..aca87fb 100644
--- a/res/xml/data_usage_metered_prefs.xml
+++ b/res/xml/data_usage_metered_prefs.xml
@@ -35,7 +35,7 @@
</PreferenceCategory>
- <com.android.settings.widget.FooterPreference
+ <com.android.settingslib.widget.FooterPreference
android:title="@string/data_usage_metered_body"
android:selectable="false" />
diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml
index 1eea8dd..273b80d 100644
--- a/res/xml/development_prefs.xml
+++ b/res/xml/development_prefs.xml
@@ -412,12 +412,12 @@
android:entries="@array/app_process_limit_entries"
android:entryValues="@array/app_process_limit_values" />
- <!-- hiding for now.
+
<Preference
android:key="background_check"
android:fragment="com.android.settings.applications.BackgroundCheckSummary"
android:title="@string/background_check_pref" />
- -->
+
<SwitchPreference
android:key="show_all_anrs"
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index b3b6692..749b87d 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -97,12 +97,12 @@
android:title="@string/lift_to_wake_title" />
<Preference
- android:key="gesture_double_tap_screen"
+ android:key="gesture_double_tap_screen_display_summary"
android:title="@string/ambient_display_title"
android:fragment="com.android.settings.gestures.DoubleTapScreenSettings" />
<Preference
- android:key="gesture_pick_up"
+ android:key="gesture_pick_up_display_summary"
android:title="@string/ambient_display_pickup_title"
android:fragment="com.android.settings.gestures.PickupGestureSettings" />
diff --git a/res/xml/installed_app_details_ia.xml b/res/xml/installed_app_details.xml
similarity index 97%
rename from res/xml/installed_app_details_ia.xml
rename to res/xml/installed_app_details.xml
index 5f8e866..12f0442 100644
--- a/res/xml/installed_app_details_ia.xml
+++ b/res/xml/installed_app_details.xml
@@ -19,7 +19,7 @@
<com.android.settings.applications.LayoutPreference
android:key="header_view"
- android:layout="@layout/app_details"
+ android:layout="@layout/settings_entity_header"
android:selectable="false"
android:order="-10000"/>
diff --git a/res/xml/language_and_input.xml b/res/xml/language_and_input.xml
index 330ef9e..8c83767 100644
--- a/res/xml/language_and_input.xml
+++ b/res/xml/language_and_input.xml
@@ -66,22 +66,22 @@
android:title="@string/gesture_preference_title">
<Preference
- android:key="gesture_assist"
+ android:key="gesture_assist_input_summary"
android:title="@string/assist_gesture_title"
android:fragment="com.android.settings.gestures.AssistGestureSettings"/>
<Preference
- android:key="gesture_swipe_down_fingerprint"
+ android:key="gesture_swipe_down_fingerprint_input_summary"
android:title="@string/fingerprint_swipe_for_notifications_title"
android:fragment="com.android.settings.gestures.SwipeToNotificationSettings"/>
<Preference
- android:key="gesture_double_tap_screen"
+ android:key="gesture_double_tap_screen_input_summary"
android:title="@string/ambient_display_title"
android:fragment="com.android.settings.gestures.DoubleTapScreenSettings"/>
<Preference
- android:key="gesture_pick_up"
+ android:key="gesture_pick_up_input_summary"
android:title="@string/ambient_display_pickup_title"
android:fragment="com.android.settings.gestures.PickupGestureSettings"/>
@@ -91,12 +91,12 @@
android:fragment="com.android.settings.gestures.CameraLiftTriggerSettings"/>
<Preference
- android:key="gesture_double_tap_power"
+ android:key="gesture_double_tap_power_input_summary"
android:title="@string/double_tap_power_for_camera_title"
android:fragment="com.android.settings.gestures.DoubleTapPowerSettings"/>
<Preference
- android:key="gesture_double_twist"
+ android:key="gesture_double_twist_input_summary"
android:title="@string/double_twist_for_camera_mode_title"
android:fragment="com.android.settings.gestures.DoubleTwistGestureSettings"/>
@@ -110,7 +110,7 @@
android:dialogTitle="@string/pointer_speed"/>
<Preference
- android:key="tts_settings"
+ android:key="tts_settings_summary"
android:title="@string/tts_settings_title"
android:fragment="com.android.settings.tts.TextToSpeechSettings"/>
diff --git a/res/xml/manage_assist.xml b/res/xml/manage_assist.xml
index eadf45f..a96fb6b 100644
--- a/res/xml/manage_assist.xml
+++ b/res/xml/manage_assist.xml
@@ -26,7 +26,7 @@
android:fragment="com.android.settings.applications.assist.DefaultAssistPicker"/>
<Preference
- android:key="gesture_assist"
+ android:key="gesture_assist_application"
android:title="@string/assist_gesture_title"
android:fragment="com.android.settings.gestures.AssistGestureSettings"/>
diff --git a/res/xml/power_usage_detail_ia.xml b/res/xml/power_usage_detail.xml
similarity index 97%
rename from res/xml/power_usage_detail_ia.xml
rename to res/xml/power_usage_detail.xml
index 39e6c38..b7865d2 100644
--- a/res/xml/power_usage_detail_ia.xml
+++ b/res/xml/power_usage_detail.xml
@@ -19,7 +19,7 @@
<com.android.settings.applications.LayoutPreference
android:key="header_view"
- android:layout="@layout/app_details"
+ android:layout="@layout/settings_entity_header"
android:selectable="false"
android:order="-10000"/>
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 336110d..26503e4 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -57,6 +57,8 @@
public static final String KEY_DISPLAY_SIZE = "screen_zoom";
private static final String KEY_SCREEN_TIMEOUT = "screen_timeout";
+ private static final String KEY_PICK_UP = "gesture_pick_up_display_summary";
+ private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen_display_summary";
@Override
public int getMetricsCategory() {
@@ -105,9 +107,10 @@
controllers.add(new NightModePreferenceController(context));
controllers.add(new ScreenSaverPreferenceController(context));
controllers.add(new PickupGesturePreferenceController(
- context, lifecycle, ambientDisplayConfig, UserHandle.myUserId()));
+ context, lifecycle, ambientDisplayConfig, UserHandle.myUserId(), KEY_PICK_UP));
controllers.add(new DoubleTapScreenPreferenceController(
- context, lifecycle, ambientDisplayConfig, UserHandle.myUserId()));
+ context, lifecycle, ambientDisplayConfig, UserHandle.myUserId(),
+ KEY_DOUBLE_TAP_SCREEN));
controllers.add(new TapToWakePreferenceController(context));
controllers.add(new TimeoutPreferenceController(context, KEY_SCREEN_TIMEOUT));
controllers.add(new VrDisplayPreferenceController(context));
diff --git a/src/com/android/settings/WifiCallingSettings.java b/src/com/android/settings/WifiCallingSettings.java
index 78f9de6..cb661ed 100644
--- a/src/com/android/settings/WifiCallingSettings.java
+++ b/src/com/android/settings/WifiCallingSettings.java
@@ -152,7 +152,9 @@
mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
setEmptyView(mEmptyView);
- mEmptyView.setText(R.string.wifi_calling_off_explanation);
+ String emptyViewText = activity.getString(R.string.wifi_calling_off_explanation)
+ + activity.getString(R.string.wifi_calling_off_explanation_2);
+ mEmptyView.setText(emptyViewText);
}
@Override
diff --git a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
index 65959b4..5aee39f 100644
--- a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
@@ -22,9 +22,8 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
-import android.support.v7.preference.Preference;
-
import android.support.v7.preference.PreferenceScreen;
+
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Utils;
@@ -45,13 +44,12 @@
public static final String KEY_ACCOUNT_TYPE = "account_type";
public static final String KEY_ACCOUNT_LABEL = "account_label";
public static final String KEY_ACCOUNT_TITLE_RES = "account_title_res";
- public static final String KEY_ACCOUNT_HEADER = "account_header";
public static final String KEY_USER_HANDLE = "user_handle";
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ @VisibleForTesting
Account mAccount;
private String mAccountLabel;
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ @VisibleForTesting
String mAccountType;
private AccountSyncPreferenceController mAccountSynController;
private RemoveAccountPreferenceController mRemoveAccountController;
@@ -110,6 +108,8 @@
controllers.add(mAccountSynController);
mRemoveAccountController = new RemoveAccountPreferenceController(context, this);
controllers.add(mRemoveAccountController);
+ controllers.add(new AccountHeaderPreferenceController(
+ context, getActivity(), this, getArguments()));
return controllers;
}
@@ -127,8 +127,6 @@
@VisibleForTesting
void updateUi() {
- final Preference headerPreference = findPreference(KEY_ACCOUNT_HEADER);
- headerPreference.setTitle(mAccount.name);
final Context context = getContext();
UserHandle userHandle = null;
Bundle args = getArguments();
@@ -136,14 +134,12 @@
userHandle = args.getParcelable(KEY_USER_HANDLE);
}
final AuthenticatorHelper helper = new AuthenticatorHelper(context, userHandle, null);
- headerPreference.setIcon(helper.getDrawableForType(context, mAccountType));
final AccountTypePreferenceLoader accountTypePreferenceLoader =
- new AccountTypePreferenceLoader(this, helper, userHandle);
- PreferenceScreen prefs =
- accountTypePreferenceLoader.addPreferencesForType(mAccountType, getPreferenceScreen());
+ new AccountTypePreferenceLoader(this, helper, userHandle);
+ PreferenceScreen prefs = accountTypePreferenceLoader.addPreferencesForType(
+ mAccountType, getPreferenceScreen());
if (prefs != null) {
accountTypePreferenceLoader.updatePreferenceIntents(prefs, mAccountType, mAccount);
}
}
-
}
\ No newline at end of file
diff --git a/src/com/android/settings/accounts/AccountHeaderPreferenceController.java b/src/com/android/settings/accounts/AccountHeaderPreferenceController.java
new file mode 100644
index 0000000..4730e9e
--- /dev/null
+++ b/src/com/android/settings/accounts/AccountHeaderPreferenceController.java
@@ -0,0 +1,87 @@
+/*
+ * 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.accounts;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.accounts.AuthenticatorHelper;
+
+import static com.android.settings.accounts.AccountDetailDashboardFragment.KEY_ACCOUNT;
+import static com.android.settings.accounts.AccountDetailDashboardFragment.KEY_USER_HANDLE;
+
+public class AccountHeaderPreferenceController extends PreferenceController {
+
+ private static final String KEY_ACCOUNT_HEADER = "account_header";
+
+ private final Activity mActivity;
+ private final Fragment mHost;
+ private final Account mAccount;
+ private final UserHandle mUserHandle;
+
+ public AccountHeaderPreferenceController(Context context, Activity activity, Fragment host,
+ Bundle args) {
+ super(context);
+ mActivity = activity;
+ mHost = host;
+ if (args != null && args.containsKey(KEY_ACCOUNT)) {
+ mAccount = args.getParcelable(KEY_ACCOUNT);
+ } else {
+ mAccount = null;
+ }
+
+ if (args != null && args.containsKey(KEY_USER_HANDLE)) {
+ mUserHandle = args.getParcelable(KEY_USER_HANDLE);
+ } else {
+ mUserHandle = null;
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mAccount != null && mUserHandle != null;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_ACCOUNT_HEADER;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ final LayoutPreference headerPreference =
+ (LayoutPreference) screen.findPreference(KEY_ACCOUNT_HEADER);
+
+ final AuthenticatorHelper helper = new AuthenticatorHelper(mContext, mUserHandle, null);
+
+ EntityHeaderController
+ .newInstance(mActivity, mHost, headerPreference.findViewById(R.id.entity_header))
+ .setLabel(mAccount.name)
+ .setIcon(helper.getDrawableForType(mContext, mAccount.type))
+ .done(mActivity, true /* rebindButtons */);
+ }
+}
diff --git a/src/com/android/settings/accounts/AccountPreferenceController.java b/src/com/android/settings/accounts/AccountPreferenceController.java
index 2801f04..b0403b8 100644
--- a/src/com/android/settings/accounts/AccountPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountPreferenceController.java
@@ -123,9 +123,9 @@
*/
public boolean pendingRemoval;
/**
- * The map from account name to account preference
+ * The map from account key to account preference
*/
- public ArrayMap<CharSequence, AccountTypePreference> accountPreferences = new ArrayMap<>();
+ public ArrayMap<String, AccountTypePreference> accountPreferences = new ArrayMap<>();
}
public AccountPreferenceController(Context context, SettingsPreferenceFragment parent,
@@ -299,6 +299,11 @@
final ProfileData data = mProfiles.get(userInfo.id);
if (data != null) {
data.pendingRemoval = false;
+ if (userInfo.isEnabled()) {
+ // recreate the authentication helper to refresh the list of enabled accounts
+ data.authenticatorHelper =
+ new AuthenticatorHelper(mContext, userInfo.getUserHandle(), this);
+ }
return;
}
final Context context = mContext;
@@ -426,7 +431,7 @@
return;
}
if (profileData.userInfo.isEnabled()) {
- final ArrayMap<CharSequence, AccountTypePreference> preferenceToRemove =
+ final ArrayMap<String, AccountTypePreference> preferenceToRemove =
new ArrayMap<>(profileData.accountPreferences);
final ArrayList<AccountTypePreference> preferences = getAccountTypePreferences(
profileData.authenticatorHelper, profileData.userInfo.getUserHandle(),
@@ -435,18 +440,19 @@
for (int i = 0; i < count; i++) {
final AccountTypePreference preference = preferences.get(i);
preference.setOrder(i);
- if (!profileData.accountPreferences.containsValue(preference)) {
- profileData.preferenceGroup.addPreference(preferences.get(i));
- profileData.accountPreferences.put(preference.getTitle(), preference);
+ final String key = preference.getKey();
+ if (!profileData.accountPreferences.containsKey(key)) {
+ profileData.preferenceGroup.addPreference(preference);
+ profileData.accountPreferences.put(key, preference);
}
}
if (profileData.addAccountPreference != null) {
profileData.preferenceGroup.addPreference(profileData.addAccountPreference);
}
- for (CharSequence name : preferenceToRemove.keySet()) {
+ for (String key : preferenceToRemove.keySet()) {
profileData.preferenceGroup.removePreference(
- profileData.accountPreferences.get(name));
- profileData.accountPreferences.remove(name);
+ profileData.accountPreferences.get(key));
+ profileData.accountPreferences.remove(key);
}
} else {
profileData.preferenceGroup.removeAll();
@@ -471,8 +477,7 @@
}
private ArrayList<AccountTypePreference> getAccountTypePreferences(AuthenticatorHelper helper,
- UserHandle userHandle,
- ArrayMap<CharSequence, AccountTypePreference> preferenceToRemove) {
+ UserHandle userHandle, ArrayMap<String, AccountTypePreference> preferenceToRemove) {
final String[] accountTypes = helper.getEnabledAccountTypes();
final ArrayList<AccountTypePreference> accountTypePreferences =
new ArrayList<>(accountTypes.length);
@@ -497,7 +502,8 @@
// Add a preference row for each individual account
for (Account account : accounts) {
- final AccountTypePreference preference = preferenceToRemove.remove(account.name);
+ final AccountTypePreference preference =
+ preferenceToRemove.remove(AccountTypePreference.buildKey(account));
if (preference != null) {
accountTypePreferences.add(preference);
continue;
@@ -521,7 +527,7 @@
fragmentArguments.putParcelable(EXTRA_USER, userHandle);
accountTypePreferences.add(new AccountTypePreference(
prefContext, mMetricsFeatureProvider.getMetricsCategory(mParent),
- account.name, titleResPackageName, titleResId, label,
+ account, titleResPackageName, titleResId, label,
AccountDetailDashboardFragment.class.getName(), fragmentArguments, icon));
}
helper.preloadDrawableForType(mContext, accountType);
diff --git a/src/com/android/settings/accounts/AccountTypePreference.java b/src/com/android/settings/accounts/AccountTypePreference.java
index 0abfb50..4f92829 100644
--- a/src/com/android/settings/accounts/AccountTypePreference.java
+++ b/src/com/android/settings/accounts/AccountTypePreference.java
@@ -16,6 +16,7 @@
package com.android.settings.accounts;
+import android.accounts.Account;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -67,18 +68,11 @@
private final int mMetricsCategory;
- public AccountTypePreference(Context context, int metricsCategory, CharSequence title,
- String titleResPackageName, int titleResId, String fragment, Bundle fragmentArguments,
- Drawable icon) {
- this(context, metricsCategory, title, titleResPackageName, titleResId, null, fragment,
- fragmentArguments, icon);
- }
-
- public AccountTypePreference(Context context, int metricsCategory, CharSequence title,
+ public AccountTypePreference(Context context, int metricsCategory, Account account,
String titleResPackageName, int titleResId, CharSequence summary, String fragment,
Bundle fragmentArguments, Drawable icon) {
super(context);
- mTitle = title;
+ mTitle = account.name;
mTitleResPackageName = titleResPackageName;
mTitleResId = titleResId;
mSummary = summary;
@@ -87,7 +81,8 @@
mMetricsCategory = metricsCategory;
setWidgetLayoutResource(R.layout.account_type_preference);
- setTitle(title);
+ setKey(buildKey(account));
+ setTitle(mTitle);
setSummary(summary);
setIcon(icon);
@@ -115,6 +110,13 @@
return false;
}
+ /**
+ * Build a unique preference key based on account.
+ */
+ public static String buildKey(Account account) {
+ return String.valueOf(account.hashCode());
+ }
+
public CharSequence getTitle() {
return mTitle;
}
@@ -122,5 +124,4 @@
public CharSequence getSummary() {
return mSummary;
}
-
}
diff --git a/src/com/android/settings/applications/AppInfoWithHeader.java b/src/com/android/settings/applications/AppInfoWithHeader.java
index 6b1ef67..bbcec3c 100644
--- a/src/com/android/settings/applications/AppInfoWithHeader.java
+++ b/src/com/android/settings/applications/AppInfoWithHeader.java
@@ -16,17 +16,17 @@
package com.android.settings.applications;
-import static com.android.settings.applications.AppHeaderController.ActionType;
-
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.util.IconDrawableFactory;
import android.util.Log;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
+import static com.android.settings.widget.EntityHeaderController.ActionType;
+
public abstract class AppInfoWithHeader extends AppInfoBase {
private boolean mCreated;
@@ -41,9 +41,8 @@
mCreated = true;
if (mPackageInfo == null) return;
final Activity activity = getActivity();
- final Preference pref = FeatureFactory.getFactory(activity)
- .getApplicationFeatureProvider(activity)
- .newAppHeaderController(this, null /* appHeader */)
+ final Preference pref = EntityHeaderController
+ .newInstance(activity, this, null /* header */)
.setIcon(IconDrawableFactory.newInstance(activity)
.getBadgedIcon(mPackageInfo.applicationInfo))
.setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))
diff --git a/src/com/android/settings/applications/AppOpsDetails.java b/src/com/android/settings/applications/AppOpsDetails.java
index e6c040b..b488af6 100644
--- a/src/com/android/settings/applications/AppOpsDetails.java
+++ b/src/com/android/settings/applications/AppOpsDetails.java
@@ -28,6 +28,7 @@
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -43,6 +44,7 @@
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
+import com.android.settings.widget.EntityHeaderController;
import java.util.List;
@@ -64,7 +66,7 @@
final View appSnippet = mRootView.findViewById(R.id.app_snippet);
CharSequence label = mPm.getApplicationLabel(pkgInfo.applicationInfo);
Drawable icon = mPm.getApplicationIcon(pkgInfo.applicationInfo);
- InstalledAppDetails.setupAppSnippet(appSnippet, label, icon,
+ setupAppSnippet(appSnippet, label, icon,
pkgInfo != null ? pkgInfo.versionName : null);
}
@@ -191,4 +193,30 @@
setIntentAndFinish(true, true);
}
}
+
+ /**
+ * @deprecated app info pages should use {@link EntityHeaderController} to show the app header.
+ */
+ void setupAppSnippet(View appSnippet, CharSequence label, Drawable icon,
+ CharSequence versionName) {
+ LayoutInflater.from(appSnippet.getContext()).inflate(R.layout.widget_text_views,
+ appSnippet.findViewById(android.R.id.widget_frame));
+
+ ImageView iconView = appSnippet.findViewById(android.R.id.icon);
+ iconView.setImageDrawable(icon);
+ // Set application name.
+ TextView labelView = appSnippet.findViewById(android.R.id.title);
+ labelView.setText(label);
+ // Version number of application
+ TextView appVersion = appSnippet.findViewById(R.id.widget_text1);
+
+ if (!TextUtils.isEmpty(versionName)) {
+ appVersion.setSelected(true);
+ appVersion.setVisibility(View.VISIBLE);
+ appVersion.setText(appSnippet.getContext().getString(R.string.version_text,
+ String.valueOf(versionName)));
+ } else {
+ appVersion.setVisibility(View.INVISIBLE);
+ }
+ }
}
diff --git a/src/com/android/settings/applications/ApplicationFeatureProvider.java b/src/com/android/settings/applications/ApplicationFeatureProvider.java
index 3266fe0..bff93b8e 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProvider.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProvider.java
@@ -28,14 +28,8 @@
public interface ApplicationFeatureProvider {
/**
- * Returns a new {@link AppHeaderController} instance to customize app header.
- */
- AppHeaderController newAppHeaderController(Fragment fragment, View appHeader);
-
- /**
- *
- * Returns a new {@link InstantAppButtonsController} instance for showing buttons
- * only relevant to instant apps.
+ * Returns a new {@link InstantAppButtonsController} instance for showing buttons
+ * only relevant to instant apps.
*/
InstantAppButtonsController newInstantAppButtonsController(Fragment fragment,
View view, InstantAppButtonsController.ShowDialogDelegate showDialogDelegate);
@@ -44,7 +38,7 @@
* Calculates the total number of apps installed on the device via policy in the current user
* and all its managed profiles.
*
- * @param async Whether to count asynchronously in a background thread
+ * @param async Whether to count asynchronously in a background thread
* @param callback The callback to invoke with the result
*/
void calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback);
@@ -61,10 +55,10 @@
* Asynchronously calculates the total number of apps installed in the current user and all its
* managed profiles that have been granted one or more of the given permissions by the admin.
*
- * @param permissions Only consider apps that have been granted one or more of these permissions
- * by the admin, either at run-time or install-time
- * @param async Whether to count asynchronously in a background thread
- * @param callback The callback to invoke with the result
+ * @param permissions Only consider apps that have been granted one or more of these
+ * permissions by the admin, either at run-time or install-time
+ * @param async Whether to count asynchronously in a background thread
+ * @param callback The callback to invoke with the result
*/
void calculateNumberOfAppsWithAdminGrantedPermissions(String[] permissions, boolean async,
NumberOfAppsCallback callback);
@@ -73,9 +67,9 @@
* Asynchronously builds the list of apps installed in the current user and all its
* managed profiles that have been granted one or more of the given permissions by the admin.
*
- * @param permissions Only consider apps that have been granted one or more of these permissions
- * by the admin, either at run-time or install-time
- * @param callback The callback to invoke with the result
+ * @param permissions Only consider apps that have been granted one or more of these
+ * permissions by the admin, either at run-time or install-time
+ * @param callback The callback to invoke with the result
*/
void listAppsWithAdminGrantedPermissions(String[] permissions, ListOfAppsCallback callback);
@@ -85,10 +79,9 @@
* given intent (e.g. open browser), even if the user has other apps installed that would also
* be able to handle the intent.
*
- * @param userId ID of the user for which to find persistent preferred activities
- * @param intent The intents for which to find persistent preferred activities
- *
- * @return the persistent preferred activites for the given intents, ordered first by user id,
+ * @param userId ID of the user for which to find persistent preferred activities
+ * @param intents The intents for which to find persistent preferred activities
+ * @return the persistent preferred activities for the given intents, ordered first by user id,
* then by package name
*/
List<UserAppInfo> findPersistentPreferredActivities(@UserIdInt int userId, Intent[] intents);
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index a744792..36e0965 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -24,7 +24,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArraySet;
import android.view.View;
@@ -54,11 +53,6 @@
}
@Override
- public AppHeaderController newAppHeaderController(Fragment fragment, View appHeader) {
- return new AppHeaderController(mContext, fragment, appHeader);
- }
-
- @Override
public InstantAppButtonsController newInstantAppButtonsController(Fragment fragment,
View view, InstantAppButtonsController.ShowDialogDelegate showDialogDelegate) {
return new InstantAppButtonsController(mContext, fragment, view, showDialogDelegate);
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 6cc37e7..3021f75 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -37,7 +37,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
import android.icu.text.ListFormatter;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
@@ -60,16 +59,12 @@
import android.text.format.DateUtils;
import android.text.format.Formatter;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup;
import android.webkit.IWebViewUpdateService;
import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.BatterySipper;
@@ -96,6 +91,7 @@
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.AppItem;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils;
@@ -349,7 +345,7 @@
}
setHasOptionsMenu(true);
- addPreferencesFromResource(R.xml.installed_app_details_ia);
+ addPreferencesFromResource(R.xml.installed_app_details);
addDynamicPrefs();
if (Utils.isBandwidthControlEnabled()) {
INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
@@ -411,14 +407,12 @@
final Activity activity = getActivity();
mHeader = (LayoutPreference) findPreference(KEY_HEADER);
mActionButtons = (LayoutPreference) findPreference(KEY_ACTION_BUTTONS);
- FeatureFactory.getFactory(activity)
- .getApplicationFeatureProvider(activity)
- .newAppHeaderController(this, mHeader.findViewById(R.id.app_snippet))
+ EntityHeaderController.newInstance(activity, this, mHeader.findViewById(R.id.entity_header))
.setPackageName(mPackageName)
- .setButtonActions(AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
- AppHeaderController.ActionType.ACTION_NONE)
+ .setButtonActions(EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
+ EntityHeaderController.ActionType.ACTION_NONE)
.styleActionBar(activity)
- .bindAppHeaderButtons();
+ .bindHeaderButtons();
prepareUninstallAndStop();
mNotificationPreference = findPreference(KEY_NOTIFICATION);
@@ -584,15 +578,13 @@
// Utility method to set application label and icon.
private void setAppLabelAndIcon(PackageInfo pkgInfo) {
- final View appSnippet = mHeader.findViewById(R.id.app_snippet);
+ final View appSnippet = mHeader.findViewById(R.id.entity_header);
mState.ensureIcon(mAppEntry);
final Activity activity = getActivity();
final boolean isInstantApp = AppUtils.isInstant(mPackageInfo.applicationInfo);
final CharSequence summary =
isInstantApp ? null : getString(Utils.getInstallationStatus(mAppEntry.info));
- FeatureFactory.getFactory(activity)
- .getApplicationFeatureProvider(activity)
- .newAppHeaderController(this, appSnippet)
+ EntityHeaderController.newInstance(activity, this, appSnippet)
.setLabel(mAppEntry)
.setIcon(mAppEntry)
.setSummary(summary)
@@ -1245,32 +1237,6 @@
}
}
- /**
- * @deprecated app info pages should use {@link AppHeaderController} to show the app header.
- */
- public static void setupAppSnippet(View appSnippet, CharSequence label, Drawable icon,
- CharSequence versionName) {
- LayoutInflater.from(appSnippet.getContext()).inflate(R.layout.widget_text_views,
- (ViewGroup) appSnippet.findViewById(android.R.id.widget_frame));
-
- ImageView iconView = (ImageView) appSnippet.findViewById(R.id.app_detail_icon);
- iconView.setImageDrawable(icon);
- // Set application name.
- TextView labelView = (TextView) appSnippet.findViewById(R.id.app_detail_title);
- labelView.setText(label);
- // Version number of application
- TextView appVersion = (TextView) appSnippet.findViewById(R.id.widget_text1);
-
- if (!TextUtils.isEmpty(versionName)) {
- appVersion.setSelected(true);
- appVersion.setVisibility(View.VISIBLE);
- appVersion.setText(appSnippet.getContext().getString(R.string.version_text,
- String.valueOf(versionName)));
- } else {
- appVersion.setVisibility(View.INVISIBLE);
- }
- }
-
public static NetworkTemplate getTemplate(Context context) {
if (DataUsageList.hasReadyMobileRadio(context)) {
return NetworkTemplate.buildTemplateMobileWildcard();
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index b6b5861..6274374 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -506,10 +506,9 @@
}
@Override
- public void onResume() {
- super.onResume();
+ public void onStart() {
+ super.onStart();
updateView();
- updateOptionsMenu();
if (mApplications != null) {
mApplications.resume(mSortOrder);
mApplications.updateLoading();
@@ -527,16 +526,11 @@
}
@Override
- public void onPause() {
- super.onPause();
+ public void onStop() {
+ super.onStop();
if (mApplications != null) {
mApplications.pause();
}
- }
-
- @Override
- public void onStop() {
- super.onStop();
mResetAppsHelper.stop();
}
diff --git a/src/com/android/settings/applications/ProcessStatsDetail.java b/src/com/android/settings/applications/ProcessStatsDetail.java
index 6c0928c..9f229af 100644
--- a/src/com/android/settings/applications/ProcessStatsDetail.java
+++ b/src/com/android/settings/applications/ProcessStatsDetail.java
@@ -16,8 +16,6 @@
package com.android.settings.applications;
-import static com.android.settings.applications.AppHeaderController.ActionType;
-
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
@@ -53,7 +51,7 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.SummaryPreference;
import com.android.settings.applications.ProcStatsEntry.Service;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
import java.util.ArrayList;
import java.util.Collections;
@@ -61,6 +59,8 @@
import java.util.HashMap;
import java.util.List;
+import static com.android.settings.widget.EntityHeaderController.ActionType;
+
public class ProcessStatsDetail extends SettingsPreferenceFragment {
private static final String TAG = "ProcessStatsDetail";
@@ -126,9 +126,8 @@
return;
}
final Activity activity = getActivity();
- final Preference pref = FeatureFactory.getFactory(activity)
- .getApplicationFeatureProvider(activity)
- .newAppHeaderController(this, null /* appHeader */)
+ final Preference pref = EntityHeaderController
+ .newInstance(activity, this, null /* appHeader */)
.setIcon(mApp.mUiTargetApp != null
? IconDrawableFactory.newInstance(activity).getBadgedIcon(mApp.mUiTargetApp)
: new ColorDrawable(0))
diff --git a/src/com/android/settings/applications/assist/ManageAssist.java b/src/com/android/settings/applications/assist/ManageAssist.java
index e78e6e1..3b8edf3 100644
--- a/src/com/android/settings/applications/assist/ManageAssist.java
+++ b/src/com/android/settings/applications/assist/ManageAssist.java
@@ -38,6 +38,7 @@
public class ManageAssist extends DashboardFragment {
private static final String TAG = "ManageAssist";
+ private static final String KEY_ASSIST = "gesture_assist_application";
@Override
protected String getLogTag() {
@@ -71,7 +72,7 @@
Lifecycle lifecycle) {
final List<PreferenceController> controllers = new ArrayList<>();
controllers.add(new DefaultAssistPreferenceController(context));
- controllers.add(new AssistGesturePreferenceController(context, lifecycle));
+ controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST));
controllers.add(new AssistContextPreferenceController(context, lifecycle));
controllers.add(new AssistScreenshotPreferenceController(context, lifecycle));
controllers.add(new AssistFlashScreenPreferenceController(context, lifecycle));
@@ -94,5 +95,12 @@
public List<PreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context, null /* lifecycle */);
}
+
+ @Override
+ public List<String> getNonIndexableKeys(Context context) {
+ List<String> keys = super.getNonIndexableKeys(context);
+ keys.add(KEY_ASSIST);
+ return keys;
+ }
};
}
diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
index 7eb7fdd..59496dd 100644
--- a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
@@ -17,6 +17,7 @@
package com.android.settings.bluetooth;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
@@ -45,6 +46,12 @@
private static final String NOTIFICATION_TAG_PBAP = "Phonebook Access" ;
private static final String NOTIFICATION_TAG_MAP = "Message Access";
private static final String NOTIFICATION_TAG_SAP = "SIM Access";
+ /* TODO: Consolidate this multiple defined but common channel ID with other
+ * handlers that declare and use the same channel ID */
+ private static final String BLUETOOTH_NOTIFICATION_CHANNEL =
+ "bluetooth_notification_channel";
+
+ private NotificationChannel mNotificationChannel = null;
Context mContext;
int mRequestType;
@@ -151,7 +158,16 @@
deviceAlias, deviceAlias);
break;
}
- Notification notification = new Notification.Builder(context)
+ NotificationManager notificationManager =
+ (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ if (mNotificationChannel == null) {
+ mNotificationChannel = new NotificationChannel(BLUETOOTH_NOTIFICATION_CHANNEL,
+ context.getString(R.string.bluetooth),
+ NotificationManager.IMPORTANCE_HIGH);
+ notificationManager.createNotificationChannel(mNotificationChannel);
+ }
+ Notification notification = new Notification.Builder(context,
+ BLUETOOTH_NOTIFICATION_CHANNEL)
.setContentTitle(title)
.setTicker(message)
.setContentText(message)
@@ -169,9 +185,6 @@
notification.flags |= Notification.FLAG_NO_CLEAR; // Cannot be set with the builder.
- NotificationManager notificationManager =
- (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-
notificationManager.notify(getNotificationTag(mRequestType), NOTIFICATION_ID,
notification);
}
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
index cc519a7..6b172c2 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
@@ -15,9 +15,11 @@
*/
package com.android.settings.connecteddevice;
+import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.SearchIndexableResource;
+import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
@@ -25,6 +27,7 @@
import com.android.settings.bluetooth.Utils;
import com.android.settings.core.PreferenceController;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.deviceinfo.UsbBackend;
import com.android.settings.nfc.NfcPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -67,13 +70,50 @@
lifecycle.addObserver(mUsbPrefController);
controllers.add(mUsbPrefController);
final BluetoothMasterSwitchPreferenceController bluetoothPreferenceController =
- new BluetoothMasterSwitchPreferenceController(
- context, Utils.getLocalBtManager(context));
+ new BluetoothMasterSwitchPreferenceController(
+ context, Utils.getLocalBtManager(context));
lifecycle.addObserver(bluetoothPreferenceController);
controllers.add(bluetoothPreferenceController);
return controllers;
}
+ @VisibleForTesting
+ static class SummaryProvider implements SummaryLoader.SummaryProvider {
+
+ private final Context mContext;
+ private final SummaryLoader mSummaryLoader;
+ private final NfcPreferenceController mNfcPreferenceController;
+
+ public SummaryProvider(Context context, SummaryLoader summaryLoader) {
+ mContext = context;
+ mSummaryLoader = summaryLoader;
+ mNfcPreferenceController = new NfcPreferenceController(context);
+ }
+
+
+ @Override
+ public void setListening(boolean listening) {
+ if (listening) {
+ if (mNfcPreferenceController.isAvailable()) {
+ mSummaryLoader.setSummary(this,
+ mContext.getString(R.string.connected_devices_dashboard_summary));
+ } else {
+ mSummaryLoader.setSummary(this, mContext.getString(
+ R.string.connected_devices_dashboard_no_nfc_summary));
+ }
+ }
+ }
+ }
+
+ 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/core/instrumentation/SharedPreferencesLogger.java b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
index 69f174b..d1c7c7a 100644
--- a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
+++ b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
@@ -111,6 +111,9 @@
mPreferenceKeySet.add(prefKey);
return;
}
+ // TODO: Remove count logging to save some resource.
+ mMetricsFeature.count(mContext, prefKey + "|" + value, 1);
+
// Pref key exists in set, log it's change in metrics.
mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey),
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index 3d2db96..a47e135 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -41,9 +41,8 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
-import com.android.settings.applications.AppHeaderController;
import com.android.settings.applications.AppInfoBase;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.AppItem;
import com.android.settingslib.net.ChartData;
import com.android.settingslib.net.ChartDataLoader;
@@ -326,13 +325,12 @@
final boolean showInfoButton = mAppItem.key > 0;
final Activity activity = getActivity();
- final Preference pref = FeatureFactory.getFactory(activity)
- .getApplicationFeatureProvider(activity)
- .newAppHeaderController(this, null /* appHeader */)
+ final Preference pref = EntityHeaderController
+ .newInstance(activity, this, null /* header */)
.setButtonActions(showInfoButton
- ? AppHeaderController.ActionType.ACTION_APP_INFO
- : AppHeaderController.ActionType.ACTION_NONE,
- AppHeaderController.ActionType.ACTION_NONE)
+ ? EntityHeaderController.ActionType.ACTION_APP_INFO
+ : EntityHeaderController.ActionType.ACTION_NONE,
+ EntityHeaderController.ActionType.ACTION_NONE)
.setIcon(mIcon)
.setLabel(mLabel)
.setPackageName(pkg)
diff --git a/src/com/android/settings/development/TelephonyMonitorPreferenceController.java b/src/com/android/settings/development/TelephonyMonitorPreferenceController.java
index 135af7d..c21ccda 100644
--- a/src/com/android/settings/development/TelephonyMonitorPreferenceController.java
+++ b/src/com/android/settings/development/TelephonyMonitorPreferenceController.java
@@ -23,15 +23,27 @@
import android.support.v7.preference.PreferenceScreen;
import android.widget.Toast;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.core.PreferenceController;
import com.android.settings.R;
public class TelephonyMonitorPreferenceController extends PreferenceController {
private static final String KEY_TELEPHONY_MONITOR_SWITCH = "telephony_monitor_switch";
+ @VisibleForTesting
static final String BUILD_TYPE = "ro.build.type";
+ @VisibleForTesting
static final String PROPERTY_TELEPHONY_MONITOR = "persist.radio.enable_tel_mon";
+ @VisibleForTesting
+ static final String ENABLED_STATUS = "enabled";
+ @VisibleForTesting
+ static final String DISABLED_STATUS = "disabled";
+ @VisibleForTesting
+ static final String USER_ENABLED_STATUS = "user_enabled";
+ @VisibleForTesting
+ static final String USER_DISABLED_STATUS = "user_disabled";
+
private SwitchPreference mPreference;
public TelephonyMonitorPreferenceController(Context context) {
@@ -43,7 +55,7 @@
super.displayPreference(screen);
if (isAvailable()) {
mPreference = (SwitchPreference) screen.findPreference(KEY_TELEPHONY_MONITOR_SWITCH);
- mPreference.setChecked(SystemProperties.getBoolean(PROPERTY_TELEPHONY_MONITOR, false));
+ mPreference.setChecked(isTelephonyMonitorEnabled());
}
}
@@ -69,7 +81,7 @@
if (KEY_TELEPHONY_MONITOR_SWITCH.equals(preference.getKey())) {
final SwitchPreference switchPreference = (SwitchPreference) preference;
SystemProperties.set(PROPERTY_TELEPHONY_MONITOR,
- switchPreference.isChecked() ? "true" : "false");
+ switchPreference.isChecked() ? USER_ENABLED_STATUS : USER_DISABLED_STATUS);
Toast.makeText(mContext, R.string.telephony_monitor_toast,
Toast.LENGTH_LONG).show();
return true;
@@ -87,9 +99,14 @@
if (!isAvailable()) {
return false;
}
- final boolean enabled = SystemProperties.getBoolean(PROPERTY_TELEPHONY_MONITOR, false);
+ final boolean enabled = isTelephonyMonitorEnabled();
mPreference.setChecked(enabled);
return enabled;
}
+ private boolean isTelephonyMonitorEnabled() {
+ final String tmStatus = SystemProperties.get(PROPERTY_TELEPHONY_MONITOR, DISABLED_STATUS);
+ return ENABLED_STATUS.equals(tmStatus) || USER_ENABLED_STATUS.equals(tmStatus);
+ }
+
}
diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java
index b2bad3a..ce9ea9b 100644
--- a/src/com/android/settings/deviceinfo/StorageSettings.java
+++ b/src/com/android/settings/deviceinfo/StorageSettings.java
@@ -235,7 +235,7 @@
args.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
Intent intent = Utils.onBuildStartFragmentIntent(getActivity(),
StorageDashboardFragment.class.getName(), args, null,
- R.string.storage_settings_2, null, false, getMetricsCategory());
+ R.string.storage_settings, null, false, getMetricsCategory());
intent.putExtra(SettingsDrawerActivity.EXTRA_SHOW_MENU, true);
getActivity().startActivity(intent);
finish();
@@ -280,7 +280,7 @@
if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) {
startFragment(this, StorageDashboardFragment.class.getCanonicalName(),
- R.string.storage_settings_2, 0, args);
+ R.string.storage_settings, 0, args);
} else {
// TODO: Go to the StorageDashboardFragment once it fully handles all of the
// SD card cases and other private internal storage cases.
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
index b46fef7..2aad313 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
@@ -134,7 +134,7 @@
return;
}
}
- getFragmentManager().beginTransaction().remove(mSidecar).commit();
+ getFragmentManager().beginTransaction().remove(mSidecar).commitAllowingStateLoss();
mSidecar = null;
startActivityForResult(getEnrollingIntent(), ENROLLING);
}
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
index a1f4017..26b3427 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
@@ -17,6 +17,7 @@
package com.android.settings.fingerprint;
import android.app.KeyguardManager;
+import android.app.admin.DevicePolicyManager;
import android.content.Intent;
import android.content.res.Resources;
import android.os.UserHandle;
@@ -27,13 +28,19 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
+import com.android.settings.password.ChooseLockGeneric;
+import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
import com.android.settings.password.SetupChooseLockGeneric;
public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction {
@Override
protected Intent getChooseLockIntent() {
- Intent intent = new Intent(this, SetupChooseLockGeneric.class);
+ Intent intent = new Intent(this, SetupChooseLockGeneric.class)
+ .putExtra(
+ LockPatternUtils.PASSWORD_TYPE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
+ intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
SetupWizardUtils.copySetupExtras(getIntent(), intent);
return intent;
}
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 7a2e4c0..1822341 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -37,13 +37,12 @@
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
-import com.android.settings.applications.AppHeaderController;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.enterprise.DevicePolicyManagerWrapper;
import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
@@ -180,14 +179,13 @@
@VisibleForTesting
void initHeader() {
- final View appSnippet = mHeaderPreference.findViewById(R.id.app_snippet);
+ final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
final Activity context = getActivity();
final Bundle bundle = getArguments();
- AppHeaderController controller = FeatureFactory.getFactory(context)
- .getApplicationFeatureProvider(context)
- .newAppHeaderController(this, appSnippet)
- .setButtonActions(AppHeaderController.ActionType.ACTION_NONE,
- AppHeaderController.ActionType.ACTION_NONE);
+ EntityHeaderController controller = EntityHeaderController
+ .newInstance(context, this, appSnippet)
+ .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
+ EntityHeaderController.ActionType.ACTION_NONE);
if (mAppEntry == null) {
controller.setLabel(bundle.getString(EXTRA_LABEL));
@@ -224,7 +222,7 @@
@Override
protected int getPreferenceScreenResId() {
- return R.xml.power_usage_detail_ia;
+ return R.xml.power_usage_detail;
}
@Override
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 86cb203..849144a 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -22,7 +22,9 @@
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
+import android.text.format.DateUtils;
import android.util.Log;
+import android.util.SparseLongArray;
import com.android.internal.os.BatterySipper;
import com.android.settings.overlay.FeatureFactory;
@@ -115,25 +117,64 @@
}
/**
- * Remove the {@link BatterySipper} that we should hide.
+ * Remove the {@link BatterySipper} that we should hide and smear the screen usage based on
+ * foreground activity time.
*
* @param sippers sipper list that need to check and remove
* @return the total power of the hidden items of {@link BatterySipper}
+ * for proportional smearing
*/
public double removeHiddenBatterySippers(List<BatterySipper> sippers) {
- double totalPowerMah = 0;
+ double proportionalSmearPowerMah = 0;
+ BatterySipper screenSipper = null;
for (int i = sippers.size() - 1; i >= 0; i--) {
final BatterySipper sipper = sippers.get(i);
if (shouldHideSipper(sipper)) {
sippers.remove(i);
- if (sipper.drainType != BatterySipper.DrainType.OVERCOUNTED) {
- // Don't add it if it is overcounted
- totalPowerMah += sipper.totalPowerMah;
+ if (sipper.drainType != BatterySipper.DrainType.OVERCOUNTED
+ && sipper.drainType != BatterySipper.DrainType.SCREEN
+ && sipper.drainType != BatterySipper.DrainType.UNACCOUNTED) {
+ // Don't add it if it is overcounted, unaccounted or screen
+ proportionalSmearPowerMah += sipper.totalPowerMah;
}
}
+
+ if (sipper.drainType == BatterySipper.DrainType.SCREEN) {
+ screenSipper = sipper;
+ }
}
- return totalPowerMah;
+ smearScreenBatterySipper(sippers, screenSipper);
+
+ return proportionalSmearPowerMah;
+ }
+
+ /**
+ * Smear the screen on power usage among {@code sippers}, based on ratio of foreground activity
+ * time.
+ */
+ @VisibleForTesting
+ void smearScreenBatterySipper(List<BatterySipper> sippers, BatterySipper screenSipper) {
+ final long rawRealtimeMs = SystemClock.elapsedRealtime();
+ long totalActivityTimeMs = 0;
+ final SparseLongArray activityTimeArray = new SparseLongArray();
+ for (int i = 0, size = sippers.size(); i < size; i++) {
+ final BatteryStats.Uid uid = sippers.get(i).uidObj;
+ if (uid != null) {
+ final long timeMs = getForegroundActivityTotalTimeMs(uid, rawRealtimeMs);
+ activityTimeArray.put(uid.getUid(), timeMs);
+ totalActivityTimeMs += timeMs;
+ }
+ }
+
+ if (totalActivityTimeMs >= 10 * DateUtils.MINUTE_IN_MILLIS) {
+ final double screenPowerMah = screenSipper.totalPowerMah;
+ for (int i = 0, size = sippers.size(); i < size; i++) {
+ final BatterySipper sipper = sippers.get(i);
+ sipper.totalPowerMah += screenPowerMah * activityTimeArray.get(sipper.getUid(), 0)
+ / totalActivityTimeMs;
+ }
+ }
}
/**
@@ -144,9 +185,7 @@
return drainType == BatterySipper.DrainType.IDLE
|| drainType == BatterySipper.DrainType.CELL
- || drainType == BatterySipper.DrainType.WIFI
|| drainType == BatterySipper.DrainType.SCREEN
- || drainType == BatterySipper.DrainType.BLUETOOTH
|| drainType == BatterySipper.DrainType.UNACCOUNTED
|| drainType == BatterySipper.DrainType.OVERCOUNTED
|| (sipper.totalPowerMah * SECONDS_IN_HOUR) < MIN_POWER_THRESHOLD_MILLI_AMP
@@ -186,5 +225,15 @@
return mPackageManager == null;
}
+ @VisibleForTesting
+ long getForegroundActivityTotalTimeMs(BatteryStats.Uid uid, long rawRealtimeMs) {
+ final BatteryStats.Timer timer = uid.getForegroundActivityTimer();
+ if (timer != null) {
+ return timer.getTotalTimeLocked(rawRealtimeMs, BatteryStats.STATS_SINCE_CHARGED);
+ }
+
+ return 0;
+ }
+
}
diff --git a/src/com/android/settings/fuelgauge/FakeUid.java b/src/com/android/settings/fuelgauge/FakeUid.java
index 6f92b3d..6cb5c64 100644
--- a/src/com/android/settings/fuelgauge/FakeUid.java
+++ b/src/com/android/settings/fuelgauge/FakeUid.java
@@ -45,6 +45,11 @@
}
@Override
+ public Timer getAggregatedPartialWakelockTimer() {
+ return null;
+ }
+
+ @Override
public ArrayMap<String, ? extends Timer> getSyncStats() {
return null;
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java
index aee55d6..060abdd 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageBase.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java
@@ -57,7 +57,7 @@
mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(getContext());
mBatteryBroadcastReceiver.setBatteryChangedListener(() -> {
- getLoaderManager().restartLoader(0, null, this);
+ restartBatteryStatsLoader();
});
getLoaderManager().initLoader(0, icicle, this);
@@ -95,6 +95,10 @@
}
}
+ protected void restartBatteryStatsLoader() {
+ getLoaderManager().restartLoader(0, Bundle.EMPTY, this);
+ }
+
protected abstract void refreshUi();
protected void updatePreference(BatteryHistoryPreference historyPref) {
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 23895e3..c27ea22 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -113,7 +113,8 @@
@VisibleForTesting
static final int ANOMALY_LOADER = 1;
- private static final int BATTERY_ESTIMATE_LOADER = 2;
+ @VisibleForTesting
+ static final int BATTERY_ESTIMATE_LOADER = 2;
private static final int MENU_STATS_TYPE = Menu.FIRST;
@VisibleForTesting
static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3;
@@ -182,6 +183,7 @@
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
final Uri queryUri = mPowerFeatureProvider.getEnhancedBatteryPredictionUri();
+
return new CursorLoader(getContext(), queryUri, null, null, null, null);
}
@@ -228,10 +230,7 @@
mAnomalySparseArray = new SparseArray<>();
initFeatureProvider();
- if (mPowerFeatureProvider != null) {
- getLoaderManager().initLoader(BATTERY_ESTIMATE_LOADER, Bundle.EMPTY,
- mBatteryPredictionLoaderCallbacks);
- }
+ initializeBatteryEstimateLoader();
}
@Override
@@ -377,7 +376,7 @@
item.setTitle(mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
metricsFeatureProvider.action(context,
MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE, mShowAllApps);
- refreshUi();
+ restartBatteryStatsLoader();
return true;
default:
return super.onOptionsItemSelected(item);
@@ -760,7 +759,7 @@
final CharSequence timeSequence = Utils.formatElapsedTime(getContext(), usageTimeMs,
false);
preference.setSummary(
- TextUtils.expandTemplate(getText(R.string.battery_used_for), timeSequence));
+ TextUtils.expandTemplate(getText(R.string.battery_screen_usage), timeSequence));
}
}
@@ -815,6 +814,15 @@
}
}
+ @VisibleForTesting
+ void initializeBatteryEstimateLoader() {
+ if (mPowerFeatureProvider != null
+ && mPowerFeatureProvider.isEnhancedBatteryPredictionEnabled(getContext())) {
+ getLoaderManager().initLoader(BATTERY_ESTIMATE_LOADER, Bundle.EMPTY,
+ mBatteryPredictionLoaderCallbacks);
+ }
+ }
+
private static List<BatterySipper> getFakeStats() {
ArrayList<BatterySipper> stats = new ArrayList<>();
float use = 5;
diff --git a/src/com/android/settings/gestures/AssistGesturePreferenceController.java b/src/com/android/settings/gestures/AssistGesturePreferenceController.java
index c59c328..3230804 100644
--- a/src/com/android/settings/gestures/AssistGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/AssistGesturePreferenceController.java
@@ -35,7 +35,7 @@
implements OnPause, OnResume {
private static final String PREF_KEY_VIDEO = "gesture_assist_video";
- private static final String PREF_KEY_ASSIST_GESTURE = "gesture_assist";
+ private final String mAssistGesturePrefKey;
private final AssistGestureFeatureProvider mFeatureProvider;
private final SettingObserver mSettingObserver;
@@ -44,11 +44,12 @@
private PreferenceScreen mScreen;
private Preference mPreference;
- public AssistGesturePreferenceController(Context context, Lifecycle lifecycle) {
+ public AssistGesturePreferenceController(Context context, Lifecycle lifecycle, String key) {
super(context, lifecycle);
mFeatureProvider = FeatureFactory.getFactory(context).getAssistGestureFeatureProvider();
mSettingObserver = new SettingObserver();
mWasAvailable = isAvailable();
+ mAssistGesturePrefKey = key;
}
@Override
@@ -110,7 +111,7 @@
@Override
public String getPreferenceKey() {
- return PREF_KEY_ASSIST_GESTURE;
+ return mAssistGesturePrefKey;
}
@Override
diff --git a/src/com/android/settings/gestures/AssistGestureSettings.java b/src/com/android/settings/gestures/AssistGestureSettings.java
index 8874e3f..a080bec 100644
--- a/src/com/android/settings/gestures/AssistGestureSettings.java
+++ b/src/com/android/settings/gestures/AssistGestureSettings.java
@@ -34,6 +34,8 @@
private static final String TAG = "AssistGesture";
+ private static final String KEY_ASSIST = "gesture_assist";
+
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
@@ -57,7 +59,7 @@
private static List<PreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
final List<PreferenceController> controllers = new ArrayList<>();
- controllers.add(new AssistGesturePreferenceController(context, lifecycle));
+ controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST));
controllers.add(new AssistGestureSensitivityPreferenceController(context, lifecycle));
return controllers;
}
diff --git a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java
index df7f734..d36ecc4 100644
--- a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java
+++ b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java
@@ -20,18 +20,16 @@
import android.provider.Settings;
import android.support.v7.preference.Preference;
-import android.util.ArrayMap;
-import com.android.settings.search2.InlineSwitchPayload;
-import com.android.settings.search2.ResultPayload;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class DoubleTapPowerPreferenceController extends GesturePreferenceController {
private static final String PREF_KEY_VIDEO = "gesture_double_tap_power_video";
- private static final String PREF_KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power";
+ private final String mDoubleTapPowerKey;
- public DoubleTapPowerPreferenceController(Context context, Lifecycle lifecycle) {
+ public DoubleTapPowerPreferenceController(Context context, Lifecycle lifecycle, String key) {
super(context, lifecycle);
+ mDoubleTapPowerKey = key;
}
@Override
@@ -47,7 +45,7 @@
@Override
public String getPreferenceKey() {
- return PREF_KEY_DOUBLE_TAP_POWER;
+ return mDoubleTapPowerKey;
}
@Override
diff --git a/src/com/android/settings/gestures/DoubleTapPowerSettings.java b/src/com/android/settings/gestures/DoubleTapPowerSettings.java
index 111281f..d38292d 100644
--- a/src/com/android/settings/gestures/DoubleTapPowerSettings.java
+++ b/src/com/android/settings/gestures/DoubleTapPowerSettings.java
@@ -33,6 +33,7 @@
public class DoubleTapPowerSettings extends DashboardFragment {
private static final String TAG = "DoubleTapPower";
+ private static final String KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power";
@Override
public int getMetricsCategory() {
@@ -57,7 +58,8 @@
private static List<PreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
final List<PreferenceController> controllers = new ArrayList<>();
- controllers.add(new DoubleTapPowerPreferenceController(context, lifecycle));
+ controllers.add(new DoubleTapPowerPreferenceController(context, lifecycle,
+ KEY_DOUBLE_TAP_POWER));
return controllers;
}
diff --git a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
index 38d29a0..a38e4b6 100644
--- a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
+++ b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
@@ -21,26 +21,24 @@
import android.provider.Settings;
import android.support.v7.preference.Preference;
-import android.util.ArrayMap;
import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.settings.search2.InlineSwitchPayload;
-import com.android.settings.search2.ResultPayload;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class DoubleTapScreenPreferenceController extends GesturePreferenceController {
private static final String PREF_KEY_VIDEO = "gesture_double_tap_screen_video";
- private static final String PREF_KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen";
+ private final String mDoubleTapScreenPrefKey;
private final AmbientDisplayConfiguration mAmbientConfig;
@UserIdInt
private final int mUserId;
public DoubleTapScreenPreferenceController(Context context, Lifecycle lifecycle,
- AmbientDisplayConfiguration config, @UserIdInt int userId) {
+ AmbientDisplayConfiguration config, @UserIdInt int userId, String key) {
super(context, lifecycle);
mAmbientConfig = config;
mUserId = userId;
+ mDoubleTapScreenPrefKey = key;
}
@Override
@@ -50,7 +48,7 @@
@Override
public String getPreferenceKey() {
- return PREF_KEY_DOUBLE_TAP_SCREEN;
+ return mDoubleTapScreenPrefKey;
}
@Override
diff --git a/src/com/android/settings/gestures/DoubleTapScreenSettings.java b/src/com/android/settings/gestures/DoubleTapScreenSettings.java
index 20adbbe..4a80273 100644
--- a/src/com/android/settings/gestures/DoubleTapScreenSettings.java
+++ b/src/com/android/settings/gestures/DoubleTapScreenSettings.java
@@ -35,6 +35,7 @@
public class DoubleTapScreenSettings extends DashboardFragment {
private static final String TAG = "DoubleTapScreen";
+ private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen";
@Override
public int getMetricsCategory() {
@@ -60,7 +61,8 @@
Lifecycle lifecycle) {
final List<PreferenceController> controllers = new ArrayList<>();
controllers.add(new DoubleTapScreenPreferenceController(context, lifecycle,
- new AmbientDisplayConfiguration(context), UserHandle.myUserId()));
+ new AmbientDisplayConfiguration(context), UserHandle.myUserId(),
+ KEY_DOUBLE_TAP_SCREEN));
return controllers;
}
diff --git a/src/com/android/settings/gestures/DoubleTwistGestureSettings.java b/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
index 5a0ff12..2b46cce 100644
--- a/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
+++ b/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
@@ -33,6 +33,7 @@
public class DoubleTwistGestureSettings extends DashboardFragment {
private static final String TAG = "DoubleTwistGesture";
+ private static final String KEY_DOUBLE_TWIST = "gesture_double_twist";
@Override
public int getMetricsCategory() {
@@ -57,7 +58,7 @@
private static List<PreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
final List<PreferenceController> controllers = new ArrayList<>();
- controllers.add(new DoubleTwistPreferenceController(context, lifecycle));
+ controllers.add(new DoubleTwistPreferenceController(context, lifecycle, KEY_DOUBLE_TWIST));
return controllers;
}
diff --git a/src/com/android/settings/gestures/DoubleTwistPreferenceController.java b/src/com/android/settings/gestures/DoubleTwistPreferenceController.java
index eb47588..69f9e8d 100644
--- a/src/com/android/settings/gestures/DoubleTwistPreferenceController.java
+++ b/src/com/android/settings/gestures/DoubleTwistPreferenceController.java
@@ -24,19 +24,17 @@
import android.support.v7.preference.Preference;
import android.text.TextUtils;
-import android.util.ArrayMap;
import com.android.settings.R;
-import com.android.settings.search2.InlineSwitchPayload;
-import com.android.settings.search2.ResultPayload;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class DoubleTwistPreferenceController extends GesturePreferenceController {
private static final String PREF_KEY_VIDEO = "gesture_double_twist_video";
- private static final String PREF_KEY_DOUBLE_TWIST = "gesture_double_twist";
+ private final String mDoubleTwistPrefKey;
- public DoubleTwistPreferenceController(Context context, Lifecycle lifecycle) {
+ public DoubleTwistPreferenceController(Context context, Lifecycle lifecycle, String key) {
super(context, lifecycle);
+ mDoubleTwistPrefKey = key;
}
@Override
@@ -52,7 +50,7 @@
@Override
public String getPreferenceKey() {
- return PREF_KEY_DOUBLE_TWIST;
+ return mDoubleTwistPrefKey;
}
@Override
diff --git a/src/com/android/settings/gestures/PickupGesturePreferenceController.java b/src/com/android/settings/gestures/PickupGesturePreferenceController.java
index 19537f6..a6ce1a1 100644
--- a/src/com/android/settings/gestures/PickupGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/PickupGesturePreferenceController.java
@@ -21,26 +21,24 @@
import android.provider.Settings;
import android.support.v7.preference.Preference;
-import android.util.ArrayMap;
import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.settings.search2.InlineSwitchPayload;
-import com.android.settings.search2.ResultPayload;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class PickupGesturePreferenceController extends GesturePreferenceController {
private static final String PREF_VIDEO_KEY = "gesture_pick_up_video";
- private static final String PREF_KEY_PICK_UP = "gesture_pick_up";
+ private final String mPickUpPrefKey;
private final AmbientDisplayConfiguration mAmbientConfig;
@UserIdInt
private final int mUserId;
public PickupGesturePreferenceController(Context context, Lifecycle lifecycle,
- AmbientDisplayConfiguration config, @UserIdInt int userId) {
+ AmbientDisplayConfiguration config, @UserIdInt int userId, String key) {
super(context, lifecycle);
mAmbientConfig = config;
mUserId = userId;
+ mPickUpPrefKey = key;
}
@Override
@@ -60,7 +58,7 @@
@Override
public String getPreferenceKey() {
- return PREF_KEY_PICK_UP;
+ return mPickUpPrefKey;
}
@Override
diff --git a/src/com/android/settings/gestures/PickupGestureSettings.java b/src/com/android/settings/gestures/PickupGestureSettings.java
index ce4d9d7..6ed412f 100644
--- a/src/com/android/settings/gestures/PickupGestureSettings.java
+++ b/src/com/android/settings/gestures/PickupGestureSettings.java
@@ -35,6 +35,7 @@
public class PickupGestureSettings extends DashboardFragment {
private static final String TAG = "PickupGestureSettings";
+ private static final String KEY_PICK_UP = "gesture_pick_up";
@Override
public int getMetricsCategory() {
@@ -60,7 +61,7 @@
Lifecycle lifecycle) {
final List<PreferenceController> controllers = new ArrayList<>();
controllers.add(new PickupGesturePreferenceController(context, lifecycle,
- new AmbientDisplayConfiguration(context), UserHandle.myUserId()));
+ new AmbientDisplayConfiguration(context), UserHandle.myUserId(), KEY_PICK_UP));
return controllers;
}
diff --git a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
index 821eb04..75cffa5 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
@@ -28,15 +28,17 @@
public class SwipeToNotificationPreferenceController extends GesturePreferenceController {
private static final String PREF_KEY_VIDEO = "gesture_swipe_down_fingerprint_video";
- private static final String PREF_KEY_SWIPE_DOWN_FINGERPRINT = "gesture_swipe_down_fingerprint";
+ private final String mSwipeDownFingerPrefKey;
- public SwipeToNotificationPreferenceController(Context context, Lifecycle lifecycle) {
+ public SwipeToNotificationPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
super(context, lifecycle);
+ mSwipeDownFingerPrefKey = key;
}
@Override
public String getPreferenceKey() {
- return PREF_KEY_SWIPE_DOWN_FINGERPRINT;
+ return mSwipeDownFingerPrefKey;
}
@Override
diff --git a/src/com/android/settings/gestures/SwipeToNotificationSettings.java b/src/com/android/settings/gestures/SwipeToNotificationSettings.java
index 0cfc922..00d4700 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationSettings.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationSettings.java
@@ -34,6 +34,8 @@
private static final String TAG = "SwipeToNotifSettings";
+ private static final String KEY = "gesture_swipe_down_fingerprint";
+
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.SETTINGS_GESTURE_SWIPE_TO_NOTIFICATION;
@@ -57,7 +59,7 @@
private static List<PreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
final List<PreferenceController> controllers = new ArrayList<>();
- controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle));
+ controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle, KEY));
return controllers;
}
diff --git a/src/com/android/settings/language/LanguageAndInputSettings.java b/src/com/android/settings/language/LanguageAndInputSettings.java
index ffaab67..3818511 100644
--- a/src/com/android/settings/language/LanguageAndInputSettings.java
+++ b/src/com/android/settings/language/LanguageAndInputSettings.java
@@ -60,6 +60,13 @@
private static final String TAG = "LangAndInputSettings";
+ private static final String KEY_TEXT_TO_SPEECH = "tts_settings_summary";
+ private static final String KEY_ASSIST = "gesture_assist_input_summary";
+ private static final String KEY_SWIPE_DOWN = "gesture_swipe_down_fingerprint_input_summary";
+ private static final String KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power_input_summary";
+ private static final String KEY_DOUBLE_TWIST = "gesture_double_twist_input_summary";
+ private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen_input_summary";
+ private static final String KEY_PICK_UP = "gesture_pick_up_input_summary";
private static final String KEY_CAMERA_LIFT_TRIGGER = "gesture_camera_lift_trigger_summary";
private AmbientDisplayConfiguration mAmbientDisplayConfig;
@@ -128,14 +135,16 @@
controllers.add(gameControllerPreferenceController);
// Gestures
- controllers.add(new AssistGesturePreferenceController(context, lifecycle));
- controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle));
- controllers.add(new DoubleTwistPreferenceController(context, lifecycle));
- controllers.add(new DoubleTapPowerPreferenceController(context, lifecycle));
- controllers.add(new PickupGesturePreferenceController(
- context, lifecycle, ambientDisplayConfiguration, UserHandle.myUserId()));
- controllers.add(new DoubleTapScreenPreferenceController(
- context, lifecycle, ambientDisplayConfiguration, UserHandle.myUserId()));
+ controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST));
+ controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle,
+ KEY_SWIPE_DOWN));
+ controllers.add(new DoubleTwistPreferenceController(context, lifecycle, KEY_DOUBLE_TWIST));
+ controllers.add(new DoubleTapPowerPreferenceController(context, lifecycle,
+ KEY_DOUBLE_TAP_POWER));
+ controllers.add(new PickupGesturePreferenceController(context, lifecycle,
+ ambientDisplayConfiguration, UserHandle.myUserId(), KEY_PICK_UP));
+ controllers.add(new DoubleTapScreenPreferenceController(context, lifecycle,
+ ambientDisplayConfiguration, UserHandle.myUserId(), KEY_DOUBLE_TAP_SCREEN));
controllers.add(new CameraLiftTriggerPreferenceController(context, lifecycle,
KEY_CAMERA_LIFT_TRIGGER));
controllers.add(new DefaultAutofillPreferenceController(context));
@@ -199,5 +208,20 @@
return buildPreferenceControllers(context, null,
new AmbientDisplayConfiguration(context));
}
+
+ @Override
+ public List<String> getNonIndexableKeys(Context context) {
+ List<String> keys = super.getNonIndexableKeys(context);
+ // Duplicates in summary and details pages.
+ keys.add(KEY_TEXT_TO_SPEECH);
+ keys.add(KEY_ASSIST);
+ keys.add(KEY_SWIPE_DOWN);
+ keys.add(KEY_DOUBLE_TAP_POWER);
+ keys.add(KEY_DOUBLE_TWIST);
+ keys.add(KEY_DOUBLE_TAP_SCREEN);
+ keys.add(KEY_PICK_UP);
+
+ return keys;
+ }
};
}
diff --git a/src/com/android/settings/language/TtsPreferenceController.java b/src/com/android/settings/language/TtsPreferenceController.java
index 0d1c753..a734e4b 100644
--- a/src/com/android/settings/language/TtsPreferenceController.java
+++ b/src/com/android/settings/language/TtsPreferenceController.java
@@ -23,7 +23,8 @@
public class TtsPreferenceController extends PreferenceController {
- private static final String KEY_TTS_SETTINGS = "tts_settings";
+ private static final String KEY_VOICE_CATEGORY = "voice_category";
+ private static final String KEY_TTS_SETTINGS = "tts_settings_summary";
private final TtsEngines mTtsEngines;
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index d567971..869cef9 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -15,10 +15,12 @@
*/
package com.android.settings.network;
+import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.provider.SearchIndexableResource;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -27,7 +29,7 @@
import com.android.settings.R;
import com.android.settings.core.PreferenceController;
import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.wifi.WifiMasterSwitchPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -133,6 +135,66 @@
return 0;
}
+ @VisibleForTesting
+ static class SummaryProvider implements SummaryLoader.SummaryProvider {
+
+ private final Context mContext;
+ private final SummaryLoader mSummaryLoader;
+ private final MobileNetworkPreferenceController mMobileNetworkPreferenceController;
+ private final TetherPreferenceController mTetherPreferenceController;
+
+ public SummaryProvider(Context context, SummaryLoader summaryLoader) {
+ this(context, summaryLoader,
+ new MobileNetworkPreferenceController(context),
+ new TetherPreferenceController(context, null /* lifecycle */));
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ SummaryProvider(Context context, SummaryLoader summaryLoader,
+ MobileNetworkPreferenceController mobileNetworkPreferenceController,
+ TetherPreferenceController tetherPreferenceController) {
+ mContext = context;
+ mSummaryLoader = summaryLoader;
+ mMobileNetworkPreferenceController = mobileNetworkPreferenceController;
+ mTetherPreferenceController = tetherPreferenceController;
+ }
+
+
+ @Override
+ public void setListening(boolean listening) {
+ if (listening) {
+ String summary = mContext.getString(R.string.wifi_settings_title);
+ if (mMobileNetworkPreferenceController.isAvailable()) {
+ final String mobileSettingSummary = mContext.getString(
+ R.string.network_dashboard_summary_mobile);
+ summary = mContext.getString(R.string.join_many_items_middle, summary,
+ mobileSettingSummary);
+ }
+ final String dataUsageSettingSummary = mContext.getString(
+ R.string.network_dashboard_summary_data_usage);
+ summary = mContext.getString(R.string.join_many_items_middle, summary,
+ dataUsageSettingSummary);
+ if (mTetherPreferenceController.isAvailable()) {
+ final String hotspotSettingSummary = mContext.getString(
+ R.string.network_dashboard_summary_hotspot);
+ summary = mContext.getString(R.string.join_many_items_middle, summary,
+ hotspotSettingSummary);
+ }
+ mSummaryLoader.setSummary(this, summary);
+ }
+ }
+ }
+
+ 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);
+ }
+ };
+
+
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 03a71ca..92ad3f1 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -16,10 +16,6 @@
package com.android.settings.notification;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
-
import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
@@ -41,22 +37,24 @@
import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.Utils;
-import com.android.settings.applications.AppHeaderController;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.notification.NotificationBackend.AppRow;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
import com.android.settings.widget.MasterSwitchPreference;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.widget.FooterPreference;
-import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+
/** These settings are per app, so should not be returned in global search results. */
public class AppNotificationSettings extends NotificationSettingsBase {
private static final String TAG = "AppNotificationSettings";
@@ -128,19 +126,18 @@
}
private void addHeaderPref() {
- ArrayMap<String, AppRow> rows = new ArrayMap<String, AppRow>();
+ ArrayMap<String, AppRow> rows = new ArrayMap<>();
rows.put(mAppRow.pkg, mAppRow);
collectConfigActivities(rows);
final Activity activity = getActivity();
- final Preference pref = FeatureFactory.getFactory(activity)
- .getApplicationFeatureProvider(activity)
- .newAppHeaderController(this /* fragment */, null /* appHeader */)
+ final Preference pref = EntityHeaderController
+ .newInstance(activity, this /* fragment */, null /* header */)
.setIcon(mAppRow.icon)
.setLabel(mAppRow.label)
.setPackageName(mAppRow.pkg)
.setUid(mAppRow.uid)
- .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
- AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
+ .setButtonActions(EntityHeaderController.ActionType.ACTION_APP_INFO,
+ EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
.done(activity, getPrefContext());
pref.setKey(KEY_HEADER);
getPreferenceScreen().addPreference(pref);
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index 0ce9ec3..85a56ba 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -16,18 +16,12 @@
package com.android.settings.notification;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
-
import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Intent;
-import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.Bundle;
-import android.os.UserHandle;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
@@ -38,19 +32,21 @@
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.widget.LockPatternUtils;
import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.RingtonePreference;
import com.android.settings.Utils;
-import com.android.settings.applications.AppHeaderController;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.LayoutPreference;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.widget.FooterPreference;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+
public class ChannelNotificationSettings extends NotificationSettingsBase {
private static final String TAG = "ChannelSettings";
@@ -110,20 +106,19 @@
}
private void addHeaderPref() {
- ArrayMap<String, NotificationBackend.AppRow> rows = new ArrayMap<String, NotificationBackend.AppRow>();
+ ArrayMap<String, NotificationBackend.AppRow> rows = new ArrayMap<>();
rows.put(mAppRow.pkg, mAppRow);
collectConfigActivities(rows);
final Activity activity = getActivity();
- final Preference pref = FeatureFactory.getFactory(activity)
- .getApplicationFeatureProvider(activity)
- .newAppHeaderController(this /* fragment */, null /* appHeader */)
+ final Preference pref = EntityHeaderController
+ .newInstance(activity, this /* fragment */, null /* header */)
.setIcon(mAppRow.icon)
.setLabel(mChannel.getName())
.setSummary(mAppRow.label)
.setPackageName(mAppRow.pkg)
.setUid(mAppRow.uid)
- .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
- AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
+ .setButtonActions(EntityHeaderController.ActionType.ACTION_APP_INFO,
+ EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
.done(activity, getPrefContext());
getPreferenceScreen().addPreference(pref);
}
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index c3d8b81..ad71e83 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -35,6 +35,8 @@
public class ConfigureNotificationSettings extends DashboardFragment {
private static final String TAG = "ConfigNotiSettings";
+ private static final String KEY_SWIPE_DOWN = "gesture_swipe_down_fingerprint_notifications";
+
@Override
public int getMetricsCategory() {
return MetricsEvent.CONFIGURE_NOTIFICATION;
@@ -68,7 +70,8 @@
lifecycle.addObserver(pulseController);
lifecycle.addObserver(lockScreenNotificationController);
}
- controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle));
+ controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle,
+ KEY_SWIPE_DOWN));
controllers.add(badgeController);
controllers.add(pulseController);
controllers.add(lockScreenNotificationController);
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 6f1d350..60893b2 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -30,8 +30,8 @@
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.gestures.AssistGestureFeatureProvider;
import com.android.settings.localepicker.LocaleFeatureProvider;
-import com.android.settings.security.SecurityFeatureProvider;
import com.android.settings.search2.SearchFeatureProvider;
+import com.android.settings.security.SecurityFeatureProvider;
import com.android.settings.users.UserFeatureProvider;
/**
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index a56ac83..3f68e5a 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -29,7 +29,6 @@
import android.app.FragmentManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.hardware.fingerprint.Fingerprint;
@@ -40,6 +39,7 @@
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.security.KeyStore;
+import android.support.annotation.StringRes;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
@@ -95,14 +95,9 @@
}
public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
+
private static final String TAG = "ChooseLockGenericFragment";
private static final int MIN_PASSWORD_LENGTH = 4;
- private static final String KEY_UNLOCK_SET_OFF = "unlock_set_off";
- private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none";
- private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin";
- private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password";
- private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern";
- private static final String KEY_UNLOCK_SET_MANAGED = "unlock_set_managed";
private static final String KEY_SKIP_FINGERPRINT = "unlock_skip_fingerprint";
private static final String PASSWORD_CONFIRMED = "password_confirmed";
private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
@@ -112,6 +107,27 @@
public static final String ENCRYPT_REQUESTED_DISABLED = "encrypt_requested_disabled";
public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog";
+ /**
+ * Boolean extra determining whether a "screen lock options" button should be shown. This
+ * extra is both sent and received by ChooseLockGeneric.
+ *
+ * When this extra is false, nothing will be done.
+ * When ChooseLockGeneric receives this extra set as true, and if ChooseLockGeneric is
+ * starting ChooseLockPassword or ChooseLockPattern automatically without user interaction,
+ * ChooseLockGeneric will set this extra to true when starting ChooseLockPassword/Pattern.
+ *
+ * This gives the user the choice to select a different screen lock type, even if
+ * ChooseLockGeneric selected a default.
+ */
+ public static final String EXTRA_SHOW_OPTIONS_BUTTON = "show_options_button";
+
+ /**
+ * Original intent extras used to start this activity. This is passed to ChooseLockPassword
+ * when the "screen lock options" button is shown, so that when that button is clicked,
+ * ChooseLockGeneric can be relaunched with the same extras.
+ */
+ public static final String EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS = "choose_lock_generic_extras";
+
private static final int CONFIRM_EXISTING_REQUEST = 100;
private static final int ENABLE_ENCRYPTION_REQUEST = 101;
private static final int CHOOSE_LOCK_REQUEST = 102;
@@ -136,6 +152,7 @@
private ManagedLockPasswordProvider mManagedPasswordProvider;
private boolean mIsSetNewPassword = false;
private UserManager mUserManager;
+ private ChooseLockGenericController mController;
protected boolean mForFingerprint = false;
@@ -192,6 +209,7 @@
UserManager.get(getActivity()),
getArguments(),
getActivity().getIntent().getExtras()).getIdentifier();
+ mController = new ChooseLockGenericController(getContext(), mUserId);
if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
&& UserManager.get(getActivity()).isManagedProfile(mUserId)
&& mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
@@ -303,7 +321,7 @@
finish();
return;
}
- updateUnlockMethodAndFinish(quality, disabled);
+ updateUnlockMethodAndFinish(quality, disabled, false /* chooseLockSkipped */);
}
}
@@ -328,6 +346,15 @@
if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) {
getActivity().setResult(resultCode, data);
finish();
+ } else {
+ // If PASSWORD_TYPE_KEY is set, this activity is used as a trampoline to start
+ // the actual password enrollment. If the result is canceled, which means the
+ // user pressed back, finish the activity with result canceled.
+ int quality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
+ if (quality != -1) {
+ getActivity().setResult(RESULT_CANCELED, data);
+ finish();
+ }
}
} else if (requestCode == CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
&& resultCode == FingerprintEnrollBase.RESULT_FINISHED) {
@@ -374,7 +401,7 @@
if (quality == -1) {
// If caller didn't specify password quality, show UI and allow the user to choose.
quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);
- quality = upgradeQuality(quality);
+ quality = mController.upgradeQuality(quality);
final boolean hideDisabledPrefs = intent.getBooleanExtra(
HIDE_DISABLED_PREFS, false);
final PreferenceScreen prefScreen = getPreferenceScreen();
@@ -387,7 +414,7 @@
updateCurrentPreference();
updatePreferenceSummaryIfNeeded();
} else {
- updateUnlockMethodAndFinish(quality, false);
+ updateUnlockMethodAndFinish(quality, false, true /* chooseLockSkipped */);
}
}
@@ -395,33 +422,26 @@
addPreferencesFromResource(R.xml.security_settings_picker);
// Used for testing purposes
- findPreference(KEY_UNLOCK_SET_NONE).setViewId(R.id.lock_none);
+ findPreference(ScreenLockType.NONE.preferenceKey).setViewId(R.id.lock_none);
findPreference(KEY_SKIP_FINGERPRINT).setViewId(R.id.lock_none);
- findPreference(KEY_UNLOCK_SET_PIN).setViewId(R.id.lock_pin);
- findPreference(KEY_UNLOCK_SET_PASSWORD).setViewId(R.id.lock_password);
+ findPreference(ScreenLockType.PIN.preferenceKey).setViewId(R.id.lock_pin);
+ findPreference(ScreenLockType.PASSWORD.preferenceKey).setViewId(R.id.lock_password);
}
private void updatePreferenceText() {
if (mForFingerprint) {
- final String key[] = { KEY_UNLOCK_SET_PATTERN,
- KEY_UNLOCK_SET_PIN,
- KEY_UNLOCK_SET_PASSWORD };
- final int res[] = { R.string.fingerprint_unlock_set_unlock_pattern,
- R.string.fingerprint_unlock_set_unlock_pin,
- R.string.fingerprint_unlock_set_unlock_password };
- for (int i = 0; i < key.length; i++) {
- Preference pref = findPreference(key[i]);
- if (pref != null) { // can be removed by device admin
- pref.setTitle(res[i]);
- }
- }
+ setPreferenceTitle(ScreenLockType.PATTERN,
+ R.string.fingerprint_unlock_set_unlock_pattern);
+ setPreferenceTitle(ScreenLockType.PIN, R.string.fingerprint_unlock_set_unlock_pin);
+ setPreferenceTitle(ScreenLockType.PASSWORD,
+ R.string.fingerprint_unlock_set_unlock_password);
}
if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
- Preference managed = findPreference(KEY_UNLOCK_SET_MANAGED);
- managed.setTitle(mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
+ setPreferenceTitle(ScreenLockType.MANAGED,
+ mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
} else {
- removePreference(KEY_UNLOCK_SET_MANAGED);
+ removePreference(ScreenLockType.MANAGED.preferenceKey);
}
if (!(mForFingerprint && mIsSetNewPassword)) {
@@ -429,6 +449,27 @@
}
}
+ private void setPreferenceTitle(ScreenLockType lock, @StringRes int title) {
+ Preference preference = findPreference(lock.preferenceKey);
+ if (preference != null) {
+ preference.setTitle(title);
+ }
+ }
+
+ private void setPreferenceTitle(ScreenLockType lock, CharSequence title) {
+ Preference preference = findPreference(lock.preferenceKey);
+ if (preference != null) {
+ preference.setTitle(title);
+ }
+ }
+
+ private void setPreferenceSummary(ScreenLockType lock, @StringRes int summary) {
+ Preference preference = findPreference(lock.preferenceKey);
+ if (preference != null) {
+ preference.setSummary(summary);
+ }
+ }
+
private void updateCurrentPreference() {
String currentKey = getKeyForCurrent();
Preference preference = findPreference(currentKey);
@@ -441,39 +482,12 @@
final int credentialOwner = UserManager.get(getContext())
.getCredentialOwnerProfile(mUserId);
if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) {
- return KEY_UNLOCK_SET_OFF;
+ return ScreenLockType.NONE.preferenceKey;
}
- switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner)) {
- case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
- return KEY_UNLOCK_SET_PATTERN;
- case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
- case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
- return KEY_UNLOCK_SET_PIN;
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
- case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
- return KEY_UNLOCK_SET_PASSWORD;
- case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
- return KEY_UNLOCK_SET_MANAGED;
- case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
- return KEY_UNLOCK_SET_NONE;
- }
- return null;
- }
-
- /** increases the quality if necessary */
- private int upgradeQuality(int quality) {
- quality = upgradeQualityForDPM(quality);
- return quality;
- }
-
- private int upgradeQualityForDPM(int quality) {
- // Compare min allowed password quality
- int minQuality = mDPM.getPasswordQuality(null, mUserId);
- if (quality < minQuality) {
- quality = minQuality;
- }
- return quality;
+ ScreenLockType lock =
+ ScreenLockType.fromQuality(
+ mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner));
+ return lock != null ? lock.preferenceKey : null;
}
/***
@@ -501,54 +515,17 @@
int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId);
EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
getActivity(), mUserId);
- for (int i = entries.getPreferenceCount() - 1; i >= 0; --i) {
- Preference pref = entries.getPreference(i);
+
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ String key = lock.preferenceKey;
+ Preference pref = findPreference(key);
if (pref instanceof RestrictedPreference) {
- final String key = pref.getKey();
- boolean enabled = true;
- boolean visible = true;
- boolean disabledByAdmin = false;
- if (KEY_UNLOCK_SET_OFF.equals(key)) {
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- if (getResources().getBoolean(R.bool.config_hide_none_security_option)) {
- enabled = false;
- visible = false;
- }
- disabledByAdmin = adminEnforcedQuality
- > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- } else if (KEY_UNLOCK_SET_NONE.equals(key)) {
- if (getResources().getBoolean(R.bool.config_hide_swipe_security_option)) {
- enabled = false;
- visible = false;
- } else {
- if (mUserId != UserHandle.myUserId()) {
- // Swipe doesn't make sense for profiles.
- visible = false;
- }
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- }
- disabledByAdmin = adminEnforcedQuality
- > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
- disabledByAdmin = adminEnforcedQuality
- > DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
- } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
- disabledByAdmin = adminEnforcedQuality
- > DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
- } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
- disabledByAdmin = adminEnforcedQuality
- > DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
- } else if (KEY_UNLOCK_SET_MANAGED.equals(key)) {
- enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_MANAGED
- && mManagedPasswordProvider.isManagedPasswordChoosable();
- disabledByAdmin = adminEnforcedQuality
- > DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
- }
+ boolean visible = mController.isScreenLockVisible(lock);
+ boolean enabled = mController.isScreenLockEnabled(lock, quality);
+ boolean disabledByAdmin =
+ mController.isScreenLockDisabledByAdmin(lock, adminEnforcedQuality);
if (hideDisabled) {
- visible = enabled;
+ visible = visible && enabled;
}
if (!visible) {
entries.removePreference(pref);
@@ -583,21 +560,10 @@
return;
}
- CharSequence summary = getString(R.string.secure_lock_encryption_warning);
-
- PreferenceScreen screen = getPreferenceScreen();
- final int preferenceCount = screen.getPreferenceCount();
- for (int i = 0; i < preferenceCount; i++) {
- Preference preference = screen.getPreference(i);
- switch (preference.getKey()) {
- case KEY_UNLOCK_SET_PATTERN:
- case KEY_UNLOCK_SET_PIN:
- case KEY_UNLOCK_SET_PASSWORD:
- case KEY_UNLOCK_SET_MANAGED: {
- preference.setSummary(summary);
- } break;
- }
- }
+ setPreferenceSummary(ScreenLockType.PATTERN, R.string.secure_lock_encryption_warning);
+ setPreferenceSummary(ScreenLockType.PIN, R.string.secure_lock_encryption_warning);
+ setPreferenceSummary(ScreenLockType.PASSWORD, R.string.secure_lock_encryption_warning);
+ setPreferenceSummary(ScreenLockType.MANAGED, R.string.secure_lock_encryption_warning);
}
protected Intent getLockManagedPasswordIntent(String password) {
@@ -643,17 +609,24 @@
*
* @param quality the desired quality. Ignored if DevicePolicyManager requires more security
* @param disabled whether or not to show LockScreen at all. Only meaningful when quality is
+ * @param chooseLockSkipped whether or not this activity is skipped. This is true when this
+ * activity was not shown to the user at all, instead automatically proceeding based on
+ * the given intent extras, typically {@link LockPatternUtils#PASSWORD_TYPE_KEY}.
* {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}
*/
- void updateUnlockMethodAndFinish(int quality, boolean disabled) {
+ void updateUnlockMethodAndFinish(int quality, boolean disabled, boolean chooseLockSkipped) {
// Sanity check. We should never get here without confirming user's existing password.
if (!mPasswordConfirmed) {
throw new IllegalStateException("Tried to update password without confirming it");
}
- quality = upgradeQuality(quality);
+ quality = mController.upgradeQuality(quality);
Intent intent = getIntentForUnlockMethod(quality);
if (intent != null) {
+ if (getIntent().getBooleanExtra(EXTRA_SHOW_OPTIONS_BUTTON, false)) {
+ intent.putExtra(EXTRA_SHOW_OPTIONS_BUTTON, chooseLockSkipped);
+ }
+ intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras());
startActivityForResult(intent,
mIsSetNewPassword && mHasChallenge
? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
@@ -832,35 +805,33 @@
}
private boolean isUnlockMethodSecure(String unlockMethod) {
- return !(KEY_UNLOCK_SET_OFF.equals(unlockMethod) ||
- KEY_UNLOCK_SET_NONE.equals(unlockMethod));
+ return !(ScreenLockType.SWIPE.preferenceKey.equals(unlockMethod) ||
+ ScreenLockType.NONE.preferenceKey.equals(unlockMethod));
}
private boolean setUnlockMethod(String unlockMethod) {
EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod);
- if (KEY_UNLOCK_SET_OFF.equals(unlockMethod)) {
- updateUnlockMethodAndFinish(
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, true /* disabled */ );
- } else if (KEY_UNLOCK_SET_NONE.equals(unlockMethod)) {
- updateUnlockMethodAndFinish(
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, false /* disabled */ );
- } else if (KEY_UNLOCK_SET_MANAGED.equals(unlockMethod)) {
- maybeEnableEncryption(DevicePolicyManager.PASSWORD_QUALITY_MANAGED, false);
- } else if (KEY_UNLOCK_SET_PATTERN.equals(unlockMethod)) {
- maybeEnableEncryption(
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false);
- } else if (KEY_UNLOCK_SET_PIN.equals(unlockMethod)) {
- maybeEnableEncryption(
- DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, false);
- } else if (KEY_UNLOCK_SET_PASSWORD.equals(unlockMethod)) {
- maybeEnableEncryption(
- DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, false);
- } else {
- Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
- return false;
+ ScreenLockType lock = ScreenLockType.fromKey(unlockMethod);
+ if (lock != null) {
+ switch (lock) {
+ case NONE:
+ case SWIPE:
+ updateUnlockMethodAndFinish(
+ lock.defaultQuality,
+ lock == ScreenLockType.NONE,
+ false /* chooseLockSkipped */);
+ return true;
+ case PATTERN:
+ case PIN:
+ case PASSWORD:
+ case MANAGED:
+ maybeEnableEncryption(lock.defaultQuality, false);
+ return true;
+ }
}
- return true;
+ Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
+ return false;
}
private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) {
@@ -906,23 +877,12 @@
.setTitle(args.getInt(ARG_TITLE_RES))
.setMessage(args.getInt(ARG_MESSAGE_RES))
.setPositiveButton(R.string.unlock_disable_frp_warning_ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- ((ChooseLockGenericFragment) getParentFragment())
- .setUnlockMethod(
- args.getString(ARG_UNLOCK_METHOD_TO_SET));
- }
- }
- )
- .setNegativeButton(R.string.cancel,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- dismiss();
- }
- }
- )
+ (dialog, whichButton) -> {
+ String unlockMethod = args.getString(ARG_UNLOCK_METHOD_TO_SET);
+ ((ChooseLockGenericFragment) getParentFragment())
+ .setUnlockMethod(unlockMethod);
+ })
+ .setNegativeButton(R.string.cancel, (dialog, whichButton) -> dismiss())
.create();
}
diff --git a/src/com/android/settings/password/ChooseLockGenericController.java b/src/com/android/settings/password/ChooseLockGenericController.java
new file mode 100644
index 0000000..a6a1701
--- /dev/null
+++ b/src/com/android/settings/password/ChooseLockGenericController.java
@@ -0,0 +1,158 @@
+/*
+ * 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.password;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.UserHandle;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
+
+import com.android.settings.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A controller for ChooseLockGeneric, and other similar classes which shows a list of possible
+ * screen locks for the user to choose from.
+ */
+public class ChooseLockGenericController {
+
+ private final Context mContext;
+ private final int mUserId;
+ private ManagedLockPasswordProvider mManagedPasswordProvider;
+ private DevicePolicyManager mDpm;
+
+ public ChooseLockGenericController(Context context, int userId) {
+ this(
+ context,
+ userId,
+ context.getSystemService(DevicePolicyManager.class),
+ ManagedLockPasswordProvider.get(context, userId));
+ }
+
+ @VisibleForTesting
+ ChooseLockGenericController(
+ Context context,
+ int userId,
+ DevicePolicyManager dpm,
+ ManagedLockPasswordProvider managedLockPasswordProvider) {
+ mContext = context;
+ mUserId = userId;
+ mManagedPasswordProvider = managedLockPasswordProvider;
+ mDpm = dpm;
+ }
+
+ /**
+ * @return The higher quality of either the specified {@code quality} or the quality required
+ * by {@link DevicePolicyManager#getPasswordQuality}.
+ */
+ public int upgradeQuality(int quality) {
+ // Compare min allowed password quality
+ return Math.max(quality, mDpm.getPasswordQuality(null, mUserId));
+ }
+
+ /**
+ * Whether the given screen lock type should be visible in the given context.
+ */
+ public boolean isScreenLockVisible(ScreenLockType type) {
+ switch (type) {
+ case NONE:
+ return !mContext.getResources().getBoolean(R.bool.config_hide_none_security_option);
+ case SWIPE:
+ return !mContext.getResources().getBoolean(R.bool.config_hide_swipe_security_option)
+ // Swipe doesn't make sense for profiles.
+ && mUserId == UserHandle.myUserId();
+ case MANAGED:
+ return mManagedPasswordProvider.isManagedPasswordChoosable();
+ }
+ return true;
+ }
+
+ /**
+ * Whether screen lock with {@code type} should be enabled.
+ *
+ * @param type The screen lock type.
+ * @param quality The minimum required quality. This can either be requirement by device policy
+ * manager or because some flow only makes sense with secure lock screens.
+ */
+ public boolean isScreenLockEnabled(ScreenLockType type, int quality) {
+ return type.maxQuality >= quality;
+ }
+
+ /**
+ * Whether screen lock with {@code type} is disabled by device policy admin.
+ *
+ * @param type The screen lock type.
+ * @param adminEnforcedQuality The minimum quality that the admin enforces.
+ */
+ public boolean isScreenLockDisabledByAdmin(ScreenLockType type, int adminEnforcedQuality) {
+ boolean disabledByAdmin = type.maxQuality < adminEnforcedQuality;
+ if (type == ScreenLockType.MANAGED) {
+ disabledByAdmin = disabledByAdmin
+ || !mManagedPasswordProvider.isManagedPasswordChoosable();
+ }
+ return disabledByAdmin;
+ }
+
+ /**
+ * User friendly title for the given screen lock type.
+ */
+ public CharSequence getTitle(ScreenLockType type) {
+ switch (type) {
+ case NONE:
+ return mContext.getText(R.string.unlock_set_unlock_off_title);
+ case SWIPE:
+ return mContext.getText(R.string.unlock_set_unlock_none_title);
+ case PATTERN:
+ return mContext.getText(R.string.unlock_set_unlock_pattern_title);
+ case PIN:
+ return mContext.getText(R.string.unlock_set_unlock_pin_title);
+ case PASSWORD:
+ return mContext.getText(R.string.unlock_set_unlock_password_title);
+ case MANAGED:
+ return mManagedPasswordProvider.getPickerOptionTitle(false);
+ }
+ return null;
+ }
+
+ /**
+ * Gets a list of screen locks that should be visible for the given quality. The returned list
+ * is ordered in the natural order of the enum (the order those enums were defined).
+ *
+ * @param quality The minimum quality required in the context of the current flow. This should
+ * be one of the constants defined in
+ * {@code DevicePolicyManager#PASSWORD_QUALITY_*}.
+ * @param includeDisabled Whether to include screen locks disabled by {@code quality}
+ * requirements in the returned list.
+ */
+ @NonNull
+ public List<ScreenLockType> getVisibleScreenLockTypes(int quality, boolean includeDisabled) {
+ int upgradedQuality = upgradeQuality(quality);
+ List<ScreenLockType> locks = new ArrayList<>();
+ // EnumSet's iterator guarantees the natural order of the enums
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ if (isScreenLockVisible(lock)) {
+ if (includeDisabled || isScreenLockEnabled(lock, upgradedQuality)) {
+ locks.add(lock);
+ }
+ }
+ }
+ return locks;
+ }
+}
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index f9aabd6..df0621e 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -28,6 +28,7 @@
import android.app.admin.PasswordMetrics;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Insets;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -171,7 +172,7 @@
private int mPasswordMinNumeric = 0;
private int mPasswordMinNonLetter = 0;
private int mPasswordMinLengthToFulfillAllPolicies = 0;
- private int mUserId;
+ protected int mUserId;
private boolean mHideDrawer = false;
/**
* Password requirements that we need to verify.
@@ -188,7 +189,7 @@
private TextView mHeaderText;
private String mFirstPin;
private RecyclerView mPasswordRestrictionView;
- private boolean mIsAlphaMode;
+ protected boolean mIsAlphaMode;
private Button mCancelButton;
private Button mNextButton;
@@ -291,6 +292,11 @@
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
+ // Make the password container consume the optical insets so the edit text is aligned
+ // with the sides of the parent visually.
+ ViewGroup container = view.findViewById(R.id.password_container);
+ container.setOpticalInsets(Insets.NONE);
+
mCancelButton = (Button) view.findViewById(R.id.cancel_button);
mCancelButton.setOnClickListener(this);
mNextButton = (Button) view.findViewById(R.id.next_button);
diff --git a/src/com/android/settings/password/ChooseLockTypeDialogFragment.java b/src/com/android/settings/password/ChooseLockTypeDialogFragment.java
new file mode 100644
index 0000000..2581483
--- /dev/null
+++ b/src/com/android/settings/password/ChooseLockTypeDialogFragment.java
@@ -0,0 +1,132 @@
+/*
+ * 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.password;
+
+import android.app.AlertDialog.Builder;
+import android.app.Dialog;
+import android.app.Fragment;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+import java.util.List;
+
+/**
+ * A dialog fragment similar to {@link ChooseLockGeneric} where the user can select from a few
+ * lock screen types.
+ */
+public class ChooseLockTypeDialogFragment extends InstrumentedDialogFragment
+ implements OnClickListener {
+
+ private static final String ARG_USER_ID = "userId";
+ private static final String ARG_EXCLUDE_LOCK = "excludeLock";
+
+ private ScreenLockAdapter mAdapter;
+ private ChooseLockGenericController mController;
+
+ public static ChooseLockTypeDialogFragment newInstance(int userId, String excludeLock) {
+ Bundle args = new Bundle();
+ args.putInt(ARG_USER_ID, userId);
+ args.putString(ARG_EXCLUDE_LOCK, excludeLock);
+ ChooseLockTypeDialogFragment fragment = new ChooseLockTypeDialogFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ public interface OnLockTypeSelectedListener {
+ void onLockTypeSelected(ScreenLockType lock);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final int userId = getArguments().getInt(ARG_USER_ID);
+ mController = new ChooseLockGenericController(getContext(), userId);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ OnLockTypeSelectedListener listener = null;
+ Fragment parentFragment = getParentFragment();
+ if (parentFragment instanceof OnLockTypeSelectedListener) {
+ listener = (OnLockTypeSelectedListener) parentFragment;
+ } else {
+ Context context = getContext();
+ if (context instanceof OnLockTypeSelectedListener) {
+ listener = (OnLockTypeSelectedListener) context;
+ }
+ }
+ if (listener != null) {
+ listener.onLockTypeSelected(mAdapter.getItem(i));
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Context context = getContext();
+ Builder builder = new Builder(context);
+ List<ScreenLockType> locks =
+ mController.getVisibleScreenLockTypes(
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
+ false /* includeDisabled */);
+ String excludeLockName = getArguments().getString(ARG_EXCLUDE_LOCK);
+ if (excludeLockName != null) {
+ locks.remove(ScreenLockType.valueOf(excludeLockName));
+ }
+ mAdapter = new ScreenLockAdapter(context, locks, mController);
+ builder.setAdapter(mAdapter, this);
+ return builder.create();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.SETTINGS_CHOOSE_LOCK_DIALOG;
+ }
+
+ private static class ScreenLockAdapter extends ArrayAdapter<ScreenLockType> {
+
+ private final ChooseLockGenericController mController;
+
+ ScreenLockAdapter(
+ Context context,
+ List<ScreenLockType> locks,
+ ChooseLockGenericController controller) {
+ super(context, android.R.layout.simple_list_item_1, locks);
+ mController = controller;
+ }
+
+ @Override
+ public View getView(int position, View view, ViewGroup parent) {
+ if (view == null) {
+ view = LayoutInflater.from(parent.getContext())
+ .inflate(android.R.layout.simple_list_item_1, parent, false);
+ }
+ ((TextView) view).setText(mController.getTitle(getItem(position)));
+ return view;
+ }
+ }
+}
diff --git a/src/com/android/settings/password/ManagedLockPasswordProvider.java b/src/com/android/settings/password/ManagedLockPasswordProvider.java
index 65bf1f6..09fe104 100644
--- a/src/com/android/settings/password/ManagedLockPasswordProvider.java
+++ b/src/com/android/settings/password/ManagedLockPasswordProvider.java
@@ -52,7 +52,7 @@
* Should be overridden if {@link #isManagedPasswordSupported()} returns true.
* @param forFingerprint Whether fingerprint unlock is enabled.
*/
- String getPickerOptionTitle(boolean forFingerprint) { return ""; }
+ CharSequence getPickerOptionTitle(boolean forFingerprint) { return ""; }
/**
* Gets resource id of the lock screen preference that should be displayed in security settings
diff --git a/src/com/android/settings/password/ScreenLockType.java b/src/com/android/settings/password/ScreenLockType.java
new file mode 100644
index 0000000..608c8f6
--- /dev/null
+++ b/src/com/android/settings/password/ScreenLockType.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.password;
+
+import android.app.admin.DevicePolicyManager;
+
+/**
+ * List of screen lock type options that are available in ChooseLockGeneric. Provides the key and
+ * the associated quality, and also some helper functions to translate between them.
+ */
+public enum ScreenLockType {
+
+ NONE(
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
+ "unlock_set_off"),
+ SWIPE(
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
+ "unlock_set_none"),
+ PATTERN(
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
+ "unlock_set_pattern"),
+ PIN(
+ DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
+ DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX,
+ "unlock_set_pin"),
+ PASSWORD(
+ DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
+ DevicePolicyManager.PASSWORD_QUALITY_COMPLEX,
+ "unlock_set_password"),
+ MANAGED(
+ DevicePolicyManager.PASSWORD_QUALITY_MANAGED,
+ "unlock_set_managed");
+
+ private static final ScreenLockType MIN_QUALITY = ScreenLockType.NONE;
+ private static final ScreenLockType MAX_QUALITY = ScreenLockType.MANAGED;
+
+ /**
+ * The default quality of the type of lock used. For example, in the case of PIN, the default
+ * quality if PASSWORD_QUALITY_NUMERIC, while the highest quality is
+ * PASSWORD_QUALITY_NUMERIC_COMPLEX.
+ */
+ public final int defaultQuality;
+
+ /**
+ * The highest quality for the given type of lock. For example, in the case of password, the
+ * default quality is PASSWORD_QUALITY_ALPHABETIC, but the highest possible quality is
+ * PASSWORD_QUALITY_COMPLEX.
+ */
+ public final int maxQuality;
+
+ public final String preferenceKey;
+
+ ScreenLockType(int quality, String preferenceKey) {
+ this(quality, quality, preferenceKey);
+ }
+
+ ScreenLockType(int defaultQuality, int maxQuality, String preferenceKey) {
+ this.defaultQuality = defaultQuality;
+ this.maxQuality = maxQuality;
+ this.preferenceKey = preferenceKey;
+ }
+
+ /**
+ * Gets the screen lock type for the given quality. Note that this method assumes that a screen
+ * lock is enabled, which means if the quality is
+ * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, the returned type will be
+ * {@link #SWIPE} and not {@link #NONE}.
+ */
+ public static ScreenLockType fromQuality(int quality) {
+ switch (quality) {
+ case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+ return ScreenLockType.PATTERN;
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+ return ScreenLockType.PIN;
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+ return ScreenLockType.PASSWORD;
+ case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
+ return ScreenLockType.MANAGED;
+ case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
+ return ScreenLockType.SWIPE;
+ }
+ return null;
+ }
+
+ public static ScreenLockType fromKey(String key) {
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ if (lock.preferenceKey.equals(key)) {
+ return lock;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java
index 74aac2c..4e73b87 100644
--- a/src/com/android/settings/password/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/password/SetupChooseLockGeneric.java
@@ -111,20 +111,16 @@
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode != RESULT_CANCELED) {
- if (data == null) {
- data = new Intent();
- }
- // Add the password quality extra to the intent data that will be sent back for
- // Setup Wizard.
- LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
- data.putExtra(EXTRA_PASSWORD_QUALITY,
- lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId()));
-
- super.onActivityResult(requestCode, resultCode, data);
+ if (data == null) {
+ data = new Intent();
}
- // If the started activity was cancelled (e.g. the user presses back), then this
- // activity will be resumed to foreground.
+ // Add the password quality extra to the intent data that will be sent back for
+ // Setup Wizard.
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
+ data.putExtra(EXTRA_PASSWORD_QUALITY,
+ lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId()));
+
+ super.onActivityResult(requestCode, resultCode, data);
}
@Override
diff --git a/src/com/android/settings/password/SetupChooseLockPassword.java b/src/com/android/settings/password/SetupChooseLockPassword.java
index b8a741d..0c62c7c 100644
--- a/src/com/android/settings/password/SetupChooseLockPassword.java
+++ b/src/com/android/settings/password/SetupChooseLockPassword.java
@@ -16,16 +16,24 @@
package com.android.settings.password;
+import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
import android.widget.LinearLayout;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SetupRedactionInterstitial;
import com.android.settings.SetupWizardUtils;
+import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
+import com.android.settings.password.ChooseLockTypeDialogFragment.OnLockTypeSelectedListener;
+import com.android.setupwizardlib.util.WizardManagerHelper;
/**
* Setup Wizard's version of ChooseLockPassword screen. It inherits the logic and basic structure
@@ -67,7 +75,41 @@
super.onApplyThemeResource(theme, resid, first);
}
- public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment {
+ public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment
+ implements OnLockTypeSelectedListener {
+
+ @VisibleForTesting
+ static final int REQUEST_SCREEN_LOCK_OPTIONS = 1;
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ boolean showOptionsButton = getActivity().getIntent().getBooleanExtra(
+ ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
+ if (showOptionsButton) {
+ Button optionsButton = view.findViewById(R.id.screen_lock_options);
+ optionsButton.setVisibility(View.VISIBLE);
+ optionsButton.setOnClickListener(this);
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.screen_lock_options:
+ launchChooseLockGeneric();
+ break;
+ default:
+ super.onClick(v);
+ }
+ }
+
+ private void launchChooseLockGeneric() {
+ ScreenLockType currentLock = mIsAlphaMode
+ ? ScreenLockType.PASSWORD : ScreenLockType.PIN;
+ ChooseLockTypeDialogFragment.newInstance(mUserId, currentLock.toString())
+ .show(getChildFragmentManager(), null);
+ }
@Override
protected Intent getRedactionInterstitialIntent(Context context) {
@@ -76,5 +118,46 @@
SetupRedactionInterstitial.setEnabled(context, true);
return null;
}
+
+ @Override
+ public void onLockTypeSelected(ScreenLockType lock) {
+ Intent activityIntent = getActivity().getIntent();
+ Intent intent = new Intent(getContext(), SetupChooseLockGeneric.class);
+
+ // Copy the original extras into the new intent
+ if (activityIntent
+ .hasExtra(ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS)) {
+ intent.putExtras(activityIntent.getBundleExtra(
+ ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS));
+ }
+ intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, lock.defaultQuality);
+
+ // Propagate the fingerprint challenge
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE,
+ activityIntent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE,
+ false));
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE,
+ activityIntent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0));
+
+ // The user is already given the choice of the what screen lock to set up. No need to
+ // show this button again.
+ intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
+
+ WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
+
+ startActivityForResult(intent, REQUEST_SCREEN_LOCK_OPTIONS);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == REQUEST_SCREEN_LOCK_OPTIONS) {
+ if (resultCode != Activity.RESULT_CANCELED) {
+ Activity activity = getActivity();
+ activity.setResult(resultCode, data);
+ activity.finish();
+ }
+ }
+ }
}
}
diff --git a/src/com/android/settings/applications/AppHeaderController.java b/src/com/android/settings/widget/EntityHeaderController.java
similarity index 64%
rename from src/com/android/settings/applications/AppHeaderController.java
rename to src/com/android/settings/widget/EntityHeaderController.java
index 804d645..d7ba35a 100644
--- a/src/com/android/settings/applications/AppHeaderController.java
+++ b/src/com/android/settings/widget/EntityHeaderController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settings.applications;
+package com.android.settings.widget;
import android.annotation.IdRes;
import android.annotation.UserIdInt;
@@ -41,13 +41,16 @@
import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settings.applications.InstalledAppDetails;
+import com.android.settings.applications.LayoutPreference;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.applications.ApplicationsState;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-public class AppHeaderController {
+public class EntityHeaderController {
@IntDef({ActionType.ACTION_NONE,
ActionType.ACTION_APP_INFO,
@@ -68,7 +71,7 @@
private final Context mContext;
private final Fragment mFragment;
private final int mMetricsCategory;
- private final View mAppHeader;
+ private final View mHeader;
private Drawable mIcon;
private CharSequence mLabel;
@@ -78,90 +81,101 @@
@UserIdInt
private int mUid = UserHandle.USER_NULL;
@ActionType
- private int mLeftAction;
+ private int mAction1;
@ActionType
- private int mRightAction;
+ private int mAction2;
private boolean mIsInstantApp;
- public AppHeaderController(Context context, Fragment fragment, View appHeader) {
+ /**
+ * Creates a new instance of the controller.
+ *
+ * @param fragment The fragment that header will be placed in.
+ * @param header Optional: header view if it's already created.
+ */
+ public static EntityHeaderController newInstance(Context context, Fragment fragment,
+ View header) {
+ return new EntityHeaderController(context.getApplicationContext(), fragment, header);
+ }
+
+ private EntityHeaderController(Context context, Fragment fragment, View header) {
mContext = context;
mFragment = fragment;
mMetricsCategory = FeatureFactory.getFactory(context).getMetricsFeatureProvider()
.getMetricsCategory(fragment);
- if (appHeader != null) {
- mAppHeader = appHeader;
+ if (header != null) {
+ mHeader = header;
} else {
- mAppHeader = LayoutInflater.from(fragment.getContext())
- .inflate(R.layout.app_details, null /* root */);
+ mHeader = LayoutInflater.from(fragment.getContext())
+ .inflate(R.layout.settings_entity_header, null /* root */);
}
}
- public AppHeaderController setIcon(Drawable icon) {
+ public EntityHeaderController setIcon(Drawable icon) {
if (icon != null) {
mIcon = icon.getConstantState().newDrawable(mContext.getResources());
}
return this;
}
- public AppHeaderController setIcon(ApplicationsState.AppEntry appEntry) {
+ public EntityHeaderController setIcon(ApplicationsState.AppEntry appEntry) {
if (appEntry.icon != null) {
mIcon = appEntry.icon.getConstantState().newDrawable(mContext.getResources());
}
return this;
}
- public AppHeaderController setLabel(CharSequence label) {
+ public EntityHeaderController setLabel(CharSequence label) {
mLabel = label;
return this;
}
- public AppHeaderController setLabel(ApplicationsState.AppEntry appEntry) {
+ public EntityHeaderController setLabel(ApplicationsState.AppEntry appEntry) {
mLabel = appEntry.label;
return this;
}
- public AppHeaderController setSummary(CharSequence summary) {
+ public EntityHeaderController setSummary(CharSequence summary) {
mSummary = summary;
return this;
}
- public AppHeaderController setSummary(PackageInfo packageInfo) {
+ public EntityHeaderController setSummary(PackageInfo packageInfo) {
if (packageInfo != null) {
mSummary = packageInfo.versionName;
}
return this;
}
- public AppHeaderController setButtonActions(@ActionType int leftAction,
- @ActionType int rightAction) {
- mLeftAction = leftAction;
- mRightAction = rightAction;
+ public EntityHeaderController setButtonActions(@ActionType int action1,
+ @ActionType int action2) {
+ mAction1 = action1;
+ mAction2 = action2;
return this;
}
- public AppHeaderController setPackageName(String packageName) {
+ public EntityHeaderController setPackageName(String packageName) {
mPackageName = packageName;
return this;
}
- public AppHeaderController setUid(int uid) {
+ public EntityHeaderController setUid(int uid) {
mUid = uid;
return this;
}
- public AppHeaderController setAppNotifPrefIntent(Intent appNotifPrefIntent) {
+ public EntityHeaderController setAppNotifPrefIntent(Intent appNotifPrefIntent) {
mAppNotifPrefIntent = appNotifPrefIntent;
return this;
}
- public AppHeaderController setIsInstantApp(boolean isInstantApp) {
+ public EntityHeaderController setIsInstantApp(boolean isInstantApp) {
this.mIsInstantApp = isInstantApp;
return this;
}
/**
- * Done mutating appheader, rebinds everything and return a new {@link LayoutPreference}.
+ * Done mutating entity header, rebinds everything and return a new {@link LayoutPreference}.
*/
public LayoutPreference done(Activity activity, Context uiContext) {
final LayoutPreference pref = new LayoutPreference(uiContext, done(activity));
@@ -172,41 +186,41 @@
}
/**
- * Done mutating appheader, rebinds everything (optionally skip rebinding buttons).
+ * Done mutating entity header, rebinds everything (optionally skip rebinding buttons).
*/
public View done(Activity activity, boolean rebindActions) {
styleActionBar(activity);
- ImageView iconView = mAppHeader.findViewById(R.id.app_detail_icon);
+ ImageView iconView = mHeader.findViewById(R.id.entity_header_icon);
if (iconView != null) {
iconView.setImageDrawable(mIcon);
}
- setText(R.id.app_detail_title, mLabel);
- setText(R.id.app_detail_summary, mSummary);
+ setText(R.id.entity_header_title, mLabel);
+ setText(R.id.entity_header_summary, mSummary);
if (mIsInstantApp) {
setText(R.id.install_type,
- mAppHeader.getResources().getString(R.string.install_type_instant));
+ mHeader.getResources().getString(R.string.install_type_instant));
}
if (rebindActions) {
- bindAppHeaderButtons();
+ bindHeaderButtons();
}
- return mAppHeader;
+ return mHeader;
}
/**
- * Only binds app header with button actions.
+ * Only binds entity header with button actions.
*/
- public AppHeaderController bindAppHeaderButtons() {
- ImageButton leftButton = mAppHeader.findViewById(R.id.left_button);
- ImageButton rightButton = mAppHeader.findViewById(R.id.right_button);
+ public EntityHeaderController bindHeaderButtons() {
+ ImageButton button1 = mHeader.findViewById(android.R.id.button1);
+ ImageButton button2 = mHeader.findViewById(android.R.id.button2);
- bindButton(leftButton, mLeftAction);
- bindButton(rightButton, mRightAction);
+ bindButton(button1, mAction1);
+ bindButton(button2, mAction2);
return this;
}
- public AppHeaderController styleActionBar(Activity activity) {
+ public EntityHeaderController styleActionBar(Activity activity) {
if (activity == null) {
Log.w(TAG, "No activity, cannot style actionbar.");
return this;
@@ -224,7 +238,7 @@
}
/**
- * Done mutating appheader, rebinds everything.
+ * Done mutating entity header, rebinds everything.
*/
@VisibleForTesting
View done(Activity activity) {
@@ -245,9 +259,16 @@
button.setContentDescription(
mContext.getString(R.string.application_info_label));
button.setImageResource(com.android.settings.R.drawable.ic_info);
- button.setOnClickListener(v -> AppInfoBase.startAppInfoFragment(
- InstalledAppDetails.class, R.string.application_info_label,
- mPackageName, mUid, mFragment, 0 /* request */, mMetricsCategory));
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AppInfoBase.startAppInfoFragment(
+ InstalledAppDetails.class, R.string.application_info_label,
+ mPackageName, mUid, mFragment, 0 /* request */,
+ mMetricsCategory);
+
+ }
+ });
button.setVisibility(View.VISIBLE);
}
return;
@@ -256,7 +277,12 @@
if (mAppNotifPrefIntent == null) {
button.setVisibility(View.GONE);
} else {
- button.setOnClickListener(v -> mFragment.startActivity(mAppNotifPrefIntent));
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mFragment.startActivity(mAppNotifPrefIntent);
+ }
+ });
button.setVisibility(View.VISIBLE);
}
return;
@@ -268,7 +294,12 @@
button.setVisibility(View.GONE);
return;
}
- button.setOnClickListener(v -> mFragment.startActivity(intent));
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mFragment.startActivity(intent);
+ }
+ });
button.setVisibility(View.VISIBLE);
return;
}
@@ -289,7 +320,7 @@
}
private void setText(@IdRes int id, CharSequence text) {
- TextView textView = mAppHeader.findViewById(id);
+ TextView textView = mHeader.findViewById(id);
if (textView != null) {
textView.setText(text);
textView.setVisibility(TextUtils.isEmpty(text) ? View.GONE : View.VISIBLE);
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 2f1139b..39d90e1 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -225,7 +225,7 @@
mButtonsPref = (LayoutPreference) screen.findPreference(KEY_BUTTONS_PREF);
mSignInButton = (Button) mButtonsPref.findViewById(R.id.right_button);
- mSignInButton.setText(com.android.internal.R.string.network_available_sign_in);
+ mSignInButton.setText(R.string.support_sign_in_button_text);
mSignInButton.setOnClickListener(
view -> mConnectivityManagerWrapper.startCaptivePortalApp(mNetwork));
diff --git a/tests/robotests/assets/whitelist_duplicate_index_key b/tests/robotests/assets/whitelist_duplicate_index_key
index 4446403..0b8d675 100644
--- a/tests/robotests/assets/whitelist_duplicate_index_key
+++ b/tests/robotests/assets/whitelist_duplicate_index_key
@@ -1,12 +1,6 @@
-dashboard_tile_placeholder
-gesture_pick_up
add_users_when_locked
additional_system_update_settings
-gesture_assist
screen_zoom
-gesture_swipe_down_fingerprint
-gesture_double_twist
+dashboard_tile_placeholder
lock_screen_notifications
-gesture_double_tap_power
-gesture_double_tap_screen
usage_access
\ No newline at end of file
diff --git a/tests/robotests/src/android/app/admin/PasswordMetrics.java b/tests/robotests/src/android/app/admin/PasswordMetrics.java
new file mode 100644
index 0000000..a461306
--- /dev/null
+++ b/tests/robotests/src/android/app/admin/PasswordMetrics.java
@@ -0,0 +1,49 @@
+/*
+ * 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 android.app.admin;
+
+import android.annotation.NonNull;
+
+/**
+ * Stub implementation of framework's PasswordMetrics for Robolectric tests. Otherwise Robolectric
+ * is throwing ClassNotFoundError.
+ *
+ * TODO: Remove this class when Robolectric supports O
+ */
+public class PasswordMetrics {
+
+ // Maximum allowed number of repeated or ordered characters in a sequence before we'll
+ // consider it a complex PIN/password.
+ public static final int MAX_ALLOWED_SEQUENCE = 3;
+
+ public int length = 0;
+ public int letters = 0;
+ public int upperCase = 0;
+ public int lowerCase = 0;
+ public int numeric = 0;
+ public int symbols = 0;
+ public int nonLetter = 0;
+
+ public static int maxLengthSequence(@NonNull String string) {
+ // Stub implementation
+ return 1;
+ }
+
+ public static PasswordMetrics computeForPassword(@NonNull String password) {
+ return new PasswordMetrics();
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/DisplaySettingsTest.java b/tests/robotests/src/com/android/settings/DisplaySettingsTest.java
new file mode 100644
index 0000000..716eacf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/DisplaySettingsTest.java
@@ -0,0 +1,44 @@
+package com.android.settings;
+
+import android.content.Context;
+import android.os.PowerManager;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.testutils.XmlTestUtils;
+import com.android.settings.testutils.shadow.ShadowPowerManagerWrapper;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class DisplaySettingsTest {
+
+ @Test
+ @Config(shadows = ShadowPowerManagerWrapper.class)
+ public void testPreferenceControllers_getPreferenceKeys_existInPreferenceScreen() {
+ final Context context = RuntimeEnvironment.application;
+// PowerManager wrapper = mock(PowerManager.class);
+// doReturn(wrapper).when(context).getSystemService(Context.POWER_SERVICE);
+ final DisplaySettings fragment = new DisplaySettings();
+ final List<String> preferenceScreenKeys = XmlTestUtils.getKeysFromPreferenceXml(context,
+ fragment.getPreferenceScreenResId());
+ final List<String> preferenceKeys = new ArrayList<>();
+
+ for (PreferenceController controller : fragment.getPreferenceControllers(context)) {
+ preferenceKeys.add(controller.getPreferenceKey());
+ }
+ // Nightmode is currently hidden
+ preferenceKeys.remove("night_mode");
+
+ assertThat(preferenceScreenKeys).containsAllIn(preferenceKeys);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
index 90728e8..a215d13 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
@@ -17,7 +17,6 @@
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.accounts.AuthenticatorDescription;
import android.content.Context;
import android.os.Bundle;
import android.os.UserHandle;
@@ -26,8 +25,6 @@
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
-import com.android.settings.testutils.shadow.ShadowAccountManager;
-import com.android.settings.testutils.shadow.ShadowContentResolver;
import com.android.settingslib.drawer.CategoryKey;
import com.android.settingslib.drawer.Tile;
@@ -41,11 +38,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Answers.RETURNS_DEEP_STUBS;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -54,7 +47,6 @@
private static final String METADATA_CATEGORY = "com.android.settings.category";
private static final String METADATA_ACCOUNT_TYPE = "com.android.settings.ia.account";
private static final String METADATA_USER_HANDLE = "user_handle";
- private static final String PREF_ACCOUNT_HEADER = "account_header";
@Mock(answer = RETURNS_DEEP_STUBS)
private AccountManager mAccountManager;
@@ -118,20 +110,4 @@
assertThat(mFragment.displayTile(tile)).isFalse();
}
-
- @Test
- @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
- public void updateAccountHeader_shouldShowAccountName() throws Exception {
- when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(
- new AuthenticatorDescription[0]);
- when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
- when(mFragment.getContext()).thenReturn(mContext);
- doReturn(mScreen).when(mFragment).getPreferenceScreen();
- doReturn(mPreference).when(mFragment).findPreference(PREF_ACCOUNT_HEADER);
-
- mFragment.updateUi();
-
- verify(mPreference).setTitle("name1@abc.com");
- }
-
}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/AccountHeaderPreferenceControllerTest.java
new file mode 100644
index 0000000..0668379
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/AccountHeaderPreferenceControllerTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.accounts;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.support.v7.preference.PreferenceScreen;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.accounts.AuthenticatorHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AccountHeaderPreferenceControllerTest {
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock
+ private Activity mActivity;
+ @Mock
+ private Fragment mFragment;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private LayoutPreference mHeaderPreference;
+
+ private AccountHeaderPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest(mContext);
+ mHeaderPreference = new LayoutPreference(
+ RuntimeEnvironment.application, R.layout.settings_entity_header);
+ }
+
+ @Test
+ public void isAvailable_noArgs_shouldReturnNull() {
+ mController = new AccountHeaderPreferenceController(RuntimeEnvironment.application,
+ mActivity, mFragment, null /* args */);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ @Config(shadows = ShadowAuthenticatorHelper.class)
+ public void displayPreference_shouldDisplayAccountInEntityHeader() {
+ final Account account = new Account("name1@abc.com", "com.abc");
+ Bundle args = new Bundle();
+ args.putParcelable(AccountDetailDashboardFragment.KEY_ACCOUNT, account);
+ args.putParcelable(AccountDetailDashboardFragment.KEY_USER_HANDLE, UserHandle.CURRENT);
+ mController = new AccountHeaderPreferenceController(RuntimeEnvironment.application,
+ mActivity, mFragment, args);
+
+ assertThat(mController.isAvailable()).isTrue();
+
+ when(mScreen.findPreference(anyString())).thenReturn(mHeaderPreference);
+
+ mController.displayPreference(mScreen);
+
+ final CharSequence label =
+ ((TextView) mHeaderPreference.findViewById(R.id.entity_header_title)).getText();
+
+ assertThat(label).isEqualTo(account.name);
+
+ }
+
+ @Implements(AuthenticatorHelper.class)
+ public static class ShadowAuthenticatorHelper {
+ @Implementation
+ public void onAccountsUpdated(Account[] accounts) {
+
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
index 8453da5..f1ad142 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
@@ -26,8 +26,8 @@
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceScreen;
-
import android.text.TextUtils;
+
import com.android.settings.AccessiblePreferenceCategory;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
@@ -92,7 +92,7 @@
when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(
- new AuthenticatorDescription[0]);
+ new AuthenticatorDescription[0]);
when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
mController = new AccountPreferenceController(mContext, mFragment, null, mAccountHelper);
}
@@ -367,6 +367,51 @@
@Test
@Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
+ public void onResume_twoAccountsOfSameName_shouldAddFivePreferences() {
+ final List<UserInfo> infos = new ArrayList<>();
+ infos.add(new UserInfo(1, "user 1", 0));
+ when(mUserManager.isManagedProfile()).thenReturn(false);
+ when(mUserManager.isLinkedUser()).thenReturn(false);
+ when(mUserManager.getProfiles(anyInt())).thenReturn(infos);
+
+ final Account[] accountType1 = new Account[2];
+ accountType1[0] = new Account("Account1", "com.acct1");
+ accountType1[1] = new Account("Account2", "com.acct1");
+ final Account[] accountType2 = new Account[2];
+ accountType2[0] = new Account("Account1", "com.acct2");
+ accountType2[1] = new Account("Account2", "com.acct2");
+ final Account[] allAccounts = new Account[4];
+ allAccounts[0] = accountType1[0];
+ allAccounts[1] = accountType1[1];
+ allAccounts[2] = accountType2[0];
+ allAccounts[3] = accountType2[1];
+ final AuthenticatorDescription[] authDescs = {
+ new AuthenticatorDescription("com.acct1", "com.android.settings",
+ R.string.account_settings_title, 0, 0, 0, false),
+ new AuthenticatorDescription("com.acct2", "com.android.settings",
+ R.string.account_settings_title, 0, 0, 0, false)
+ };
+
+ when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(allAccounts);
+ when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class)))
+ .thenReturn(accountType1);
+ when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct2"), any(UserHandle.class)))
+ .thenReturn(accountType2);
+ when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs);
+
+ AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class);
+ when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
+ when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn(
+ preferenceGroup);
+
+ mController.onResume();
+
+ // should add 4 individual account and the Add account preference
+ verify(preferenceGroup, times(5)).addPreference(any(Preference.class));
+ }
+
+ @Test
+ @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
public void onResume_noAccountChange_shouldNotAddAccountPreference() {
final List<UserInfo> infos = new ArrayList<>();
infos.add(new UserInfo(1, "user 1", 0));
@@ -448,6 +493,42 @@
@Test
@Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
+ public void onResume_oneNewAccountType_shouldAddOneAccountPreference() {
+ final List<UserInfo> infos = new ArrayList<>();
+ infos.add(new UserInfo(1, "user 1", 0));
+ infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE));
+ when(mUserManager.isManagedProfile()).thenReturn(false);
+ when(mUserManager.isLinkedUser()).thenReturn(false);
+ when(mUserManager.getProfiles(anyInt())).thenReturn(infos);
+
+ AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class);
+ when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
+ when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn(
+ preferenceGroup);
+
+ // First time resume will build the UI with no account
+ mController.onResume();
+
+ // Add new account
+ Account[] accounts = {new Account("Acct1", "com.acct1")};
+ when(mAccountManager.getAccountsAsUser(2)).thenReturn(accounts);
+ when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class)))
+ .thenReturn(accounts);
+
+ AuthenticatorDescription[] authDescs = {
+ new AuthenticatorDescription("com.acct1", "com.android.settings",
+ R.string.account_settings_title, 0, 0, 0, false)
+ };
+ when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs);
+
+ // Resume should show the newly added account
+ mController.onResume();
+
+ verify(preferenceGroup).addPreference(argThat(new PreferenceMatcher("Acct1")));
+ }
+
+ @Test
+ @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
public void onResume_oneAccountRemoved_shouldRemoveOneAccountPreference() {
final List<UserInfo> infos = new ArrayList<>();
infos.add(new UserInfo(1, "user 1", 0));
diff --git a/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java b/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
index 68c153c..5a526e7 100644
--- a/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
@@ -28,9 +28,12 @@
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -47,10 +50,13 @@
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+ shadows = ShadowEntityHeaderController.class)
public class AppInfoWithHeaderTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private EntityHeaderController mHeaderController;
private FakeFeatureFactory mFactory;
private TestFragment mAppInfoWithHeader;
@@ -64,16 +70,16 @@
when(mFactory.metricsFeatureProvider.getMetricsCategory(any(Object.class)))
.thenReturn(MetricsProto.MetricsEvent.SETTINGS_APP_NOTIF_CATEGORY);
mAppInfoWithHeader = new TestFragment();
+ ShadowEntityHeaderController.setUseMock(mHeaderController);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowEntityHeaderController.reset();
}
@Test
public void testAppHeaderIsAdded() {
- final AppHeaderController appHeaderController = new AppHeaderController(
- ShadowApplication.getInstance().getApplicationContext(),
- mAppInfoWithHeader,
- null);
- when(mFactory.applicationFeatureProvider.newAppHeaderController(mAppInfoWithHeader, null))
- .thenReturn(appHeaderController);
mAppInfoWithHeader.onActivityCreated(null);
verify(mAppInfoWithHeader.mScreen).addPreference(any(LayoutPreference.class));
@@ -93,7 +99,7 @@
mPackageInfo.applicationInfo = new ApplicationInfo();
mShadowContext = ShadowApplication.getInstance().getApplicationContext();
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
- (InstantAppDataProvider) (info -> false));
+ (InstantAppDataProvider) (info -> false));
when(mManager.getContext()).thenReturn(mShadowContext);
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
index e792845..7421570 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
@@ -17,12 +17,15 @@
import android.content.Context;
import android.content.pm.PackageManager;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcManager;
import android.provider.SearchIndexableResource;
-import com.android.settings.bluetooth.BluetoothMasterSwitchPreferenceController;
-import com.android.settings.nfc.NfcPreferenceController;
+import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
+import com.android.settings.dashboard.SummaryLoader;
+import com.android.settings.nfc.NfcPreferenceController;
import com.android.settings.testutils.XmlTestUtils;
import com.android.settingslib.drawer.CategoryKey;
@@ -36,12 +39,17 @@
import java.util.List;
+import static android.content.Context.NFC_SERVICE;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ConnectedDeviceDashboardFragmentTest {
+
@Mock
Context mContext;
@@ -65,7 +73,8 @@
@Test
public void testSearchIndexProvider_shouldIndexResource() {
final List<SearchIndexableResource> indexRes =
- mFragment.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(mContext, true /* enabled */);
+ mFragment.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(mContext,
+ true /* enabled */);
assertThat(indexRes).isNotNull();
assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
@@ -74,7 +83,8 @@
@Test
public void testSearchIndexProvider_NoNfc_KeyAdded() {
when(mManager.hasSystemFeature(PackageManager.FEATURE_NFC)).thenReturn(false);
- final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
+ final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+ mContext);
assertThat(keys).isNotNull();
assertThat(keys).contains(NfcPreferenceController.KEY_TOGGLE_NFC);
@@ -84,7 +94,8 @@
@Test
public void testSearchIndexProvider_NFC_KeyNotAdded() {
when(mManager.hasSystemFeature(PackageManager.FEATURE_NFC)).thenReturn(true);
- final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
+ final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+ mContext);
assertThat(keys).isNotNull();
assertThat(keys).doesNotContain(NfcPreferenceController.KEY_TOGGLE_NFC);
@@ -103,4 +114,43 @@
assertThat(keys).containsAllIn(niks);
}
+
+ @Test
+ public void testSummaryProvider_hasNfc_shouldReturnNfcSummary() {
+ final NfcManager nfcManager = mock(NfcManager.class);
+ final SummaryLoader summaryLoader = mock(SummaryLoader.class);
+
+ when(mContext.getApplicationContext()).thenReturn(mContext);
+ when(mContext.getSystemService(NFC_SERVICE)).thenReturn(nfcManager);
+ when(nfcManager.getDefaultAdapter()).thenReturn(mock(NfcAdapter.class));
+
+ SummaryLoader.SummaryProvider provider =
+ new ConnectedDeviceDashboardFragment.SummaryProvider(mContext, summaryLoader);
+
+ provider.setListening(false);
+
+ verifyZeroInteractions(summaryLoader);
+
+ provider.setListening(true);
+
+ verify(mContext).getString(R.string.connected_devices_dashboard_summary);
+ }
+
+ @Test
+ public void testSummaryProvider_noNfc_shouldReturnNoNfcSummary() {
+ final SummaryLoader summaryLoader = mock(SummaryLoader.class);
+
+ when(mContext.getApplicationContext()).thenReturn(mContext);
+
+ SummaryLoader.SummaryProvider provider =
+ new ConnectedDeviceDashboardFragment.SummaryProvider(mContext, summaryLoader);
+
+ provider.setListening(false);
+
+ verifyZeroInteractions(summaryLoader);
+
+ provider.setListening(true);
+
+ verify(mContext).getString(R.string.connected_devices_dashboard_no_nfc_summary);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
index 2e49ed2..2d0f031 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
@@ -25,11 +25,13 @@
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
-import com.android.settings.applications.AppHeaderController;
-import com.android.settings.applications.AppHeaderController.ActionType;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+import com.android.settings.widget.EntityHeaderController;
+import com.android.settings.widget.EntityHeaderController.ActionType;
import com.android.settingslib.AppItem;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,28 +47,33 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+ shadows = ShadowEntityHeaderController.class)
public class AppDataUsageTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private AppHeaderController mHeaderController;
- private FakeFeatureFactory mFeatureFactory;
+ private EntityHeaderController mHeaderController;
+
private AppDataUsage mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest(mContext);
- mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowEntityHeaderController.reset();
}
@Test
public void bindAppHeader_allWorkApps_shouldNotShowAppInfoLink() {
+ ShadowEntityHeaderController.setUseMock(mHeaderController);
mFragment = spy(new AppDataUsage());
doReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS))
@@ -74,8 +81,6 @@
.getPreferenceManager();
doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
ReflectionHelpers.setField(mFragment, "mAppItem", mock(AppItem.class));
- when(mFeatureFactory.applicationFeatureProvider.newAppHeaderController(mFragment, null))
- .thenReturn(mHeaderController);
mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
diff --git a/tests/robotests/src/com/android/settings/development/TelephonyMonitorPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/TelephonyMonitorPreferenceControllerTest.java
index 5167c68..9a1a3b6 100644
--- a/tests/robotests/src/com/android/settings/development/TelephonyMonitorPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/TelephonyMonitorPreferenceControllerTest.java
@@ -134,7 +134,24 @@
when(mContext.getResources().getBoolean(R.bool.config_show_telephony_monitor))
.thenReturn(true);
SettingsShadowSystemProperties.set(
- TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR, "true");
+ TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+ TelephonyMonitorPreferenceController.ENABLED_STATUS);
+ SettingsShadowSystemProperties.set(
+ TelephonyMonitorPreferenceController.BUILD_TYPE, "userdebug");
+
+ mController.displayPreference(mScreen);
+
+ verify(mPreference).setChecked(true);
+ }
+
+ @Config(shadows = {SettingsShadowSystemProperties.class})
+ @Test
+ public void displayPreference_telephonyMonitorUserEnabled_shouldCheckedPreference() {
+ when(mContext.getResources().getBoolean(R.bool.config_show_telephony_monitor))
+ .thenReturn(true);
+ SettingsShadowSystemProperties.set(
+ TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+ TelephonyMonitorPreferenceController.USER_ENABLED_STATUS);
SettingsShadowSystemProperties.set(
TelephonyMonitorPreferenceController.BUILD_TYPE, "userdebug");
@@ -149,7 +166,24 @@
when(mContext.getResources().getBoolean(R.bool.config_show_telephony_monitor))
.thenReturn(true);
SettingsShadowSystemProperties.set(
- TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR, "false");
+ TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+ TelephonyMonitorPreferenceController.DISABLED_STATUS);
+ SettingsShadowSystemProperties.set(
+ TelephonyMonitorPreferenceController.BUILD_TYPE, "userdebug");
+
+ mController.displayPreference(mScreen);
+
+ verify(mPreference).setChecked(false);
+ }
+
+ @Config(shadows = {SettingsShadowSystemProperties.class})
+ @Test
+ public void displayPreference_telephonyMonitorUserDisabled_shouldUncheckedPreference() {
+ when(mContext.getResources().getBoolean(R.bool.config_show_telephony_monitor))
+ .thenReturn(true);
+ SettingsShadowSystemProperties.set(
+ TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+ TelephonyMonitorPreferenceController.USER_DISABLED_STATUS);
SettingsShadowSystemProperties.set(
TelephonyMonitorPreferenceController.BUILD_TYPE, "userdebug");
@@ -168,8 +202,10 @@
mController.handlePreferenceTreeClick(mPreference);
- assertThat(SystemProperties.getBoolean(
- TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR, false)).isTrue();
+ assertThat(TelephonyMonitorPreferenceController.USER_ENABLED_STATUS.equals(
+ SystemProperties.get(
+ TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+ TelephonyMonitorPreferenceController.DISABLED_STATUS))).isTrue();
}
@Config(shadows = {SettingsShadowSystemProperties.class})
@@ -182,8 +218,10 @@
mController.handlePreferenceTreeClick(mPreference);
- assertThat(SystemProperties.getBoolean(
- TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR, false)).isFalse();
+ assertThat(TelephonyMonitorPreferenceController.USER_DISABLED_STATUS.equals(
+ SystemProperties.get(
+ TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+ TelephonyMonitorPreferenceController.DISABLED_STATUS))).isTrue();
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 69bd767..7b2d8cc 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -16,41 +16,28 @@
package com.android.settings.fuelgauge;
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
import android.app.Activity;
-import android.app.Fragment;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.BatteryStats;
import android.os.Bundle;
-import android.view.View;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
-import com.android.settings.applications.AppHeaderController;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -64,8 +51,21 @@
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+ shadows = ShadowEntityHeaderController.class)
public class AdvancedPowerUsageDetailTest {
private static final String APP_LABEL = "app label";
private static final String SUMMARY = "summary";
@@ -85,7 +85,7 @@
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock
- private AppHeaderController mAppHeaderController;
+ private EntityHeaderController mEntityHeaderController;
@Mock
private LayoutPreference mHeaderPreference;
@Mock
@@ -121,18 +121,17 @@
doReturn(APP_LABEL).when(mBundle).getString(anyString());
doReturn(mBundle).when(mFragment).getArguments();
- doReturn(mAppHeaderController).when(mFeatureFactory.applicationFeatureProvider)
- .newAppHeaderController(any(Fragment.class), any(View.class));
- doReturn(mAppHeaderController).when(mAppHeaderController).setButtonActions(anyInt(),
- anyInt());
- doReturn(mAppHeaderController).when(mAppHeaderController).setIcon(any(Drawable.class));
- doReturn(mAppHeaderController).when(mAppHeaderController).setIcon(any(
+ ShadowEntityHeaderController.setUseMock(mEntityHeaderController);
+ doReturn(mEntityHeaderController).when(mEntityHeaderController)
+ .setButtonActions(anyInt(), anyInt());
+ doReturn(mEntityHeaderController).when(mEntityHeaderController)
+ .setIcon(any(Drawable.class));
+ doReturn(mEntityHeaderController).when(mEntityHeaderController).setIcon(any(
ApplicationsState.AppEntry.class));
- doReturn(mAppHeaderController).when(mAppHeaderController).setLabel(anyString());
- doReturn(mAppHeaderController).when(mAppHeaderController).setLabel(any(
- ApplicationsState.AppEntry.class));
- doReturn(mAppHeaderController).when(mAppHeaderController).setSummary(anyString());
-
+ doReturn(mEntityHeaderController).when(mEntityHeaderController).setLabel(anyString());
+ doReturn(mEntityHeaderController).when(mEntityHeaderController)
+ .setLabel(any(ApplicationsState.AppEntry.class));
+ doReturn(mEntityHeaderController).when(mEntityHeaderController).setSummary(anyString());
doReturn(UID).when(mBatterySipper).getUid();
doReturn(APP_LABEL).when(mBatteryEntry).getLabel();
@@ -166,13 +165,18 @@
captor.capture(), anyInt(), any(), any());
}
+ @After
+ public void reset() {
+ ShadowEntityHeaderController.reset();
+ }
+
@Test
public void testInitHeader_NoAppEntry_BuildByBundle() {
mFragment.mAppEntry = null;
mFragment.initHeader();
- verify(mAppHeaderController).setIcon(any(Drawable.class));
- verify(mAppHeaderController).setLabel(APP_LABEL);
+ verify(mEntityHeaderController).setIcon(any(Drawable.class));
+ verify(mEntityHeaderController).setLabel(APP_LABEL);
}
@Test
@@ -187,9 +191,9 @@
mFragment.mAppEntry = mAppEntry;
mFragment.initHeader();
- verify(mAppHeaderController).setIcon(mAppEntry);
- verify(mAppHeaderController).setLabel(mAppEntry);
- verify(mAppHeaderController).setIsInstantApp(false);
+ verify(mEntityHeaderController).setIcon(mAppEntry);
+ verify(mEntityHeaderController).setLabel(mAppEntry);
+ verify(mEntityHeaderController).setIsInstantApp(false);
}
@Test
@@ -204,10 +208,10 @@
mFragment.mAppEntry = mAppEntry;
mFragment.initHeader();
- verify(mAppHeaderController).setIcon(mAppEntry);
- verify(mAppHeaderController).setLabel(mAppEntry);
- verify(mAppHeaderController).setIsInstantApp(true);
- verify(mAppHeaderController).setSummary((CharSequence) null);
+ verify(mEntityHeaderController).setIcon(mAppEntry);
+ verify(mEntityHeaderController).setLabel(mAppEntry);
+ verify(mEntityHeaderController).setIsInstantApp(true);
+ verify(mEntityHeaderController).setSummary((CharSequence) null);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
index fd89558..03759ec 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.os.BatteryStats;
import android.os.Process;
+import android.text.format.DateUtils;
import com.android.internal.os.BatterySipper;
import com.android.settings.SettingsRobolectricTestRunner;
@@ -47,8 +48,11 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.spy;
@@ -62,6 +66,8 @@
private static final long TIME_STATE_TOP_SLEEPING = 2500 * UNIT;
private static final long TIME_STATE_FOREGROUND = 3000 * UNIT;
private static final long TIME_STATE_BACKGROUND = 6000 * UNIT;
+ private static final long TIME_FOREGROUND_ACTIVITY_ZERO = 0;
+ private static final long TIME_FOREGROUND_ACTIVITY = 100 * DateUtils.MINUTE_IN_MILLIS;
private static final int UID = 123;
private static final long TIME_EXPECTED_FOREGROUND = 1500;
@@ -71,6 +77,7 @@
private static final double BATTERY_SYSTEM_USAGE = 600;
private static final double BATTERY_OVERACCOUNTED_USAGE = 500;
private static final double BATTERY_UNACCOUNTED_USAGE = 700;
+ private static final double BATTERY_APP_USAGE = 100;
private static final double TOTAL_BATTERY_USAGE = 1000;
private static final double HIDDEN_USAGE = 200;
private static final int DISCHARGE_AMOUNT = 80;
@@ -180,11 +187,12 @@
sippers.add(mUnaccountedBatterySipper);
when(mProvider.isTypeSystem(mSystemBatterySipper))
.thenReturn(true);
+ doNothing().when(mBatteryUtils).smearScreenBatterySipper(any(), any());
final double totalUsage = mBatteryUtils.removeHiddenBatterySippers(sippers);
+
assertThat(sippers).containsExactly(mNormalBatterySipper);
- assertThat(totalUsage).isWithin(PRECISION).of(
- BATTERY_SCREEN_USAGE + BATTERY_SYSTEM_USAGE + BATTERY_UNACCOUNTED_USAGE);
+ assertThat(totalUsage).isWithin(PRECISION).of(BATTERY_SYSTEM_USAGE);
}
@Test
@@ -206,12 +214,6 @@
}
@Test
- public void testShouldHideSipper_TypeWifi_ReturnTrue() {
- mNormalBatterySipper.drainType = BatterySipper.DrainType.WIFI;
- assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
- }
-
- @Test
public void testShouldHideSipper_TypeCell_ReturnTrue() {
mNormalBatterySipper.drainType = BatterySipper.DrainType.CELL;
assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
@@ -224,12 +226,6 @@
}
@Test
- public void testShouldHideSipper_TypeBluetooth_ReturnTrue() {
- mNormalBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH;
- assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
- }
-
- @Test
public void testShouldHideSipper_TypeSystem_ReturnTrue() {
mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
when(mNormalBatterySipper.getUid()).thenReturn(Process.ROOT_UID);
@@ -259,4 +255,43 @@
HIDDEN_USAGE, DISCHARGE_AMOUNT))
.isWithin(PRECISION).of(PERCENT_SYSTEM_USAGE);
}
+
+ @Test
+ public void testSmearScreenBatterySipper() {
+ final BatterySipper sipperNull = createTestSmearBatterySipper(TIME_FOREGROUND_ACTIVITY_ZERO,
+ BATTERY_APP_USAGE, 0 /* uid */, true /* isUidNull */);
+ final BatterySipper sipperBg = createTestSmearBatterySipper(TIME_FOREGROUND_ACTIVITY_ZERO,
+ BATTERY_APP_USAGE, 1 /* uid */, false /* isUidNull */);
+ final BatterySipper sipperFg = createTestSmearBatterySipper(TIME_FOREGROUND_ACTIVITY,
+ BATTERY_APP_USAGE, 2 /* uid */, false /* isUidNull */);
+
+ final List<BatterySipper> sippers = new ArrayList<>();
+ sippers.add(sipperNull);
+ sippers.add(sipperBg);
+ sippers.add(sipperFg);
+
+ mBatteryUtils.smearScreenBatterySipper(sippers, mScreenBatterySipper);
+
+ assertThat(sipperNull.totalPowerMah).isWithin(PRECISION).of(BATTERY_APP_USAGE);
+ assertThat(sipperBg.totalPowerMah).isWithin(PRECISION).of(BATTERY_APP_USAGE);
+ assertThat(sipperFg.totalPowerMah).isWithin(PRECISION).of(
+ BATTERY_APP_USAGE + BATTERY_SCREEN_USAGE);
+ }
+
+ private BatterySipper createTestSmearBatterySipper(long activityTime, double totalPowerMah,
+ int uidCode, boolean isUidNull) {
+ final BatterySipper sipper = mock(BatterySipper.class);
+ sipper.drainType = BatterySipper.DrainType.APP;
+ sipper.totalPowerMah = totalPowerMah;
+ doReturn(uidCode).when(sipper).getUid();
+ if (!isUidNull) {
+ final BatteryStats.Uid uid = mock(BatteryStats.Uid.class, RETURNS_DEEP_STUBS);
+ doReturn(activityTime).when(mBatteryUtils).getForegroundActivityTotalTimeMs(eq(uid),
+ anyLong());
+ doReturn(uidCode).when(uid).getUid();
+ sipper.uidObj = uid;
+ }
+
+ return sipper;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index c068d11..efbfbda 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -69,6 +69,7 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -172,6 +173,7 @@
mFragment.initFeatureProvider();
mBatteryMeterView = spy(new BatteryMeterView(mRealContext));
mBatteryMeterView.mDrawable = new BatteryMeterView.BatteryMeterDrawable(mRealContext, 0);
+ doNothing().when(mFragment).restartBatteryStatsLoader();
when(mFragment.getActivity()).thenReturn(mSettingsActivity);
when(mAdditionalBatteryInfoMenu.getItemId())
@@ -367,10 +369,10 @@
@Test
public void testSetUsageSummary_timeMoreThanOneMinute_setSummary() {
final long usageTimeMs = 2 * DateUtils.MINUTE_IN_MILLIS;
- doReturn(mRealContext.getText(R.string.battery_used_for)).when(mFragment).getText(
- R.string.battery_used_for);
+ doReturn(mRealContext.getText(R.string.battery_screen_usage)).when(mFragment).getText(
+ R.string.battery_screen_usage);
doReturn(mRealContext).when(mFragment).getContext();
- final String expectedSummary = "Used for 2m";
+ final String expectedSummary = "Screen usage 2m";
mFragment.setUsageSummary(mPreference, usageTimeMs);
@@ -575,6 +577,18 @@
}
@Test
+ public void testOnCreate_BatteryPredictionSkippedWhenDisabled() {
+ PowerUsageFeatureProvider provider = mFeatureFactory.getPowerUsageFeatureProvider(mContext);
+ when(provider.isEnhancedBatteryPredictionEnabled(any())).thenReturn(false);
+ mFragment.mPowerFeatureProvider = provider;
+ doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+ mFragment.initializeBatteryEstimateLoader();
+
+ verify(mLoaderManager, never()).initLoader(eq(PowerUsageSummary.BATTERY_ESTIMATE_LOADER),
+ eq(Bundle.EMPTY), any());
+ }
+
+ @Test
public void testInitAnomalyDetectionIfPossible_detectionEnabled_init() {
when(mFeatureFactory.powerUsageFeatureProvider.isAnomalyDetectionEnabled()).thenReturn(
true);
diff --git a/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java
index 9862f83..e83e237 100644
--- a/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java
@@ -52,12 +52,14 @@
private FakeFeatureFactory mFactory;
private AssistGesturePreferenceController mController;
+ private static final String KEY_ASSIST = "gesture_assist";
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest(mContext);
mFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
- mController = new AssistGesturePreferenceController(mContext, null);
+ mController = new AssistGesturePreferenceController(mContext, null, KEY_ASSIST);
}
@Test
@@ -77,7 +79,7 @@
// Set the setting to be enabled.
final Context context = ShadowApplication.getInstance().getApplicationContext();
Settings.System.putInt(context.getContentResolver(), ASSIST_GESTURE_ENABLED, 1);
- mController = new AssistGesturePreferenceController(context, null);
+ mController = new AssistGesturePreferenceController(context, null, KEY_ASSIST);
assertThat(mController.isSwitchPrefEnabled()).isTrue();
}
@@ -87,7 +89,7 @@
// Set the setting to be disabled.
final Context context = ShadowApplication.getInstance().getApplicationContext();
Settings.System.putInt(context.getContentResolver(), ASSIST_GESTURE_ENABLED, 0);
- mController = new AssistGesturePreferenceController(context, null);
+ mController = new AssistGesturePreferenceController(context, null, KEY_ASSIST);
assertThat(mController.isSwitchPrefEnabled()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java
index bdb3522..d7961e3 100644
--- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java
@@ -47,11 +47,12 @@
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceScreen mScreen;
private DoubleTapPowerPreferenceController mController;
+ private static final String KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power";
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = new DoubleTapPowerPreferenceController(mContext, null);
+ mController = new DoubleTapPowerPreferenceController(mContext, null, KEY_DOUBLE_TAP_POWER);
}
@Test
@@ -78,7 +79,7 @@
final Context context = ShadowApplication.getInstance().getApplicationContext();
Settings.System.putInt(context.getContentResolver(),
CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0);
- mController = new DoubleTapPowerPreferenceController(context, null);
+ mController = new DoubleTapPowerPreferenceController(context, null, KEY_DOUBLE_TAP_POWER);
assertThat(mController.isSwitchPrefEnabled()).isTrue();
}
@@ -89,7 +90,7 @@
final Context context = ShadowApplication.getInstance().getApplicationContext();
Settings.System.putInt(context.getContentResolver(),
CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 1);
- mController = new DoubleTapPowerPreferenceController(context, null);
+ mController = new DoubleTapPowerPreferenceController(context, null, KEY_DOUBLE_TAP_POWER);
assertThat(mController.isSwitchPrefEnabled()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java
index adf8b75..442d11d 100644
--- a/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java
@@ -46,11 +46,13 @@
private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
private DoubleTapScreenPreferenceController mController;
+ private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen";
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = new DoubleTapScreenPreferenceController(
- mContext, null, mAmbientDisplayConfiguration, 0);
+ mContext, null, mAmbientDisplayConfiguration, 0, KEY_DOUBLE_TAP_SCREEN);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java
index 9bf6655..8393fc3 100644
--- a/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java
@@ -53,11 +53,12 @@
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private SensorManager mSensorManager;
private DoubleTwistPreferenceController mController;
+ private static final String KEY_DOUBLE_TWIST = "gesture_double_twist";
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = new DoubleTwistPreferenceController(mContext, null);
+ mController = new DoubleTwistPreferenceController(mContext, null, KEY_DOUBLE_TWIST);
}
@Test
@@ -98,7 +99,7 @@
final Context context = ShadowApplication.getInstance().getApplicationContext();
Settings.System.putInt(context.getContentResolver(),
CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, 1);
- mController = new DoubleTwistPreferenceController(context, null);
+ mController = new DoubleTwistPreferenceController(context, null, KEY_DOUBLE_TWIST);
assertThat(mController.isSwitchPrefEnabled()).isTrue();
}
@@ -109,7 +110,7 @@
final Context context = ShadowApplication.getInstance().getApplicationContext();
Settings.System.putInt(context.getContentResolver(),
CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, 0);
- mController = new DoubleTwistPreferenceController(context, null);
+ mController = new DoubleTwistPreferenceController(context, null, KEY_DOUBLE_TWIST);
assertThat(mController.isSwitchPrefEnabled()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java
index 9dce074..46c0f65 100644
--- a/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java
@@ -47,11 +47,13 @@
private PickupGesturePreferenceController mController;
+ private static final String KEY_PICK_UP = "gesture_pick_up";
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = new PickupGesturePreferenceController(
- mContext, null, mAmbientDisplayConfiguration, 0);
+ mContext, null, mAmbientDisplayConfiguration, 0, KEY_PICK_UP);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
index e909667..cf26cb2 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
@@ -45,11 +45,12 @@
private Context mContext;
private SwipeToNotificationPreferenceController mController;
+ private static final String KEY_SWIPE_DOWN = "gesture_swipe_down_fingerprint";
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = new SwipeToNotificationPreferenceController(mContext, null);
+ mController = new SwipeToNotificationPreferenceController(mContext, null, KEY_SWIPE_DOWN);
}
@Test
@@ -75,7 +76,7 @@
// Set the setting to be enabled.
final Context context = ShadowApplication.getInstance().getApplicationContext();
Settings.System.putInt(context.getContentResolver(), SYSTEM_NAVIGATION_KEYS_ENABLED, 1);
- mController = new SwipeToNotificationPreferenceController(context, null);
+ mController = new SwipeToNotificationPreferenceController(context, null, KEY_SWIPE_DOWN);
assertThat(mController.isSwitchPrefEnabled()).isTrue();
}
@@ -85,7 +86,7 @@
// Set the setting to be disabled.
final Context context = ShadowApplication.getInstance().getApplicationContext();
Settings.System.putInt(context.getContentResolver(), SYSTEM_NAVIGATION_KEYS_ENABLED, 0);
- mController = new SwipeToNotificationPreferenceController(context, null);
+ mController = new SwipeToNotificationPreferenceController(context, null, KEY_SWIPE_DOWN);
assertThat(mController.isSwitchPrefEnabled()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
index fe67449..195e007 100644
--- a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
@@ -16,13 +16,6 @@
package com.android.settings.language;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
@@ -42,6 +35,8 @@
import com.android.settings.TestConfig;
import com.android.settings.core.PreferenceController;
import com.android.settings.dashboard.SummaryLoader;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.ShadowSecureSettings;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -52,11 +47,21 @@
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class LanguageAndInputSettingsTest {
@@ -80,6 +85,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest(mContext);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mock(UserManager.class));
when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mock(InputManager.class));
when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mIm);
@@ -145,6 +151,37 @@
verify(loader).setSummary(provider, null);
}
+ @Test
+ public void testNonIndexableKeys_existInXmlLayout() {
+ final Context context = spy(RuntimeEnvironment.application);
+ //(InputManager) context.getSystemService(Context.INPUT_SERVICE);
+ InputManager manager = mock(InputManager.class);
+ when(manager.getInputDeviceIds()).thenReturn(new int[]{});
+ doReturn(manager).when(context).getSystemService(Context.INPUT_SERVICE);
+ final List<String> niks = LanguageAndInputSettings.SEARCH_INDEX_DATA_PROVIDER
+ .getNonIndexableKeys(context);
+ final int xmlId = (new LanguageAndInputSettings()).getPreferenceScreenResId();
+
+ final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId);
+
+ assertThat(keys).containsAllIn(niks);
+ }
+
+ @Test
+ public void testPreferenceControllers_getPreferenceKeys_existInPreferenceScreen() {
+ final Context context = RuntimeEnvironment.application;
+ final LanguageAndInputSettings fragment = new LanguageAndInputSettings();
+ final List<String> preferenceScreenKeys = XmlTestUtils.getKeysFromPreferenceXml(context,
+ fragment.getPreferenceScreenResId());
+ final List<String> preferenceKeys = new ArrayList<>();
+
+ for (PreferenceController controller : fragment.getPreferenceControllers(context)) {
+ preferenceKeys.add(controller.getPreferenceKey());
+ }
+
+ assertThat(preferenceScreenKeys).containsAllIn(preferenceKeys);
+ }
+
/**
* Test fragment to expose lifecycle and context so we can verify behavior for observables.
*/
diff --git a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
index d1c3207..e7f4968 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
@@ -19,15 +19,18 @@
import android.provider.SearchIndexableResource;
import android.view.Menu;
+import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
-import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
+import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.testutils.XmlTestUtils;
import com.android.settingslib.drawer.CategoryKey;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
@@ -38,16 +41,23 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class NetworkDashboardFragmentTest {
+ @Mock
+ private Context mContext;
+
private NetworkDashboardFragment mFragment;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mFragment = new NetworkDashboardFragment();
}
@@ -89,4 +99,58 @@
assertThat(keys).containsAllIn(niks);
}
-}
+
+ @Test
+ public void testSummaryProvider_hasMobileAndHotspot_shouldReturnMobileSummary() {
+ final MobileNetworkPreferenceController mobileNetworkPreferenceController =
+ mock(MobileNetworkPreferenceController.class);
+ final TetherPreferenceController tetherPreferenceController =
+ mock(TetherPreferenceController.class);
+
+ final SummaryLoader summaryLoader = mock(SummaryLoader.class);
+ final SummaryLoader.SummaryProvider provider =
+ new NetworkDashboardFragment.SummaryProvider(mContext, summaryLoader,
+ mobileNetworkPreferenceController, tetherPreferenceController);
+
+ provider.setListening(false);
+
+ verifyZeroInteractions(summaryLoader);
+
+ when(mobileNetworkPreferenceController.isAvailable()).thenReturn(true);
+ when(tetherPreferenceController.isAvailable()).thenReturn(true);
+
+ provider.setListening(true);
+
+ verify(mContext).getString(R.string.wifi_settings_title);
+ verify(mContext).getString(R.string.network_dashboard_summary_data_usage);
+ verify(mContext).getString(R.string.network_dashboard_summary_hotspot);
+ verify(mContext).getString(R.string.network_dashboard_summary_mobile);
+ verify(mContext, times(3)).getString(R.string.join_many_items_middle, null, null);
+ }
+
+ @Test
+ public void testSummaryProvider_noMobileOrHotspot_shouldReturnSimpleSummary() {
+ final MobileNetworkPreferenceController mobileNetworkPreferenceController =
+ mock(MobileNetworkPreferenceController.class);
+ final TetherPreferenceController tetherPreferenceController =
+ mock(TetherPreferenceController.class);
+
+ final SummaryLoader summaryLoader = mock(SummaryLoader.class);
+ final SummaryLoader.SummaryProvider provider =
+ new NetworkDashboardFragment.SummaryProvider(mContext, summaryLoader,
+ mobileNetworkPreferenceController, tetherPreferenceController);
+
+ provider.setListening(false);
+
+ verifyZeroInteractions(summaryLoader);
+
+ when(mobileNetworkPreferenceController.isAvailable()).thenReturn(false);
+ when(tetherPreferenceController.isAvailable()).thenReturn(false);
+
+ provider.setListening(true);
+
+ verify(mContext).getString(R.string.wifi_settings_title);
+ verify(mContext).getString(R.string.network_dashboard_summary_data_usage);
+ verify(mContext).getString(R.string.join_many_items_middle, null, null);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java
new file mode 100644
index 0000000..589e2df
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java
@@ -0,0 +1,230 @@
+/*
+ * 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.password;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import java.util.Arrays;
+import java.util.regex.Pattern;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+ manifest = TestConfig.MANIFEST_PATH,
+ sdk = TestConfig.SDK_VERSION,
+ shadows = {
+ SettingsShadowResources.class
+ })
+public class ChooseLockGenericControllerTest {
+
+ private ChooseLockGenericController mController;
+
+ @Mock
+ private ManagedLockPasswordProvider mManagedLockPasswordProvider;
+
+ @Mock
+ private DevicePolicyManager mDevicePolicyManager;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mController = new ChooseLockGenericController(
+ application,
+ 0 /* userId */,
+ mDevicePolicyManager,
+ mManagedLockPasswordProvider);
+ SettingsShadowResources.overrideResource(R.bool.config_hide_none_security_option, false);
+ SettingsShadowResources.overrideResource(R.bool.config_hide_swipe_security_option, false);
+ }
+
+ @After
+ public void tearDown() {
+ SettingsShadowResources.reset();
+ }
+
+ @Test
+ public void isScreenLockVisible_shouldRespectResourceConfig() {
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ // All locks except managed defaults to visible
+ assertThat(mController.isScreenLockVisible(lock)).named(lock + " visible")
+ .isEqualTo(lock != ScreenLockType.MANAGED);
+ }
+
+ SettingsShadowResources.overrideResource(R.bool.config_hide_none_security_option, true);
+ SettingsShadowResources.overrideResource(R.bool.config_hide_swipe_security_option, true);
+ assertThat(mController.isScreenLockVisible(ScreenLockType.NONE)).named("NONE visible")
+ .isFalse();
+ assertThat(mController.isScreenLockVisible(ScreenLockType.SWIPE)).named("SWIPE visible")
+ .isFalse();
+ }
+
+ @Test
+ public void isScreenLockVisible_notCurrentUser_shouldHideSwipe() {
+ mController = new ChooseLockGenericController(application, 1 /* userId */);
+ assertThat(mController.isScreenLockVisible(ScreenLockType.SWIPE)).named("SWIPE visible")
+ .isFalse();
+ }
+
+ @Test
+ public void isScreenLockVisible_managedPasswordChoosable_shouldShowManaged() {
+ doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
+
+ assertThat(mController.isScreenLockVisible(ScreenLockType.MANAGED)).named("MANAGED visible")
+ .isTrue();
+ }
+
+ @Test
+ public void isScreenLockEnabled_lowerQuality_shouldReturnFalse() {
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ assertThat(mController.isScreenLockEnabled(lock, lock.maxQuality + 1))
+ .named(lock + " enabled")
+ .isFalse();
+ }
+ }
+
+ @Test
+ public void isScreenLockEnabled_equalQuality_shouldReturnTrue() {
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ assertThat(mController.isScreenLockEnabled(lock, lock.defaultQuality))
+ .named(lock + " enabled")
+ .isTrue();
+ }
+ }
+
+ @Test
+ public void isScreenLockEnabled_higherQuality_shouldReturnTrue() {
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ assertThat(mController.isScreenLockEnabled(lock, lock.maxQuality - 1))
+ .named(lock + " enabled")
+ .isTrue();
+ }
+ }
+
+ @Test
+ public void isScreenLockDisabledByAdmin_lowerQuality_shouldReturnTrue() {
+ doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ assertThat(mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality + 1))
+ .named(lock + " disabledByAdmin")
+ .isTrue();
+ }
+ }
+
+ @Test
+ public void isScreenLockDisabledByAdmin_equalQuality_shouldReturnFalse() {
+ doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ assertThat(mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality))
+ .named(lock + " disabledByAdmin")
+ .isFalse();
+ }
+ }
+
+ @Test
+ public void isScreenLockDisabledByAdmin_higherQuality_shouldReturnFalse() {
+ doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ assertThat(mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality - 1))
+ .named(lock + " disabledByAdmin")
+ .isFalse();
+ }
+ }
+
+ @Test
+ public void isScreenLockDisabledByAdmin_managedNotChoosable_shouldReturnTrue() {
+ doReturn(false).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
+ assertThat(mController.isScreenLockDisabledByAdmin(
+ ScreenLockType.MANAGED, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
+ .named("MANANGED disabledByAdmin")
+ .isTrue();
+ }
+
+ @Test
+ public void getTitle_shouldContainEnumName() {
+ doReturn("MANAGED").when(mManagedLockPasswordProvider).getPickerOptionTitle(anyBoolean());
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ assertThat(mController.getTitle(lock).toString())
+ .containsMatch(Pattern.compile(lock.toString(), Pattern.CASE_INSENSITIVE));
+ }
+ }
+
+ @Test
+ public void getVisibleScreenLockTypes_qualitySomething_shouldReturnPatterPinPassword() {
+ assertThat(mController.getVisibleScreenLockTypes(
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false))
+ .isEqualTo(Arrays.asList(
+ ScreenLockType.PATTERN,
+ ScreenLockType.PIN,
+ ScreenLockType.PASSWORD));
+ }
+
+ @Test
+ public void getVisibleScreenLockTypes_showDisabled_shouldReturnAllButManaged() {
+ assertThat(mController.getVisibleScreenLockTypes(
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, true))
+ .isEqualTo(Arrays.asList(
+ ScreenLockType.NONE,
+ ScreenLockType.SWIPE,
+ ScreenLockType.PATTERN,
+ ScreenLockType.PIN,
+ ScreenLockType.PASSWORD));
+ }
+
+ @Test
+ public void upgradeQuality_noDpmRequirement_shouldReturnQuality() {
+ doReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
+ .when(mDevicePolicyManager).getPasswordQuality(any(ComponentName.class), anyInt());
+
+ int upgradedQuality = mController.upgradeQuality(
+ DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
+ assertThat(upgradedQuality).named("upgradedQuality")
+ .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
+ }
+
+ @Test
+ public void upgradeQuality_dpmRequirement_shouldReturnRequiredQuality() {
+ doReturn(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC)
+ .when(mDevicePolicyManager).getPasswordQuality(any(ComponentName.class), anyInt());
+
+ int upgradedQuality = mController.upgradeQuality(
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ assertThat(upgradedQuality).named("upgradedQuality")
+ .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/password/ScreenLockTypeTest.java b/tests/robotests/src/com/android/settings/password/ScreenLockTypeTest.java
new file mode 100644
index 0000000..96bce00
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/password/ScreenLockTypeTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.password;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.admin.DevicePolicyManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+ manifest = TestConfig.MANIFEST_PATH,
+ sdk = TestConfig.SDK_VERSION)
+public class ScreenLockTypeTest {
+
+ @Test
+ public void fromQuality_shouldReturnLockWithAssociatedQuality() {
+ assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC))
+ .isEqualTo(ScreenLockType.PASSWORD);
+ assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC))
+ .isEqualTo(ScreenLockType.PASSWORD);
+ assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK))
+ .isNull();
+ assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX))
+ .isEqualTo(ScreenLockType.PASSWORD);
+ assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_MANAGED))
+ .isEqualTo(ScreenLockType.MANAGED);
+ assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC))
+ .isEqualTo(ScreenLockType.PIN);
+ assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX))
+ .isEqualTo(ScreenLockType.PIN);
+ assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING))
+ .isEqualTo(ScreenLockType.PATTERN);
+ assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
+ .isEqualTo(ScreenLockType.SWIPE);
+ }
+
+ @Test
+ public void fromKey_shouldReturnLockWithGivenKey() {
+ for (ScreenLockType lock : ScreenLockType.values()) {
+ assertThat(ScreenLockType.fromKey(lock.preferenceKey)).isEqualTo(lock);
+ }
+ assertThat(ScreenLockType.fromKey("nonexistent")).isNull();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
new file mode 100644
index 0000000..2436906
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.password;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.RuntimeEnvironment.application;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.Fragment;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.Button;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
+import com.android.settings.password.ChooseLockPassword.IntentBuilder;
+import com.android.settings.password.SetupChooseLockPassword.SetupChooseLockPasswordFragment;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
+import com.android.settings.testutils.shadow.ShadowEventLogWriter;
+import com.android.settings.testutils.shadow.ShadowUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowActivity;
+import org.robolectric.shadows.ShadowActivity.IntentForResult;
+import org.robolectric.shadows.ShadowDialog;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+ manifest = TestConfig.MANIFEST_PATH,
+ sdk = TestConfig.SDK_VERSION,
+ shadows = {
+ SettingsShadowResources.class,
+ SettingsShadowResources.SettingsShadowTheme.class,
+ ShadowDynamicIndexableContentMonitor.class,
+ ShadowEventLogWriter.class,
+ ShadowUtils.class
+ })
+public class SetupChooseLockPasswordTest {
+
+ @Test
+ public void createActivity_shouldNotCrash() {
+ // Basic sanity test for activity created without crashing
+ Robolectric.buildActivity(SetupChooseLockPassword.class,
+ SetupChooseLockPassword.modifyIntentForSetup(
+ application,
+ new IntentBuilder(application).build()))
+ .setup().get();
+ }
+
+ @Test
+ public void createActivity_withShowOptionsButtonExtra_shouldShowButton() {
+ Intent intent = SetupChooseLockPassword.modifyIntentForSetup(
+ application,
+ new IntentBuilder(application).build());
+ intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
+ SetupChooseLockPassword activity =
+ Robolectric.buildActivity(SetupChooseLockPassword.class, intent).setup().get();
+
+ Button optionsButton = activity.findViewById(R.id.screen_lock_options);
+ assertThat(optionsButton).isNotNull();
+
+ ShadowActivity shadowActivity = shadowOf(activity);
+ optionsButton.performClick();
+
+ assertThat(ShadowDialog.getLatestDialog()).isNotNull();
+ }
+
+ @Test
+ public void createActivity_clickDifferentOption_extrasShouldBePropagated() {
+ Bundle bundle = new Bundle();
+ bundle.putString("foo", "bar");
+
+ Intent intent = new IntentBuilder(application).build();
+ intent.putExtra(ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, bundle);
+ intent = SetupChooseLockPassword.modifyIntentForSetup(application, intent);
+ intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
+
+ SetupChooseLockPassword activity =
+ Robolectric.buildActivity(SetupChooseLockPassword.class, intent).setup().get();
+
+ SetupChooseLockPasswordFragment fragment =
+ (SetupChooseLockPasswordFragment) activity.getFragmentManager()
+ .findFragmentById(R.id.main_content);
+ fragment.onLockTypeSelected(ScreenLockType.PATTERN);
+
+ ShadowActivity shadowActivity = shadowOf(activity);
+ IntentForResult chooseLockIntent = shadowActivity.getNextStartedActivityForResult();
+ assertThat(chooseLockIntent).isNotNull();
+ assertThat(chooseLockIntent.requestCode)
+ .isEqualTo(SetupChooseLockPasswordFragment.REQUEST_SCREEN_LOCK_OPTIONS);
+ assertThat(chooseLockIntent.intent.getStringExtra("foo")).named("Foo extra")
+ .isEqualTo("bar");
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java b/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
index 87eeced..ddbda23 100644
--- a/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
+++ b/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
@@ -108,7 +108,7 @@
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
- sir.xmlResId = R.xml.language_and_input;
+ sir.xmlResId = R.xml.data_usage;
return Arrays.asList(sir);
}
@@ -121,13 +121,7 @@
final List<String> nonIndexableKeys = provider
.getNonIndexableKeys(RuntimeEnvironment.application);
- assertThat(nonIndexableKeys).containsAllOf("phone_language", "spellcheckers_settings",
- "key_user_dictionary_settings", "gesture_settings_category", "gesture_assist",
- "gesture_swipe_down_fingerprint", "gesture_double_tap_power",
- "gesture_double_twist", "gesture_double_tap_screen", "gesture_pick_up",
- "pointer_speed", "tts_settings",
- "game_controller_settings_category", "vibrate_input_devices");
+ assertThat(nonIndexableKeys).containsAllOf("status_header", "limit_summary",
+ "restrict_background");
}
-
-
}
diff --git a/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
index 65b39e6..483dee7 100644
--- a/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
@@ -17,11 +17,13 @@
package com.android.settings.system;
import android.content.Context;
-
import android.os.UserManager;
+
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.testutils.XmlTestUtils;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
@@ -36,7 +38,10 @@
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+ shadows = {
+ ShadowUserManager.class
+ })
public class SystemDashboardFragmentTest {
@Test
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index 65bb389..6085c1e 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -28,14 +28,13 @@
import com.android.settings.localepicker.LocaleFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.overlay.SupportFeatureProvider;
-import com.android.settings.security.SecurityFeatureProvider;
-import com.android.settings.search2.SearchFeatureProvider;
import com.android.settings.overlay.SurveyFeatureProvider;
+import com.android.settings.search2.SearchFeatureProvider;
+import com.android.settings.security.SecurityFeatureProvider;
import com.android.settings.users.UserFeatureProvider;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.mockingDetails;
import static org.mockito.Mockito.when;
/**
@@ -64,7 +63,7 @@
*
* @param context The context must be a deep mock.
*/
- public static void setupForTest(Context context) {
+ public static FakeFeatureFactory setupForTest(Context context) {
sFactory = null;
when(context.getString(com.android.settings.R.string.config_featureFactory))
.thenReturn(FakeFeatureFactory.class.getName());
@@ -74,6 +73,7 @@
} catch (ClassNotFoundException e) {
// Ignore.
}
+ return (FakeFeatureFactory) FakeFeatureFactory.getFactory(context);
}
/**
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
index cb02d3e..d4b0ff7 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
@@ -137,6 +137,16 @@
realResources, Resources.class, "getInteger", ClassParameter.from(int.class, id));
}
+ @Implementation
+ public boolean getBoolean(int id) {
+ final Object override = sResourceOverrides.get(id);
+ if (override instanceof Boolean) {
+ return (boolean) override;
+ }
+ return Shadow.directlyOn(realResources, Resources.class, "getBoolean",
+ ClassParameter.from(int.class, id));
+ }
+
@Implements(Theme.class)
public static class SettingsShadowTheme extends ShadowTheme {
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowEntityHeaderController.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowEntityHeaderController.java
new file mode 100644
index 0000000..bccb297
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowEntityHeaderController.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.testutils.shadow;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.view.View;
+
+import com.android.settings.widget.EntityHeaderController;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(value = EntityHeaderController.class, callThroughByDefault = false)
+public class ShadowEntityHeaderController {
+
+ private static EntityHeaderController sMockController;
+
+ public static void setUseMock(EntityHeaderController mockController) {
+ sMockController = mockController;
+ }
+
+ @Resetter
+ public static void reset() {
+ sMockController = null;
+ }
+
+ @Implementation
+ public static EntityHeaderController newInstance(Context context, Fragment fragment,
+ View header) {
+ return sMockController;
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPowerManagerWrapper.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPowerManagerWrapper.java
new file mode 100644
index 0000000..7aa28fa
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPowerManagerWrapper.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.settings.testutils.shadow;
+
+import com.android.settings.display.PowerManagerWrapper;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(PowerManagerWrapper.class)
+public class ShadowPowerManagerWrapper {
+
+ @Implementation
+ public int getMinimumScreenBrightnessSetting() {
+ return 0;
+ }
+
+ @Implementation
+ public int getMaximumScreenBrightnessSetting() {
+ return 0;
+ }
+
+ @Implementation
+ public int getMinimumScreenBrightnessForVrSetting() {
+ return 0;
+ }
+
+ @Implementation
+ public int getMaximumScreenBrightnessForVrSetting() {
+ return 0;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
similarity index 61%
rename from tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java
rename to tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
index 8b9b4b4..e6c742a 100644
--- a/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
@@ -14,17 +14,9 @@
* limitations under the License.
*/
-package com.android.settings.applications;
+package com.android.settings.widget;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
import android.app.ActionBar;
import android.app.Activity;
import android.app.Fragment;
@@ -43,6 +35,8 @@
import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
@@ -53,9 +47,17 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class AppHeaderControllerTest {
+public class EntityHeaderControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@@ -64,16 +66,19 @@
@Mock
private Fragment mFragment;
+ private FakeFeatureFactory mFeatureFactory;
private Context mShadowContext;
private LayoutInflater mLayoutInflater;
private PackageInfo mInfo;
- private AppHeaderController mController;
-
+ private EntityHeaderController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest(mContext);
+ mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
mShadowContext = RuntimeEnvironment.application;
+ when(mContext.getApplicationContext()).thenReturn(mContext);
when(mFragment.getContext()).thenReturn(mShadowContext);
mLayoutInflater = LayoutInflater.from(mShadowContext);
mInfo = new PackageInfo();
@@ -82,7 +87,7 @@
@Test
public void testBuildView_constructedWithoutView_shouldCreateNewView() {
- mController = new AppHeaderController(mShadowContext, mFragment, null);
+ mController = EntityHeaderController.newInstance(mShadowContext, mFragment, null);
View view = mController.done(mActivity);
assertThat(view).isNotNull();
@@ -90,7 +95,7 @@
@Test
public void testBuildView_withContext_shouldBuildPreference() {
- mController = new AppHeaderController(mShadowContext, mFragment, null);
+ mController = EntityHeaderController.newInstance(mShadowContext, mFragment, null);
Preference preference = mController.done(mActivity, mShadowContext);
assertThat(preference instanceof LayoutPreference).isTrue();
@@ -98,8 +103,8 @@
@Test
public void testBuildView_constructedWithView_shouldReturnSameView() {
- View inputView = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
- mController = new AppHeaderController(mShadowContext, mFragment, inputView);
+ View inputView = mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
+ mController = EntityHeaderController.newInstance(mShadowContext, mFragment, inputView);
View view = mController.done(mActivity);
assertThat(view).isSameAs(inputView);
@@ -108,11 +113,12 @@
@Test
public void bindViews_shouldBindAllData() {
final String testString = "test";
- final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
- final TextView label = appHeader.findViewById(R.id.app_detail_title);
- final TextView version = appHeader.findViewById(R.id.app_detail_summary);
+ final View header = mLayoutInflater.inflate(
+ R.layout.settings_entity_header, null /* root */);
+ final TextView label = header.findViewById(R.id.entity_header_title);
+ final TextView version = header.findViewById(R.id.entity_header_summary);
- mController = new AppHeaderController(mShadowContext, mFragment, appHeader);
+ mController = EntityHeaderController.newInstance(mShadowContext, mFragment, header);
mController.setLabel(testString);
mController.setSummary(testString);
mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add));
@@ -129,22 +135,22 @@
info.activityInfo.packageName = "123";
info.activityInfo.name = "321";
final View appLinks = mLayoutInflater
- .inflate(R.layout.app_details, null /* root */);
+ .inflate(R.layout.settings_entity_header, null /* root */);
when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
.thenReturn(info);
- mController = new AppHeaderController(mContext, mFragment, appLinks);
+ mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
mController.setButtonActions(
- AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
- AppHeaderController.ActionType.ACTION_NONE);
+ EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
+ EntityHeaderController.ActionType.ACTION_NONE);
mController.done(mActivity);
- assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+ assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
.isEqualTo(View.VISIBLE);
- assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+ assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
.isEqualTo(View.GONE);
try {
- appLinks.findViewById(R.id.left_button).performClick();
+ appLinks.findViewById(android.R.id.button1).performClick();
} catch (Exception e) {
// Ignore exception because the launching intent is fake.
}
@@ -154,94 +160,94 @@
@Test
public void bindButton_noAppPref_shouldNotShowButton() {
final View appLinks = mLayoutInflater
- .inflate(R.layout.app_details, null /* root */);
+ .inflate(R.layout.settings_entity_header, null /* root */);
when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
.thenReturn(null);
- mController = new AppHeaderController(mContext, mFragment, appLinks);
+ mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
mController.setButtonActions(
- AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
- AppHeaderController.ActionType.ACTION_NONE);
+ EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
+ EntityHeaderController.ActionType.ACTION_NONE);
mController.done(mActivity);
- assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+ assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
.isEqualTo(View.GONE);
- assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+ assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void bindButton_noAppInfo_shouldNotShowButton() {
final View appLinks = mLayoutInflater
- .inflate(R.layout.app_details, null /* root */);
+ .inflate(R.layout.settings_entity_header, null /* root */);
- mController = new AppHeaderController(mContext, mFragment, appLinks);
+ mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
mController.setPackageName(null)
.setButtonActions(
- AppHeaderController.ActionType.ACTION_APP_INFO,
- AppHeaderController.ActionType.ACTION_NONE);
+ EntityHeaderController.ActionType.ACTION_APP_INFO,
+ EntityHeaderController.ActionType.ACTION_NONE);
mController.done(mActivity);
- assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+ assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
.isEqualTo(View.GONE);
- assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+ assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void bindButton_hasAppInfo_shouldShowButton() {
final View appLinks = mLayoutInflater
- .inflate(R.layout.app_details, null /* root */);
+ .inflate(R.layout.settings_entity_header, null /* root */);
when(mFragment.getActivity()).thenReturn(mock(Activity.class));
- mController = new AppHeaderController(mContext, mFragment, appLinks);
+ mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
mController.setPackageName("123")
.setUid(UserHandle.USER_SYSTEM)
.setButtonActions(
- AppHeaderController.ActionType.ACTION_APP_INFO,
- AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
+ EntityHeaderController.ActionType.ACTION_APP_INFO,
+ EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
mController.done(mActivity);
- assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+ assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
.isEqualTo(View.VISIBLE);
- assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+ assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void bindButton_hasAppInfo_shouldHaveContentDescription() {
final View appLinks = mLayoutInflater
- .inflate(R.layout.app_details, null /* root */);
+ .inflate(R.layout.settings_entity_header, null /* root */);
when(mFragment.getActivity()).thenReturn(mock(Activity.class));
when(mContext.getString(eq(R.string.application_info_label))).thenReturn("App Info");
- mController = new AppHeaderController(mContext, mFragment, appLinks);
+ mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
mController.setPackageName("123")
.setUid(UserHandle.USER_SYSTEM)
.setButtonActions(
- AppHeaderController.ActionType.ACTION_APP_INFO,
- AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
+ EntityHeaderController.ActionType.ACTION_APP_INFO,
+ EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
mController.done(mActivity);
- assertThat(appLinks.findViewById(R.id.left_button).getContentDescription())
+ assertThat(appLinks.findViewById(android.R.id.button1).getContentDescription())
.isEqualTo("App Info");
}
@Test
public void bindButton_hasAppNotifIntent_shouldShowButton() {
final View appLinks = mLayoutInflater
- .inflate(R.layout.app_details, null /* root */);
+ .inflate(R.layout.settings_entity_header, null /* root */);
- mController = new AppHeaderController(mContext, mFragment, appLinks);
+ mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
mController.setAppNotifPrefIntent(new Intent())
.setButtonActions(
- AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
- AppHeaderController.ActionType.ACTION_NONE);
+ EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
+ EntityHeaderController.ActionType.ACTION_NONE);
mController.done(mActivity);
- assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+ assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
.isEqualTo(View.VISIBLE);
- assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+ assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
.isEqualTo(View.GONE);
}
@@ -249,31 +255,35 @@
// app is instant.
@Test
public void instantApps_normalAppsDontGetLabel() {
- final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
- mController = new AppHeaderController(mContext, mFragment, appHeader);
+ final View header = mLayoutInflater.inflate(
+ R.layout.settings_entity_header, null /* root */);
+ mController = EntityHeaderController.newInstance(mContext, mFragment, header);
mController.done(mActivity);
- assertThat(appHeader.findViewById(R.id.install_type).getVisibility())
+
+ assertThat(header.findViewById(R.id.install_type).getVisibility())
.isEqualTo(View.GONE);
}
// Test that the "instant apps" label is present in the header when we have an instant app.
@Test
public void instantApps_expectedHeaderItem() {
- final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
- mController = new AppHeaderController(mContext, mFragment, appHeader);
+ final View header = mLayoutInflater.inflate(
+ R.layout.settings_entity_header, null /* root */);
+ mController = EntityHeaderController.newInstance(mContext, mFragment, header);
mController.setIsInstantApp(true);
mController.done(mActivity);
- TextView label = appHeader.findViewById(R.id.install_type);
+ TextView label = header.findViewById(R.id.install_type);
+
assertThat(label.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(label.getText()).isEqualTo(
- appHeader.getResources().getString(R.string.install_type_instant));
- assertThat(appHeader.findViewById(R.id.app_detail_summary).getVisibility())
+ header.getResources().getString(R.string.install_type_instant));
+ assertThat(header.findViewById(R.id.entity_header_summary).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void styleActionBar_invalidObjects_shouldNotCrash() {
- mController = new AppHeaderController(mShadowContext, mFragment, null);
+ mController = EntityHeaderController.newInstance(mShadowContext, mFragment, null);
mController.styleActionBar(null);
when(mActivity.getActionBar()).thenReturn(null);
@@ -286,7 +296,7 @@
public void styleActionBar_setElevationAndBackground() {
final ActionBar actionBar = mActivity.getActionBar();
- mController = new AppHeaderController(mShadowContext, mFragment, null);
+ mController = EntityHeaderController.newInstance(mShadowContext, mFragment, null);
mController.styleActionBar(mActivity);
verify(actionBar).setElevation(0);
@@ -297,7 +307,7 @@
@Test
public void initAppHeaderController_appHeaderNull_useFragmentContext() {
- mController = new AppHeaderController(mContext, mFragment, null);
+ mController = EntityHeaderController.newInstance(mContext, mFragment, null);
// Fragment.getContext() is invoked to inflate the view
verify(mFragment).getContext();
diff --git a/tests/unit/src/com/android/settings/applications/ManageApplicationsLaunchTest.java b/tests/unit/src/com/android/settings/applications/ManageApplicationsLaunchTest.java
new file mode 100644
index 0000000..e074966
--- /dev/null
+++ b/tests/unit/src/com/android/settings/applications/ManageApplicationsLaunchTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.applications;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.allOf;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ManageApplicationsLaunchTest {
+
+ private Instrumentation mInstrumentation;
+
+ @Before
+ public void setUp() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ }
+
+ @Test
+ public void launchAppsSettings_shouldShowAppList() throws Exception {
+ final Intent appsSettingsIntent = new
+ Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
+
+ mInstrumentation.startActivitySync(appsSettingsIntent);
+
+ onView(allOf(withText("Calculator"))).check(matches(isDisplayed()));
+ }
+}
diff --git a/tests/unit/src/com/android/settings/applications/ManageApplicationsTest.java b/tests/unit/src/com/android/settings/applications/ManageApplicationsUnitTest.java
similarity index 93%
rename from tests/unit/src/com/android/settings/applications/ManageApplicationsTest.java
rename to tests/unit/src/com/android/settings/applications/ManageApplicationsUnitTest.java
index 92e556e..10c9edb 100644
--- a/tests/unit/src/com/android/settings/applications/ManageApplicationsTest.java
+++ b/tests/unit/src/com/android/settings/applications/ManageApplicationsUnitTest.java
@@ -16,18 +16,22 @@
package com.android.settings.applications;
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-
import android.content.pm.ApplicationInfo;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
import org.junit.Test;
+import org.junit.runner.RunWith;
-public class ManageApplicationsTest {
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ManageApplicationsUnitTest {
@Test
public void getOverrideFilter_filtersVolumeForAudio() {
AppFilter filter =