Merge "Point to the new checkstyle location for packages/apps/Settings PREUPLOAD hook."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3c35428..87b6372 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -276,21 +276,6 @@
android:value="true" />
</activity>
- <activity android:name=".wifi.WifiSetupActivity"
- android:taskAffinity="com.android.wizard"
- android:theme="@style/SetupWizardDisableAppStartingTheme"
- android:label="@string/wifi_setup_wizard_title"
- android:icon="@drawable/empty_icon"
- android:clearTaskOnLaunch="true"
- android:windowSoftInputMode="adjustNothing">
- <intent-filter android:priority="1">
- <action android:name="com.android.net.wifi.SETUP_WIFI_NETWORK" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
- android:value="true" />
- </activity>
-
<activity android:name="Settings$AdvancedWifiSettingsActivity"
android:taskAffinity="com.android.settings"
android:label="@string/wifi_advanced_settings_label"
@@ -2565,16 +2550,6 @@
</intent-filter>
</activity>
- <activity android:name=".ActiveNetworkScorerDialog"
- android:label="@string/wifi_assistant_title"
- android:excludeFromRecents="true"
- android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert">
- <intent-filter android:priority="1">
- <action android:name="android.net.scoring.CHANGE_ACTIVE" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
<activity android:name="Settings$NotificationAccessSettingsActivity"
android:label="@string/manage_notification_access_title"
android:taskAffinity="">
@@ -3083,10 +3058,22 @@
android:value="com.android.settings.datausage.DataUsageSummary"/>
</activity-alias>
+ <activity android:name=".Settings$ConnectedDeviceDashboardActivity"
+ android:label="@string/connected_devices_dashboard_title"
+ android:icon="@drawable/ic_bt_laptop">
+ <intent-filter android:priority="10">
+ <action android:name="com.android.settings.action.SETTINGS"/>
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment"/>
+ <meta-data android:name="com.android.settings.category"
+ android:value="com.android.settings.category.ia.homepage"/>
+ </activity>
+
<activity android:name=".Settings$AppAndNotificationDashboardActivity"
android:label="@string/app_and_notification_dashboard_title"
android:icon="@drawable/ic_settings_applications">
- <intent-filter android:priority="8">
+ <intent-filter android:priority="9">
<action android:name="com.android.settings.action.SETTINGS"/>
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -3097,7 +3084,7 @@
<activity-alias android:name="BatteryDashboardAlias"
android:targetActivity="Settings$PowerUsageSummaryActivity">
- <intent-filter android:priority="7">
+ <intent-filter android:priority="8">
<action android:name="com.android.settings.action.SETTINGS"/>
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -3108,7 +3095,7 @@
<activity-alias android:name="DisplayDashboardAlias"
android:targetActivity="Settings$DisplaySettingsActivity">
- <intent-filter android:priority="6">
+ <intent-filter android:priority="7">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
<meta-data android:name="com.android.settings.category"
@@ -3121,7 +3108,7 @@
<activity-alias android:name="SoundDashboardAlias"
android:targetActivity="Settings$SoundSettingsActivity">
- <intent-filter android:priority="5">
+ <intent-filter android:priority="6">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
<meta-data android:name="com.android.settings.category"
@@ -3135,7 +3122,7 @@
<activity android:name=".Settings$StorageDashboardActivity"
android:label="@string/storage_settings"
android:icon="@drawable/ic_settings_storage">
- <intent-filter android:priority="4">
+ <intent-filter android:priority="5">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
<meta-data android:name="com.android.settings.category"
@@ -3162,7 +3149,7 @@
<activity-alias android:name="SecurityDashboardAlias"
android:targetActivity="Settings$SecuritySettingsActivity">
- <intent-filter android:priority="3">
+ <intent-filter android:priority="4">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
<meta-data android:name="com.android.settings.category"
@@ -3173,6 +3160,18 @@
android:value="true" />
</activity-alias>
+ <activity android:name=".Settings$UserAndAccountDashboardActivity"
+ android:label="@string/account_dashboard_title"
+ android:icon="@drawable/ic_settings_accounts">
+ <intent-filter android:priority="3">
+ <action android:name="com.android.settings.action.SETTINGS"/>
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.accounts.UserAndAccountDashboardFragment"/>
+ <meta-data android:name="com.android.settings.category"
+ android:value="com.android.settings.category.ia.homepage"/>
+ </activity>
+
<activity-alias android:name="LocationDashboardAlias"
android:targetActivity="Settings$LocationSettingsActivity">
<intent-filter>
@@ -3186,6 +3185,19 @@
android:value="true" />
</activity-alias>
+ <activity-alias android:name="AccessibilityDashboardAlias"
+ android:targetActivity="Settings$AccessibilitySettingsActivity">
+ <intent-filter android:priority="2">
+ <action android:name="com.android.settings.action.SETTINGS" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.category"
+ android:value="com.android.settings.category.ia.homepage" />
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.accessibility.AccessibilitySettings" />
+ <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+ android:value="true" />
+ </activity-alias>
+
<activity android:name=".Settings$SystemDashboardActivity"
android:label="@string/header_category_system"
android:icon="@drawable/ic_settings_about">
@@ -3257,19 +3269,6 @@
android:value="true" />
</activity-alias>
- <activity-alias android:name="AccessibilityDashboardAlias"
- android:targetActivity="Settings$AccessibilitySettingsActivity">
- <intent-filter android:priority="150">
- <action android:name="com.android.settings.action.SETTINGS" />
- </intent-filter>
- <meta-data android:name="com.android.settings.category"
- android:value="com.android.settings.category.ia.system" />
- <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
- android:value="com.android.settings.accessibility.AccessibilitySettings" />
- <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
- android:value="true" />
- </activity-alias>
-
<activity-alias android:name="PrivacyDashboardAlias"
android:targetActivity="Settings$PrivacySettingsActivity">
<intent-filter android:priority="60">
@@ -3334,18 +3333,6 @@
android:value="com.android.settings.applications.ProcessStatsSummary" />
</activity-alias>
- <activity android:name=".Settings$ConnectedDeviceDashboardActivity"
- android:label="@string/connected_devices_dashboard_title"
- android:icon="@drawable/ic_bt_laptop">
- <intent-filter android:priority="9">
- <action android:name="com.android.settings.action.SETTINGS"/>
- </intent-filter>
- <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
- android:value="com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment"/>
- <meta-data android:name="com.android.settings.category"
- android:value="com.android.settings.category.ia.homepage"/>
- </activity>
-
<activity-alias android:name="BluetoothDashboardAlias"
android:targetActivity="Settings$BluetoothSettingsActivity">
<intent-filter android:priority="7">
@@ -3416,18 +3403,6 @@
android:value="true" />
</activity-alias>
- <activity android:name=".Settings$UserAndAccountDashboardActivity"
- android:label="@string/account_dashboard_title"
- android:icon="@drawable/ic_settings_accounts">
- <intent-filter android:priority="2">
- <action android:name="com.android.settings.action.SETTINGS"/>
- </intent-filter>
- <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
- android:value="com.android.settings.accounts.UserAndAccountDashboardFragment"/>
- <meta-data android:name="com.android.settings.category"
- android:value="com.android.settings.category.ia.homepage"/>
- </activity>
-
<activity-alias android:name="UserDashboardAlias"
android:targetActivity="Settings$UserSettingsActivity">
<intent-filter android:priority="8">
diff --git a/res/drawable-hdpi/setup_illustration_horizontal_tile.jpg b/res/drawable-hdpi/setup_illustration_horizontal_tile.jpg
deleted file mode 100644
index 8d330ce..0000000
--- a/res/drawable-hdpi/setup_illustration_horizontal_tile.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/setup_illustration_lock_screen.jpg b/res/drawable-hdpi/setup_illustration_lock_screen.jpg
deleted file mode 100644
index 263d33e..0000000
--- a/res/drawable-hdpi/setup_illustration_lock_screen.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/setup_illustration_tile.jpg b/res/drawable-hdpi/setup_illustration_tile.jpg
deleted file mode 100644
index d518abd..0000000
--- a/res/drawable-hdpi/setup_illustration_tile.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/setup_illustration_wifi.jpg b/res/drawable-hdpi/setup_illustration_wifi.jpg
deleted file mode 100644
index 2e7241d..0000000
--- a/res/drawable-hdpi/setup_illustration_wifi.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/setup_illustration_horizontal_tile.jpg b/res/drawable-mdpi/setup_illustration_horizontal_tile.jpg
deleted file mode 100644
index 2b9b04b..0000000
--- a/res/drawable-mdpi/setup_illustration_horizontal_tile.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/setup_illustration_lock_screen.jpg b/res/drawable-mdpi/setup_illustration_lock_screen.jpg
deleted file mode 100644
index 004fa9e..0000000
--- a/res/drawable-mdpi/setup_illustration_lock_screen.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/setup_illustration_tile.jpg b/res/drawable-mdpi/setup_illustration_tile.jpg
deleted file mode 100644
index f2e1bcb..0000000
--- a/res/drawable-mdpi/setup_illustration_tile.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/setup_illustration_wifi.jpg b/res/drawable-mdpi/setup_illustration_wifi.jpg
deleted file mode 100644
index 4a9b8a5..0000000
--- a/res/drawable-mdpi/setup_illustration_wifi.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp-hdpi/setup_illustration_lock_screen.jpg b/res/drawable-sw600dp-hdpi/setup_illustration_lock_screen.jpg
deleted file mode 100644
index 933e986..0000000
--- a/res/drawable-sw600dp-hdpi/setup_illustration_lock_screen.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp-hdpi/setup_illustration_wifi.jpg b/res/drawable-sw600dp-hdpi/setup_illustration_wifi.jpg
deleted file mode 100644
index 7359f56..0000000
--- a/res/drawable-sw600dp-hdpi/setup_illustration_wifi.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp-mdpi/setup_illustration_lock_screen.jpg b/res/drawable-sw600dp-mdpi/setup_illustration_lock_screen.jpg
deleted file mode 100644
index 57e0385..0000000
--- a/res/drawable-sw600dp-mdpi/setup_illustration_lock_screen.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp-mdpi/setup_illustration_wifi.jpg b/res/drawable-sw600dp-mdpi/setup_illustration_wifi.jpg
deleted file mode 100644
index 9b13e51..0000000
--- a/res/drawable-sw600dp-mdpi/setup_illustration_wifi.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp-xhdpi/setup_illustration_lock_screen.jpg b/res/drawable-sw600dp-xhdpi/setup_illustration_lock_screen.jpg
deleted file mode 100644
index e329a96..0000000
--- a/res/drawable-sw600dp-xhdpi/setup_illustration_lock_screen.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp-xhdpi/setup_illustration_wifi.jpg b/res/drawable-sw600dp-xhdpi/setup_illustration_wifi.jpg
deleted file mode 100644
index dc9e385..0000000
--- a/res/drawable-sw600dp-xhdpi/setup_illustration_wifi.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp-xxhdpi/setup_illustration_lock_screen.jpg b/res/drawable-sw600dp-xxhdpi/setup_illustration_lock_screen.jpg
deleted file mode 100644
index 7934e8a..0000000
--- a/res/drawable-sw600dp-xxhdpi/setup_illustration_lock_screen.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp-xxhdpi/setup_illustration_wifi.jpg b/res/drawable-sw600dp-xxhdpi/setup_illustration_wifi.jpg
deleted file mode 100644
index b57bc17..0000000
--- a/res/drawable-sw600dp-xxhdpi/setup_illustration_wifi.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp-xxxhdpi/setup_illustration_lock_screen.jpg b/res/drawable-sw600dp-xxxhdpi/setup_illustration_lock_screen.jpg
deleted file mode 100644
index ab61328..0000000
--- a/res/drawable-sw600dp-xxxhdpi/setup_illustration_lock_screen.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp-xxxhdpi/setup_illustration_wifi.jpg b/res/drawable-sw600dp-xxxhdpi/setup_illustration_wifi.jpg
deleted file mode 100644
index b940a9b..0000000
--- a/res/drawable-sw600dp-xxxhdpi/setup_illustration_wifi.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/setup_illustration_horizontal_tile.jpg b/res/drawable-xhdpi/setup_illustration_horizontal_tile.jpg
deleted file mode 100644
index ae67f38..0000000
--- a/res/drawable-xhdpi/setup_illustration_horizontal_tile.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/setup_illustration_lock_screen.jpg b/res/drawable-xhdpi/setup_illustration_lock_screen.jpg
deleted file mode 100644
index b78a59d..0000000
--- a/res/drawable-xhdpi/setup_illustration_lock_screen.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/setup_illustration_tile.jpg b/res/drawable-xhdpi/setup_illustration_tile.jpg
deleted file mode 100644
index 8beeda8..0000000
--- a/res/drawable-xhdpi/setup_illustration_tile.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/setup_illustration_wifi.jpg b/res/drawable-xhdpi/setup_illustration_wifi.jpg
deleted file mode 100644
index c03f4dd..0000000
--- a/res/drawable-xhdpi/setup_illustration_wifi.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/setup_illustration_horizontal_tile.jpg b/res/drawable-xxhdpi/setup_illustration_horizontal_tile.jpg
deleted file mode 100644
index 18b885d..0000000
--- a/res/drawable-xxhdpi/setup_illustration_horizontal_tile.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/setup_illustration_lock_screen.jpg b/res/drawable-xxhdpi/setup_illustration_lock_screen.jpg
deleted file mode 100644
index 875e55e..0000000
--- a/res/drawable-xxhdpi/setup_illustration_lock_screen.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/setup_illustration_tile.jpg b/res/drawable-xxhdpi/setup_illustration_tile.jpg
deleted file mode 100644
index 05d4804..0000000
--- a/res/drawable-xxhdpi/setup_illustration_tile.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/setup_illustration_wifi.jpg b/res/drawable-xxhdpi/setup_illustration_wifi.jpg
deleted file mode 100644
index e0791cd..0000000
--- a/res/drawable-xxhdpi/setup_illustration_wifi.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/setup_illustration_horizontal_tile.jpg b/res/drawable-xxxhdpi/setup_illustration_horizontal_tile.jpg
deleted file mode 100644
index 6d97626..0000000
--- a/res/drawable-xxxhdpi/setup_illustration_horizontal_tile.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/setup_illustration_lock_screen.jpg b/res/drawable-xxxhdpi/setup_illustration_lock_screen.jpg
deleted file mode 100644
index 8ac85a4..0000000
--- a/res/drawable-xxxhdpi/setup_illustration_lock_screen.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/setup_illustration_tile.jpg b/res/drawable-xxxhdpi/setup_illustration_tile.jpg
deleted file mode 100644
index 9d5c4c9..0000000
--- a/res/drawable-xxxhdpi/setup_illustration_tile.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/setup_illustration_wifi.jpg b/res/drawable-xxxhdpi/setup_illustration_wifi.jpg
deleted file mode 100644
index 62352d3..0000000
--- a/res/drawable-xxxhdpi/setup_illustration_wifi.jpg
+++ /dev/null
Binary files differ
diff --git a/res/drawable/ic_info_outline_24dp.xml b/res/drawable/ic_info_outline_24dp.xml
new file mode 100644
index 0000000..3fe1e9e
--- /dev/null
+++ b/res/drawable/ic_info_outline_24dp.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/textColorSecondary">
+ <path
+ android:fillColor="#000000"
+ android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
+</vector>
diff --git a/res/drawable/setup_ic_add_another_network.xml b/res/drawable/setup_ic_add_another_network.xml
deleted file mode 100644
index fd716d1..0000000
--- a/res/drawable/setup_ic_add_another_network.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="25.0dp"
- android:height="32.0dp"
- android:viewportWidth="38.0"
- android:viewportHeight="48.0">
-
- <group android:translateX="5.0" android:translateY="10.0">
-
- <path
- android:fillColor="?android:attr/colorControlNormal"
- android:pathData="M28.0,16.0L16.0,16.0l0.0,12.0l-4.0,0.0L12.0,16.0L0.0,16.0l0.0,-4.0l12.0,0.0L12.0,0.0l4.0,0.0l0.0,12.0l12.0,0.0l0.0,4.0z"/>
-
- </group>
-
-</vector>
diff --git a/res/layout/choose_lock_pattern_common.xml b/res/layout/choose_lock_pattern_common.xml
index 6557e6a..c50aa5b 100644
--- a/res/layout/choose_lock_pattern_common.xml
+++ b/res/layout/choose_lock_pattern_common.xml
@@ -22,7 +22,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/ic_lock"
- settings:suwHeaderText="@string/wifi_setup_wizard_title">
+ settings:suwHeaderText="@string/lockpassword_choose_your_pattern_header">
<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
android:id="@+id/topLayout"
diff --git a/res/layout/fingerprint_enroll_introduction.xml b/res/layout/fingerprint_enroll_introduction.xml
index 2348b6a..ccd1f62 100644
--- a/res/layout/fingerprint_enroll_introduction.xml
+++ b/res/layout/fingerprint_enroll_introduction.xml
@@ -35,6 +35,12 @@
android:layout_height="wrap_content"
android:text="@string/security_settings_fingerprint_enroll_introduction_message" />
+ <com.android.setupwizardlib.view.RichTextView
+ android:id="@+id/error_text"
+ style="@style/SuwDescription.Glif"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/res/layout/fingerprint_settings_footer.xml b/res/layout/fingerprint_settings_footer.xml
deleted file mode 100644
index 8d17052..0000000
--- a/res/layout/fingerprint_settings_footer.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 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
- -->
-<com.android.settings.widget.LinkTextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- style="@android:style/TextAppearance.Material.Body1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="?android:attr/textColorSecondary"
- android:paddingTop="32dp"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:selectable="false" />
diff --git a/res/layout/preference_footer.xml b/res/layout/preference_footer.xml
new file mode 100644
index 0000000..64fad74
--- /dev/null
+++ b/res/layout/preference_footer.xml
@@ -0,0 +1,55 @@
+<?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:minHeight="?android:attr/listPreferredItemHeight"
+ android:gravity="center_vertical"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:background="?android:attr/selectableItemBackground"
+ android:clipToPadding="false">
+
+ <LinearLayout
+ android:id="@+id/icon_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="60dp"
+ android:gravity="start|center_vertical"
+ android:orientation="horizontal"
+ android:paddingEnd="12dp"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp">
+ <com.android.internal.widget.PreferenceImageView
+ android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+
+ <com.android.settings.widget.LinkTextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingBottom="16dp"
+ android:paddingTop="16dp"
+ android:maxLines="10"
+ android:textColor="?android:attr/textColorSecondary"
+ android:ellipsize="marquee"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/setup_wifi_add_network.xml b/res/layout/setup_wifi_add_network.xml
deleted file mode 100644
index 23577c5..0000000
--- a/res/layout/setup_wifi_add_network.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/other_network"
- android:layout_width="match_parent"
- android:layout_height="@dimen/setup_add_network_item_height"
- android:background="?android:attr/selectableItemBackground"
- android:gravity="center_vertical"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart">
-
- <LinearLayout
- android:layout_width="@dimen/setup_preference_icon_frame_width"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/setup_preference_icon_frame_margin_start"
- android:gravity="start|center_vertical"
- android:paddingEnd="@dimen/setup_preference_icon_frame_padding_end">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/setup_ic_add_another_network" />
-
- </LinearLayout>
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/wifi_other_network"
- android:textAppearance="@style/TextAppearance.SetupWizardDescription" />
-
-</LinearLayout>
diff --git a/res/layout/setup_wifi_empty.xml b/res/layout/setup_wifi_empty.xml
deleted file mode 100644
index b1659d7..0000000
--- a/res/layout/setup_wifi_empty.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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.
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/setup_wizard_margin_top"
- android:paddingStart="@dimen/suw_layout_margin_sides"
- android:paddingEnd="@dimen/suw_layout_margin_sides"
- android:textAppearance="@style/TextAppearance.SetupWizardDescription" />
diff --git a/res/layout/setup_wifi_layout.xml b/res/layout/setup_wifi_layout.xml
deleted file mode 100644
index 62bb6a1..0000000
--- a/res/layout/setup_wifi_layout.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright 2015, 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.
--->
-
-<com.android.setupwizardlib.SetupWizardListLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:settings="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- settings:suwBackgroundTile="@drawable/setup_illustration_tile"
- settings:suwHeaderText="@string/wifi_setup_wizard_title"
- settings:suwIllustrationHorizontalTile="@drawable/setup_illustration_horizontal_tile"
- settings:suwIllustrationImage="@drawable/setup_illustration_wifi" />
diff --git a/res/layout/setup_wifi_mac_address.xml b/res/layout/setup_wifi_mac_address.xml
deleted file mode 100644
index 60f3212..0000000
--- a/res/layout/setup_wifi_mac_address.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 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="@dimen/setup_add_network_item_height"
- android:gravity="center_vertical"
- android:orientation="vertical"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:textDirection="locale">
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="@dimen/setup_list_no_icon_padding"
- android:text="@string/wifi_advanced_mac_address_title" />
-
- <TextView
- android:id="@+id/mac_address"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="@dimen/setup_list_no_icon_padding" />
-
-</LinearLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 2931a98..4b3dba9 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -40,14 +40,6 @@
<dimen name="crypt_clock_size">100sp</dimen>
- <dimen name="setup_add_network_item_height">56dp</dimen>
- <!-- Size of padding to give in the wifi list when there is no icon -->
- <dimen name="setup_list_no_icon_padding">56dp</dimen>
- <dimen name="setup_preference_icon_frame_margin_start">-4dp</dimen>
- <dimen name="setup_preference_icon_frame_padding_end">12dp</dimen>
- <dimen name="setup_preference_icon_frame_width">60dp</dimen>
- <dimen name="setup_wizard_margin_top">24dp</dimen>
-
<dimen name="divider_height">3dip</dimen>
<dimen name="divider_margin_top">6dip</dimen>
<dimen name="divider_margin_bottom">7dip</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4d872b1..3d7a777 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -866,6 +866,10 @@
<!-- Text shown when "Add fingerprint" button is disabled -->
<string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
+ <!-- Text shown when users has enrolled a maximum number of fingerprints [CHAR LIMIT=NONE] -->
+ <string name="fingerprint_intro_error_max">You\u2019ve added the maximum number of fingerprints</string>
+ <!-- Text shown when an unknown error caused the device to be unable to add fingerprints [CHAR LIMIT=NONE] -->
+ <string name="fingerprint_intro_error_unknown">Can\u2019t add more fingerprints</string>
<!-- Title shown in a dialog which asks the user to confirm when the last fingerprint gets deleted by him. [CHAR LIMIT=50]-->
<string name="fingerprint_last_delete_title">Remove all fingerprints?</string>
@@ -1471,9 +1475,6 @@
<!-- Bluetooth settings. Dock Setting Dialog - Remember setting and don't ask user again -->
<string name="bluetooth_dock_settings_remember">Remember settings</string>
- <!-- Wifi Assistant title. [CHAR LIMIT=40] -->
- <string name="wifi_assistant_title">Wi\u2011Fi Assistant</string>
-
<!-- Wifi Display settings. The title of the screen. [CHAR LIMIT=40] -->
<string name="wifi_display_settings_title">Cast</string>
<!-- Wifi Display settings. The title of a menu item to enable wireless display [CHAR LIMIT=40] -->
@@ -1568,8 +1569,6 @@
<string name="wifi_settings_title">Wi\u2011Fi</string>
<!-- Summary text of the Wi-fi settings screen -->
<string name="wifi_settings_summary">Set up & manage wireless access points</string>
- <!-- Used in the 1st-level settings screen to turn on Wi-Fi [CHAR LIMIT=60] -->
- <string name="wifi_setup_wizard_title">Select Wi\u2011Fi network</string>
<!-- Used by Account creation for turning on Wi-Fi [CHAR LIMIT=60] -->
<string name="wifi_select_network">Select Wi\u2011Fi</string>
<!-- Summary text when turning Wi-Fi or bluetooth on -->
@@ -1592,12 +1591,12 @@
<string name="wifi_poor_network_detection_summary">Don\u2019t use a Wi\u2011Fi network unless it has a good Internet connection</string>
<!-- Checkbox summary for option to toggle poor network detection [CHAR LIMIT=60] -->
<string name="wifi_avoid_poor_network_detection_summary">Only use networks that have a good Internet connection</string>
- <!-- Checkbox title for option to connect to open Wi-Fi automatically [CHAR LIMIT=40] -->
- <string name="wifi_automatically_connect_title">Use open Wi\u2011Fi automatically</string>
- <!-- Checkbox summary for option to connect to open Wi-Fi automatically [CHAR LIMIT=100] -->
- <string name="wifi_automatically_connect_summary">Let a Wi\u2011Fi assistant automatically connect to open networks determined to be high quality</string>
- <!-- Dialog title for option to select an app which connects to open Wi-Fi automatically [CHAR LIMIT=40] -->
- <string name="wifi_select_assistant_dialog_title">Choose assistant</string>
+
+ <!-- Network recommendations toggle -->
+ <!--TODO(jjoslin): Provide final strings and mark for translation. BUG: 32913919 -->
+ <string translatable="false" name="networking_allow_recommendations_title">Use network recommendations</string>
+ <string translatable="false" name="networking_allow_recommendations_summary">When enabled, use network recommendations when selecting the Wi\u2011Fi network to connect to</string>
+
<!-- Preference title for option to install certificates -->
<string name="wifi_install_credentials">Install certificates</string>
<!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off. The
@@ -1663,8 +1662,6 @@
<string name="wifi_empty_list_wifi_on">Searching for Wi\u2011Fi networks\u2026</string>
<!-- Wifi Settings. text displayed when user has restriction DISALLOW_CONFIG_WIFI [CHAR LIMIT=NONE]-->
<string name="wifi_empty_list_user_restricted">You don\u2019t have permission to change the Wi\u2011Fi network.</string>
- <!-- Wi-Fi settings. title for setup other network button [CHAR LIMIT=35]-->
- <string name="wifi_other_network">Add another network</string>
<!-- Wi-Fi settings. content description for more button [CHAR LIMIT=50]-->
<string name="wifi_more">More</string>
<!-- Wi-Fi settings. wps menu title [CHAR LIMIT=25]-->
@@ -1813,30 +1810,6 @@
<string name="wifi_failed_save_message">Failed to save network</string>
<!-- Button label to dismiss the dialog -->
<string name="wifi_cancel">Cancel</string>
- <!-- Button for skipping a step after having been warned of a potential concern [CHAR LIMIT=30] -->
- <string name="wifi_skip_anyway">Skip anyway</string>
- <!-- Button for going to the previous screen or step [CHAR LIMIT=20] -->
- <string name="wifi_dont_skip">Go back</string>
-
- <!-- Text warning about skipping Wi-Fi with a mobile connect (tablet) [CHAR LIMIT=NONE]-->
- <string name="wifi_skipped_message" product="tablet">WARNING: if you skip Wi\u2011Fi, your tablet will only use cellular data for initial downloads and updates. To avoid possible data charges, connect to Wi\u2011Fi.</string>
- <!-- Text warning about skipping Wi-Fi with a mobile connect (device) [CHAR LIMIT=NONE]-->
- <string name="wifi_skipped_message" product="device">WARNING: if you skip Wi\u2011Fi, your device will only use cellular data for initial downloads and updates. To avoid possible data charges, connect to Wi\u2011Fi.</string>
- <!-- Text warning about skipping Wi-Fi with a mobile connect (phone) [CHAR LIMIT=NONE]-->
- <string name="wifi_skipped_message" product="default">WARNING: if you skip Wi\u2011Fi, your phone will only use cellular data for initial downloads and updates. To avoid possible data charges, connect to Wi\u2011Fi.</string>
-
- <!-- Text warning about skipping Wi-Fi without a mobile connect (tablet) [CHAR LIMIT=NONE] -->
- <string name="wifi_and_mobile_skipped_message" product="tablet">If you skip Wi\u2011Fi:\n\n<li>Your tablet won\u2019t have an Internet connection.</li>\n\n<li>You won\u2019t get software updates until you connect to the Internet.</li>\n\n<li>You can\u2019t activate device protection features at this time.</li></string>
- <!-- Text warning about skipping Wi-Fi without a mobile connect (device) [CHAR LIMIT=NONE] -->
- <string name="wifi_and_mobile_skipped_message" product="device">If you skip Wi\u2011Fi:\n\n<li>Your device won\u2019t have an Internet connection.</li>\n\n<li>You won\u2019t get software updates until you connect to the Internet.</li>\n\n<li>You can\u2019t activate device protection features at this time.</li></string>
- <!-- Text warning about skipping Wi-Fi without a mobile connect (phone) [CHAR LIMIT=NONE] -->
- <string name="wifi_and_mobile_skipped_message" product="default">If you skip Wi\u2011Fi:\n\n<li>Your phone won\u2019t have an Internet connection.</li>\n\n<li>You won\u2019t get software updates until you connect to the Internet.</li>\n\n<li>You can\u2019t activate device protection features at this time.</li></string>
- <!-- Text alerting that Wi-Fi couldn't connect (tablet) [CHAR LIMIT=NONE] -->
- <string name="wifi_connect_failed_message" product="tablet">The tablet was unable to connect to this Wi\u2011Fi network.</string>
- <!-- Text alerting that Wi-Fi couldn't connect (device) [CHAR LIMIT=NONE] -->
- <string name="wifi_connect_failed_message" product="device">The device was unable to connect to this Wi\u2011Fi network.</string>
- <!-- Text alerting that Wi-Fi couldn't connect (phone) [CHAR LIMIT=NONE] -->
- <string name="wifi_connect_failed_message" product="default">The phone was unable to connect to this Wi\u2011Fi network.</string>
<!-- Wi-Fi Advanced Settings --> <skip />
<!-- Wi-Fi settings screen, Saved networks, settings section. This is a header shown above Saved networks wifi settings. [CHAR LIMIT=30] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index f4b39d4..ce7ddaa 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -140,9 +140,6 @@
<item name="android:scrollbarStyle">outsideOverlay</item>
</style>
- <style name="TextAppearance.SetupWizardDescription" parent="@android:style/TextAppearance.Material.Subhead">
- </style>
-
<style name="TrimmedHorizontalProgressBar" parent="android:Widget.Material.ProgressBar.Horizontal">
<item name="android:indeterminateDrawable">@drawable/progress_indeterminate_horizontal_material_trimmed</item>
<item name="android:minHeight">3dip</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index edc1dbf..02bf523 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -22,13 +22,6 @@
<attr name="side_margin" format="reference|dimension" />
<attr name="wifi_signal_color" format="reference" />
- <style name="SetupWizardDisableAppStartingTheme">
- <!-- Theme to disable the app starting window. The actual theme of the activity needs to
- be then set in code via setTheme or onApplyThemeResource. -->
- <item name="preferenceTheme">@style/PreferenceTheme.SetupWizard</item>
- <item name="android:windowBackground">@null</item>
- </style>
-
<style name="SetupWizardTheme" parent="SuwThemeGlif">
<!-- For all Alert Dialogs -->
<item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
diff --git a/res/xml/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml
index 863007c..53fda71 100644
--- a/res/xml/wifi_configure_settings.xml
+++ b/res/xml/wifi_configure_settings.xml
@@ -35,11 +35,10 @@
android:entries="@array/wifi_sleep_policy_entries"
android:entryValues="@array/wifi_sleep_policy_values" />
- <com.android.settings.AppListSwitchPreference
- android:key="wifi_assistant"
- android:title="@string/wifi_automatically_connect_title"
- android:summary="@string/wifi_automatically_connect_summary"
- android:dialogTitle="@string/wifi_select_assistant_dialog_title" />
+ <SwitchPreference
+ android:key="allow_recommendations"
+ android:title="@string/networking_allow_recommendations_title"
+ android:summary="@string/networking_allow_recommendations_summary"/>
<SwitchPreference
android:key="wifi_cellular_data_fallback"
diff --git a/src/com/android/settings/ActiveNetworkScorerDialog.java b/src/com/android/settings/ActiveNetworkScorerDialog.java
deleted file mode 100644
index ae04b58..0000000
--- a/src/com/android/settings/ActiveNetworkScorerDialog.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.settings;
-
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.NetworkScoreManager;
-import android.net.NetworkScorerAppManager;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
-
-/**
- * Dialog to allow a user to select a new network scorer.
- *
- * <p>Finishes with {@link #RESULT_CANCELED} in all circumstances unless the scorer is successfully
- * changed or was already set to the new value (in which case it finishes with {@link #RESULT_OK}).
- */
-public final class ActiveNetworkScorerDialog extends AlertActivity implements
- DialogInterface.OnClickListener {
- private static final String TAG = "ActiveNetScorerDlg";
-
- private String mNewPackageName;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Intent intent = getIntent();
- mNewPackageName = intent.getStringExtra(NetworkScoreManager.EXTRA_PACKAGE_NAME);
-
- if (!buildDialog()) {
- finish();
- }
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- switch (which) {
- case BUTTON_POSITIVE:
- NetworkScoreManager nsm =
- (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE);
- if (nsm.setActiveScorer(mNewPackageName)) {
- setResult(RESULT_OK);
- }
- break;
- case BUTTON_NEGATIVE:
- break;
- }
- }
-
- private boolean buildDialog() {
- // TOOD: http://b/23422763
- if (UserHandle.myUserId() != UserHandle.USER_SYSTEM) {
- Log.i(TAG, "Can only set scorer for owner/system user.");
- return false;
- }
- NetworkScorerAppManager networkScorerAppManager = new NetworkScorerAppManager(this);
- NetworkScorerAppData newScorer = networkScorerAppManager.getScorer(mNewPackageName);
- if (newScorer == null) {
- Log.e(TAG, "New package " + mNewPackageName + " is not a valid scorer.");
- return false;
- }
-
- NetworkScorerAppData oldScorer = networkScorerAppManager.getActiveScorer();
- if (oldScorer != null && TextUtils.equals(oldScorer.mPackageName, mNewPackageName)) {
- Log.i(TAG, "New package " + mNewPackageName + " is already the active scorer.");
- // Set RESULT_OK to indicate to the caller that the "switch" was successful.
- setResult(RESULT_OK);
- return false;
- }
-
- // Compose dialog.
- CharSequence newName = newScorer.mScorerName;
- final AlertController.AlertParams p = mAlertParams;
- p.mTitle = getString(R.string.network_scorer_change_active_dialog_title);
- if (oldScorer != null) {
- p.mMessage = getString(R.string.network_scorer_change_active_dialog_text, newName,
- oldScorer.mScorerName);
- } else {
- p.mMessage = getString(R.string.network_scorer_change_active_no_previous_dialog_text,
- newName);
- }
- p.mPositiveButtonText = getString(R.string.yes);
- p.mNegativeButtonText = getString(R.string.no);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonListener = this;
- setupAlert();
-
- return true;
- }
-}
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index eeb4779..ddf0dec 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -1164,7 +1164,7 @@
void setImsConfigProvisionedState(int configItem, boolean state) {
if (phone != null && mImsManager != null) {
- QueuedWork.singleThreadExecutor().submit(new Runnable() {
+ QueuedWork.queue(new Runnable() {
public void run() {
try {
mImsManager.getConfigInterface().setProvisionedValue(
@@ -1174,7 +1174,7 @@
Log.e(TAG, "setImsConfigProvisioned() exception:", e);
}
}
- });
+ }, false);
}
}
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 5f42579..ee500a9 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -48,6 +48,7 @@
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.instrumentation.Instrumentable;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.widget.FooterPreferenceMixin;
import com.android.settingslib.HelpUtils;
import java.util.UUID;
@@ -70,6 +71,9 @@
private static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted";
+ protected final FooterPreferenceMixin mFooterPreferenceMixin =
+ new FooterPreferenceMixin(this, getLifecycle());
+
private SettingsDialogFragment mDialogFragment;
private String mHelpUri;
@@ -123,7 +127,6 @@
private LayoutPreference mHeader;
- private LayoutPreference mFooter;
private View mEmptyView;
private LinearLayoutManager mLayoutManager;
private HighlightablePreferenceGroupAdapter mAdapter;
@@ -277,10 +280,6 @@
return mHeader;
}
- public LayoutPreference getFooterView() {
- return mFooter;
- }
-
protected void setHeaderView(int resource) {
mHeader = new LayoutPreference(getPrefContext(), resource);
addPreferenceToTop(mHeader);
@@ -298,29 +297,6 @@
}
}
- protected void setFooterView(int resource) {
- setFooterView(resource != 0 ? new LayoutPreference(getPrefContext(), resource) : null);
- }
-
- protected void setFooterView(View v) {
- setFooterView(v != null ? new LayoutPreference(getPrefContext(), v) : null);
- }
-
- private void setFooterView(LayoutPreference footer) {
- if (getPreferenceScreen() != null && mFooter != null) {
- getPreferenceScreen().removePreference(mFooter);
- }
- if (footer != null) {
- mFooter = footer;
- mFooter.setOrder(ORDER_LAST);
- if (getPreferenceScreen() != null) {
- getPreferenceScreen().addPreference(mFooter);
- }
- } else {
- mFooter = null;
- }
- }
-
@Override
public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
if (preferenceScreen != null && !preferenceScreen.isAttached()) {
@@ -332,9 +308,6 @@
if (mHeader != null) {
preferenceScreen.addPreference(mHeader);
}
- if (mFooter != null) {
- preferenceScreen.addPreference(mFooter);
- }
}
}
@@ -343,7 +316,7 @@
if (getPreferenceScreen() != null) {
boolean show = (getPreferenceScreen().getPreferenceCount()
- (mHeader != null ? 1 : 0)
- - (mFooter != null ? 1 : 0)) <= 0;
+ - (mFooterPreferenceMixin.hasFooter() ? 1 : 0)) <= 0;
mEmptyView.setVisibility(show ? View.VISIBLE : View.GONE);
} else {
mEmptyView.setVisibility(View.VISIBLE);
diff --git a/src/com/android/settings/SetupWizardUtils.java b/src/com/android/settings/SetupWizardUtils.java
index 5563c3b..a0a3719 100644
--- a/src/com/android/settings/SetupWizardUtils.java
+++ b/src/com/android/settings/SetupWizardUtils.java
@@ -16,11 +16,8 @@
package com.android.settings;
-import android.app.Activity;
-import android.app.Dialog;
import android.content.Intent;
-import com.android.setupwizardlib.util.SystemBarHelper;
import com.android.setupwizardlib.util.WizardManagerHelper;
public class SetupWizardUtils {
@@ -41,22 +38,6 @@
}
}
- /**
- * Sets the immersive mode related flags based on the extra in the intent which started the
- * activity.
- */
- public static void setImmersiveMode(Activity activity) {
- final boolean useImmersiveMode = activity.getIntent().getBooleanExtra(
- WizardManagerHelper.EXTRA_USE_IMMERSIVE_MODE, false);
- if (useImmersiveMode) {
- SystemBarHelper.hideSystemBars(activity.getWindow());
- }
- }
-
- public static void applyImmersiveFlags(final Dialog dialog) {
- SystemBarHelper.hideSystemBars(dialog);
- }
-
public static void copySetupExtras(Intent fromIntent, Intent toIntent) {
toIntent.putExtra(WizardManagerHelper.EXTRA_THEME,
fromIntent.getStringExtra(WizardManagerHelper.EXTRA_THEME));
diff --git a/src/com/android/settings/applications/ApplicationFeatureProvider.java b/src/com/android/settings/applications/ApplicationFeatureProvider.java
index 8c7b257..bb0fd4c 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProvider.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProvider.java
@@ -35,7 +35,7 @@
/**
* Callback that receives the total number of packages installed on the device.
*/
- public interface NumberOfInstalledAppsCallback {
+ interface NumberOfInstalledAppsCallback {
void onNumberOfInstalledAppsResult(int num);
}
}
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index a967abf..1dd0471 100644
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -50,6 +50,7 @@
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
+import com.android.settings.widget.FooterPreference;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
@@ -97,7 +98,7 @@
// accessed from inner class (not private to avoid thunks)
- Preference mMyDevicePreference;
+ FooterPreference mMyDevicePreference;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@@ -120,7 +121,7 @@
final Resources res = context.getResources();
final Locale locale = res.getConfiguration().getLocales().get(0);
final BidiFormatter bidiFormatter = BidiFormatter.getInstance(locale);
- mMyDevicePreference.setSummary(res.getString(
+ mMyDevicePreference.setTitle(res.getString(
R.string.bluetooth_is_visible_message,
bidiFormatter.unicodeWrap(mLocalAdapter.getName())));
}
@@ -171,10 +172,8 @@
mAvailableDevicesCategory.setOrder(2);
getPreferenceScreen().addPreference(mAvailableDevicesCategory);
- mMyDevicePreference = new Preference(getPrefContext());
+ mMyDevicePreference = mFooterPreferenceMixin.createFooterPreference();
mMyDevicePreference.setSelectable(false);
- mMyDevicePreference.setOrder(3);
- getPreferenceScreen().addPreference(mMyDevicePreference);
setHasOptionsMenu(true);
}
@@ -356,7 +355,7 @@
final Resources res = getResources();
final Locale locale = res.getConfiguration().getLocales().get(0);
final BidiFormatter bidiFormatter = BidiFormatter.getInstance(locale);
- mMyDevicePreference.setSummary(res.getString(
+ mMyDevicePreference.setTitle(res.getString(
R.string.bluetooth_is_visible_message,
bidiFormatter.unicodeWrap(mLocalAdapter.getName())));
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java b/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
index 401b13c..6150920 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
@@ -150,7 +150,7 @@
static void persistDiscoveringTimestamp(final Context context) {
// Load the shared preferences and edit it on a background
// thread (but serialized!).
- QueuedWork.singleThreadExecutor().submit(new Runnable() {
+ QueuedWork.queue(new Runnable() {
public void run() {
SharedPreferences.Editor editor = getSharedPreferences(context).edit();
editor.putLong(
@@ -158,7 +158,7 @@
System.currentTimeMillis());
editor.apply();
}
- });
+ }, false);
}
static boolean hasDockAutoConnectSetting(Context context, String addr) {
diff --git a/src/com/android/settings/core/InstrumentedPreferenceFragment.java b/src/com/android/settings/core/InstrumentedPreferenceFragment.java
index 1724d0c..3a4d0c2 100644
--- a/src/com/android/settings/core/InstrumentedPreferenceFragment.java
+++ b/src/com/android/settings/core/InstrumentedPreferenceFragment.java
@@ -17,13 +17,21 @@
package com.android.settings.core;
import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import com.android.settings.core.instrumentation.Instrumentable;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
import com.android.settings.core.lifecycle.ObservablePreferenceFragment;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.PreferenceDividerDecoration;
+import com.android.settings.survey.SurveyMixin;
/**
* Instrumented fragment that logs visibility state.
@@ -48,9 +56,13 @@
protected final int GESTURE_DOUBLE_TAP_SCREEN = PLACEHOLDER_METRIC + 11;
protected final int GESTURE_DOUBLE_TWIST = PLACEHOLDER_METRIC + 12;
+ private final PreferenceDividerDecoration mDividerDecoration =
+ new PreferenceDividerDecoration();
+
public InstrumentedPreferenceFragment() {
// Mixin that logs visibility change for activity.
getLifecycle().addObserver(new VisibilityLoggerMixin(getMetricsCategory()));
+ getLifecycle().addObserver(new SurveyMixin(this, getClass().getSimpleName()));
}
@Override
@@ -60,6 +72,20 @@
}
@Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final View view = super.onCreateView(inflater, container, savedInstanceState);
+ getListView().addItemDecoration(mDividerDecoration);
+ return view;
+ }
+
+ @Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
}
+
+ @Override
+ public void setDivider(Drawable divider) {
+ mDividerDecoration.setDivider(divider);
+ super.setDivider(new ColorDrawable(Color.TRANSPARENT));
+ }
}
diff --git a/src/com/android/settings/core/PreferenceController.java b/src/com/android/settings/core/PreferenceController.java
index 8f551de..01c998a 100644
--- a/src/com/android/settings/core/PreferenceController.java
+++ b/src/com/android/settings/core/PreferenceController.java
@@ -20,6 +20,7 @@
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.search.SearchIndexableRaw;
+import com.android.settings.search2.ResultPayload;
import java.util.List;
@@ -104,4 +105,11 @@
screen.removePreference(pref);
}
}
+
+ /**
+ * @return the {@link ResultPayload} corresponding to the search result type for the preference.
+ */
+ public ResultPayload getResultPayload() {
+ return null;
+ }
}
diff --git a/src/com/android/settings/core/lifecycle/Lifecycle.java b/src/com/android/settings/core/lifecycle/Lifecycle.java
index c47f97e..9a42cd9 100644
--- a/src/com/android/settings/core/lifecycle/Lifecycle.java
+++ b/src/com/android/settings/core/lifecycle/Lifecycle.java
@@ -18,6 +18,7 @@
import android.annotation.UiThread;
import android.content.Context;
import android.os.Bundle;
+import android.support.v7.preference.PreferenceScreen;
import com.android.settings.core.lifecycle.events.OnAttach;
import com.android.settings.core.lifecycle.events.OnCreate;
@@ -27,6 +28,7 @@
import com.android.settings.core.lifecycle.events.OnSaveInstanceState;
import com.android.settings.core.lifecycle.events.OnStart;
import com.android.settings.core.lifecycle.events.OnStop;
+import com.android.settings.core.lifecycle.events.SetPreferenceScreen;
import com.android.settings.utils.ThreadUtils;
import java.util.ArrayList;
@@ -73,6 +75,14 @@
}
}
+ public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+ for (LifecycleObserver observer : mObservers) {
+ if (observer instanceof SetPreferenceScreen) {
+ ((SetPreferenceScreen) observer).setPreferenceScreen(preferenceScreen);
+ }
+ }
+ }
+
public void onResume() {
for (LifecycleObserver observer : mObservers) {
if (observer instanceof OnResume) {
diff --git a/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java b/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java
index f55b183..0a1a628 100644
--- a/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java
+++ b/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.os.Bundle;
import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.PreferenceScreen;
/**
* {@link PreferenceFragment} that has hooks to observe fragment lifecycle events.
@@ -46,6 +47,12 @@
super.onCreate(savedInstanceState);
}
+ @Override
+ public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+ mLifecycle.setPreferenceScreen(preferenceScreen);
+ super.setPreferenceScreen(preferenceScreen);
+ }
+
@CallSuper
@Override
public void onSaveInstanceState(Bundle outState) {
diff --git a/src/com/android/settings/core/lifecycle/events/SetPreferenceScreen.java b/src/com/android/settings/core/lifecycle/events/SetPreferenceScreen.java
new file mode 100644
index 0000000..d206ed3
--- /dev/null
+++ b/src/com/android/settings/core/lifecycle/events/SetPreferenceScreen.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.core.lifecycle.events;
+
+import android.support.v7.preference.PreferenceScreen;
+
+public interface SetPreferenceScreen {
+
+ void setPreferenceScreen(PreferenceScreen preferenceScreen);
+}
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index e59b7ba..ab1ec13 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -17,9 +17,6 @@
import android.app.Activity;
import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
@@ -118,16 +115,6 @@
}
@Override
- public void setDivider(Drawable divider) {
- if (mDashboardFeatureProvider.isEnabled()) {
- // Intercept divider and set it transparent so system divider decoration is disabled.
- super.setDivider(new ColorDrawable(Color.TRANSPARENT));
- } else {
- super.setDivider(divider);
- }
- }
-
- @Override
public void onStart() {
super.onStart();
final DashboardCategory category =
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
index bbaf54c..551564d 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
@@ -52,6 +52,7 @@
private UserManager mUserManager;
private boolean mHasPassword;
private boolean mFingerprintUnlockDisabledByAdmin;
+ private TextView mErrorText;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -67,13 +68,41 @@
setHeaderText(R.string.security_settings_fingerprint_enroll_introduction_title);
}
- final Button cancelButton = (Button) findViewById(R.id.fingerprint_cancel_button);
+ Button cancelButton = (Button) findViewById(R.id.fingerprint_cancel_button);
cancelButton.setOnClickListener(this);
+ mErrorText = (TextView) findViewById(R.id.error_text);
+
mUserManager = UserManager.get(this);
updatePasswordQuality();
}
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(this);
+ int errorMsg = 0;
+ if (fingerprintManager != null) {
+ final int max = getResources().getInteger(
+ com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
+ final int numEnrolledFingerprints =
+ fingerprintManager.getEnrolledFingerprints(mUserId).size();
+ if (numEnrolledFingerprints >= max) {
+ errorMsg = R.string.fingerprint_intro_error_max;
+ }
+ } else {
+ errorMsg = R.string.fingerprint_intro_error_unknown;
+ }
+ if (errorMsg == 0) {
+ mErrorText.setText(null);
+ getNextButton().setVisibility(View.VISIBLE);
+ } else {
+ mErrorText.setText(errorMsg);
+ getNextButton().setVisibility(View.GONE);
+ }
+ }
+
private void updatePasswordQuality() {
final int passwordQuality = new ChooseLockSettingsHelper(this).utils()
.getActivePasswordQuality(mUserManager.getCredentialOwnerProfile(mUserId));
diff --git a/src/com/android/settings/fingerprint/FingerprintSettings.java b/src/com/android/settings/fingerprint/FingerprintSettings.java
index 58060f3..0f48f8c 100644
--- a/src/com/android/settings/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/fingerprint/FingerprintSettings.java
@@ -17,7 +17,6 @@
package com.android.settings.fingerprint;
-import android.annotation.Nullable;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -26,7 +25,6 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.hardware.fingerprint.Fingerprint;
@@ -49,15 +47,12 @@
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
-import android.text.method.LinkMovementMethod;
import android.text.style.URLSpan;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
-import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -68,6 +63,8 @@
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.widget.FooterPreference;
+import com.android.settings.widget.FooterPreferenceMixin;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.RestrictedLockUtils;
@@ -298,21 +295,14 @@
mLaunchedConfirm = true;
launchChooseOrConfirmLock();
}
- }
- @Override
- public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- TextView v = (TextView) LayoutInflater.from(view.getContext()).inflate(
- R.layout.fingerprint_settings_footer, null);
- EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
- getActivity(), DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId);
- v.setText(LearnMoreSpan.linkify(getText(admin != null
+ final FooterPreference pref = mFooterPreferenceMixin.createFooterPreference();
+ final EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ activity, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+ pref.setTitle(LearnMoreSpan.linkify(getText(admin != null
? R.string.security_settings_fingerprint_enroll_disclaimer_lockscreen_disabled
: R.string.security_settings_fingerprint_enroll_disclaimer),
getString(getHelpResource()), admin));
- v.setMovementMethod(new LinkMovementMethod());
- setFooterView(v);
}
protected void removeFingerprintPreference(int fingerprintId) {
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java
index 0e4501c..2c44f6d 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java
@@ -19,7 +19,6 @@
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.DialogFragment;
import android.app.FragmentManager;
import android.content.DialogInterface;
import android.content.Intent;
@@ -93,7 +92,7 @@
.setTitle(R.string.setup_fingerprint_enroll_enrolling_skip_title)
.setMessage(R.string.setup_fingerprint_enroll_enrolling_skip_message)
.setCancelable(false)
- .setPositiveButton(R.string.wifi_skip_anyway,
+ .setPositiveButton(R.string.skip_anyway_button_label,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
@@ -104,7 +103,7 @@
}
}
})
- .setNegativeButton(R.string.wifi_dont_skip,
+ .setNegativeButton(R.string.go_back_button_label,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
diff --git a/src/com/android/settings/notification/AudioHelper.java b/src/com/android/settings/notification/AudioHelper.java
index ea5bc4a..07cd912 100644
--- a/src/com/android/settings/notification/AudioHelper.java
+++ b/src/com/android/settings/notification/AudioHelper.java
@@ -16,8 +16,12 @@
package com.android.settings.notification;
+import android.annotation.UserIdInt;
import android.content.Context;
import android.media.AudioSystem;
+import android.os.UserHandle;
+import android.os.UserManager;
+import com.android.settings.Utils;
/**
* Helper class to wrap API for testing
@@ -34,4 +38,11 @@
return AudioSystem.isSingleVolume(mContext);
}
+ public int getManagedProfileId(UserManager um) {
+ return Utils.getManagedProfileId(um, UserHandle.myUserId());
+ }
+
+ public Context createPackageContextAsUser(@UserIdInt int profileId) {
+ return Utils.createPackageContextAsUser(mContext, profileId);
+ }
}
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index 9166377..5f53d9a 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -16,45 +16,26 @@
package com.android.settings.notification;
-import android.annotation.UserIdInt;
import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.FragmentManager;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
-import android.media.AudioSystem;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.preference.SeekBarVolumizer;
import android.provider.SearchIndexableResource;
-import android.provider.Settings;
import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceGroup;
-import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.support.v7.preference.TwoStatePreference;
import android.text.TextUtils;
-import android.util.Log;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.RingtonePreference;
-import com.android.settings.DefaultRingtonePreference;
-import com.android.settings.Utils;
import com.android.settings.core.PreferenceController;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
@@ -66,16 +47,9 @@
import java.util.Arrays;
import java.util.List;
-public class SoundSettings extends DashboardFragment
- implements OnPreferenceChangeListener {
+public class SoundSettings extends DashboardFragment {
private static final String TAG = "SoundSettings";
- private static final String KEY_WORK_CATEGORY = "sound_work_settings_section";
- private static final String KEY_WORK_USE_PERSONAL_SOUNDS = "work_use_personal_sounds";
- private static final String KEY_WORK_PHONE_RINGTONE = "work_ringtone";
- private static final String KEY_WORK_NOTIFICATION_RINGTONE = "work_notification_ringtone";
- private static final String KEY_WORK_ALARM_RINGTONE = "work_alarm_ringtone";
-
private static final String SELECTED_PREFERENCE_KEY = "selected_preference";
private static final int REQUEST_CODE = 200;
@@ -84,20 +58,9 @@
private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback();
private final H mHandler = new H();
- private Context mContext;
- private boolean mVoiceCapable;
-
- private PreferenceGroup mWorkPreferenceCategory;
- private TwoStatePreference mWorkUsePersonalSounds;
- private Preference mWorkPhoneRingtonePreference;
- private Preference mWorkNotificationRingtonePreference;
- private Preference mWorkAlarmRingtonePreference;
-
- private UserManager mUserManager;
+ private WorkSoundPreferenceController mWorkSoundController;
private RingtonePreference mRequestPreference;
- private @UserIdInt int mManagedProfileId;
-
@Override
public int getMetricsCategory() {
return MetricsEvent.SOUND;
@@ -106,10 +69,6 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mContext = getActivity();
- mUserManager = UserManager.get(getContext());
- mVoiceCapable = Utils.isVoiceCapable(mContext);
-
if (savedInstanceState != null) {
String selectedPreference = savedInstanceState.getString(SELECTED_PREFERENCE_KEY, null);
if (!TextUtils.isEmpty(selectedPreference)) {
@@ -119,25 +78,6 @@
}
@Override
- public void onResume() {
- super.onResume();
-
- mManagedProfileId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
- if (mManagedProfileId != UserHandle.USER_NULL && shouldShowRingtoneSettings()) {
- if ((mWorkPreferenceCategory == null)) {
- // Work preferences not yet set
- addPreferencesFromResource(R.xml.sound_work_settings);
- initWorkPreferences();
- }
- if (!mWorkUsePersonalSounds.isChecked()) {
- updateWorkRingtoneSummaries();
- }
- } else {
- maybeRemoveWorkPreferences();
- }
- }
-
- @Override
public void onPause() {
super.onPause();
mVolumeCallback.stopSample();
@@ -190,6 +130,10 @@
controllers.add(new AlarmRingtonePreferenceController(context));
controllers.add(new NotificationRingtonePreferenceController(context));
+ // === Work Sound Settings ===
+ mWorkSoundController = new WorkSoundPreferenceController(context, this, getLifecycle());
+ controllers.add(mWorkSoundController);
+
return controllers;
}
@@ -209,33 +153,6 @@
}
}
- /**
- * Updates the summary of work preferences
- *
- * This fragment only listens to changes on the work ringtone preferences, identified by keys
- * "work_ringtone", "work_notification_ringtone" and "work_alarm_ringtone".
- *
- * Note: Changes to the personal ringtones aren't listened to this way because they were already
- * handled using a {@link #SettingsObserver} ContentObserver. This wouldn't be appropriate for
- * work settings since the Settings app runs on the personal user.
- */
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- int ringtoneType;
- if (KEY_WORK_PHONE_RINGTONE.equals(preference.getKey())) {
- ringtoneType = RingtoneManager.TYPE_RINGTONE;
- } else if (KEY_WORK_NOTIFICATION_RINGTONE.equals(preference.getKey())) {
- ringtoneType = RingtoneManager.TYPE_NOTIFICATION;
- } else if (KEY_WORK_ALARM_RINGTONE.equals(preference.getKey())) {
- ringtoneType = RingtoneManager.TYPE_ALARM;
- } else {
- return true;
- }
-
- preference.setSummary(updateRingtoneName(getManagedProfileContext(), ringtoneType));
- return true;
- }
-
// === Volumes ===
final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback {
@@ -265,23 +182,6 @@
}
};
-
- // === Phone & notification ringtone ===
-
- private boolean shouldShowRingtoneSettings() {
- return !AudioSystem.isSingleVolume(mContext);
- }
-
- private static CharSequence updateRingtoneName(Context context, int type) {
- if (context == null) {
- Log.e(TAG, "Unable to update ringtone name, no context provided");
- return null;
- }
- Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context, type);
- return Ringtone.getTitle(context, ringtoneUri, false /* followSettingsUri */,
- true /* allowRemote */);
- }
-
// === Callbacks ===
@@ -393,149 +293,9 @@
// === Work Sound Settings ===
- private Context getManagedProfileContext() {
- if (mManagedProfileId == UserHandle.USER_NULL) {
- return null;
- }
- return Utils.createPackageContextAsUser(mContext, mManagedProfileId);
- }
-
- private DefaultRingtonePreference initWorkPreference(String key) {
- DefaultRingtonePreference pref =
- (DefaultRingtonePreference) getPreferenceScreen().findPreference(key);
- pref.setOnPreferenceChangeListener(this);
-
- // Required so that RingtonePickerActivity lists the work profile ringtones
- pref.setUserId(mManagedProfileId);
- return pref;
- }
-
- private void initWorkPreferences() {
- mWorkPreferenceCategory = (PreferenceGroup) getPreferenceScreen()
- .findPreference(KEY_WORK_CATEGORY);
- mWorkUsePersonalSounds = (TwoStatePreference) getPreferenceScreen()
- .findPreference(KEY_WORK_USE_PERSONAL_SOUNDS);
- mWorkPhoneRingtonePreference = initWorkPreference(KEY_WORK_PHONE_RINGTONE);
- mWorkNotificationRingtonePreference = initWorkPreference(KEY_WORK_NOTIFICATION_RINGTONE);
- mWorkAlarmRingtonePreference = initWorkPreference(KEY_WORK_ALARM_RINGTONE);
-
- if (!mVoiceCapable) {
- mWorkPreferenceCategory.removePreference(mWorkPhoneRingtonePreference);
- mWorkPhoneRingtonePreference = null;
- }
-
- Context managedProfileContext = getManagedProfileContext();
- if (Settings.Secure.getIntForUser(managedProfileContext.getContentResolver(),
- Settings.Secure.SYNC_PARENT_SOUNDS, 0, mManagedProfileId) == 1) {
- enableWorkSyncSettings();
- } else {
- disableWorkSyncSettings();
- }
-
- mWorkUsePersonalSounds.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if ((boolean) newValue) {
- UnifyWorkDialogFragment.show(SoundSettings.this);
- return false;
- } else {
- disableWorkSync();
- return true;
- }
- }
- });
- }
-
- private void enableWorkSync() {
- RingtoneManager.enableSyncFromParent(getManagedProfileContext());
- enableWorkSyncSettings();
- }
-
- private void enableWorkSyncSettings() {
- mWorkUsePersonalSounds.setChecked(true);
-
- if (mWorkPhoneRingtonePreference != null) {
- mWorkPhoneRingtonePreference.setSummary(R.string.work_sound_same_as_personal);
- }
- mWorkNotificationRingtonePreference.setSummary(R.string.work_sound_same_as_personal);
- mWorkAlarmRingtonePreference.setSummary(R.string.work_sound_same_as_personal);
- }
-
- private void disableWorkSync() {
- RingtoneManager.disableSyncFromParent(getManagedProfileContext());
- disableWorkSyncSettings();
- }
-
- private void disableWorkSyncSettings() {
- if (mWorkPhoneRingtonePreference != null) {
- mWorkPhoneRingtonePreference.setEnabled(true);
- }
- mWorkNotificationRingtonePreference.setEnabled(true);
- mWorkAlarmRingtonePreference.setEnabled(true);
-
- updateWorkRingtoneSummaries();
- }
-
- private void updateWorkRingtoneSummaries() {
- Context managedProfileContext = getManagedProfileContext();
-
- if (mWorkPhoneRingtonePreference != null) {
- mWorkPhoneRingtonePreference.setSummary(
- updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_RINGTONE));
- }
- mWorkNotificationRingtonePreference.setSummary(
- updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_NOTIFICATION));
- mWorkAlarmRingtonePreference.setSummary(
- updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_ALARM));
- }
-
- private void maybeRemoveWorkPreferences() {
- if (mWorkPreferenceCategory == null) {
- // No work preferences to remove
- return;
- }
- getPreferenceScreen().removePreference(mWorkPreferenceCategory);
- mWorkPreferenceCategory = null;
- mWorkPhoneRingtonePreference = null;
- mWorkNotificationRingtonePreference = null;
- mWorkAlarmRingtonePreference = null;
- }
-
- public static class UnifyWorkDialogFragment extends InstrumentedDialogFragment
- implements DialogInterface.OnClickListener {
- private static final String TAG = "UnifyWorkDialogFragment";
- private static final int REQUEST_CODE = 200;
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.DIALOG_UNIFY_SOUND_SETTINGS;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- return new AlertDialog.Builder(getActivity())
- .setTitle(R.string.work_sync_dialog_title)
- .setMessage(R.string.work_sync_dialog_message)
- .setPositiveButton(R.string.work_sync_dialog_yes, UnifyWorkDialogFragment.this)
- .setNegativeButton(android.R.string.no, null)
- .create();
- }
-
- public static void show(SoundSettings parent) {
- FragmentManager fm = parent.getFragmentManager();
- if (fm.findFragmentByTag(TAG) == null) {
- UnifyWorkDialogFragment fragment = new UnifyWorkDialogFragment();
- fragment.setTargetFragment(parent, REQUEST_CODE);
- fragment.show(fm, TAG);
- }
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- SoundSettings soundSettings = (SoundSettings) getTargetFragment();
- if (soundSettings.isAdded()) {
- soundSettings.enableWorkSync();
- }
+ void enableWorkSync() {
+ if (mWorkSoundController != null) {
+ mWorkSoundController.enableWorkSync();
}
}
}
diff --git a/src/com/android/settings/notification/WorkSoundPreferenceController.java b/src/com/android/settings/notification/WorkSoundPreferenceController.java
new file mode 100644
index 0000000..cc671ad
--- /dev/null
+++ b/src/com/android/settings/notification/WorkSoundPreferenceController.java
@@ -0,0 +1,319 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.notification;
+
+import android.annotation.UserIdInt;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.media.AudioSystem;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.TwoStatePreference;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.DefaultRingtonePreference;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnResume;
+
+
+public class WorkSoundPreferenceController extends PreferenceController implements
+ OnPreferenceChangeListener, LifecycleObserver, OnResume {
+
+ private static final String TAG = "WorkSoundPrefController";
+ private static final String KEY_WORK_CATEGORY = "sound_work_settings_section";
+ private static final String KEY_WORK_USE_PERSONAL_SOUNDS = "work_use_personal_sounds";
+ private static final String KEY_WORK_PHONE_RINGTONE = "work_ringtone";
+ private static final String KEY_WORK_NOTIFICATION_RINGTONE = "work_notification_ringtone";
+ private static final String KEY_WORK_ALARM_RINGTONE = "work_alarm_ringtone";
+
+ private PreferenceGroup mWorkPreferenceCategory;
+ private TwoStatePreference mWorkUsePersonalSounds;
+ private Preference mWorkPhoneRingtonePreference;
+ private Preference mWorkNotificationRingtonePreference;
+ private Preference mWorkAlarmRingtonePreference;
+ private boolean mVoiceCapable;
+ private UserManager mUserManager;
+ private SoundSettings mParent;
+ private AudioHelper mHelper;
+
+ private @UserIdInt
+ int mManagedProfileId;
+
+ public WorkSoundPreferenceController(Context context, SoundSettings parent,
+ Lifecycle lifecycle) {
+ this(context, parent, lifecycle, new AudioHelper(context));
+ }
+
+ @VisibleForTesting
+ WorkSoundPreferenceController(Context context, SoundSettings parent, Lifecycle lifecycle,
+ AudioHelper helper) {
+ super(context);
+ mUserManager = UserManager.get(context);
+ mVoiceCapable = Utils.isVoiceCapable(mContext);
+ mParent = parent;
+ mHelper = helper;
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ // do nothing
+ }
+
+ @Override
+ public void onResume() {
+ if (isAvailable()) {
+ if ((mWorkPreferenceCategory == null)) {
+ // Work preferences not yet set
+ mParent.addPreferencesFromResource(R.xml.sound_work_settings);
+ initWorkPreferences();
+ }
+ if (!mWorkUsePersonalSounds.isChecked()) {
+ updateWorkRingtoneSummaries();
+ }
+ } else {
+ maybeRemoveWorkPreferences();
+ }
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_WORK_CATEGORY;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ mManagedProfileId = mHelper.getManagedProfileId(mUserManager);
+ return mManagedProfileId != UserHandle.USER_NULL && shouldShowRingtoneSettings();
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ return false;
+ }
+
+ /**
+ * Updates the summary of work preferences
+ *
+ * This controller listens to changes on the work ringtone preferences, identified by keys
+ * "work_ringtone", "work_notification_ringtone" and "work_alarm_ringtone".
+ */
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ int ringtoneType;
+ if (KEY_WORK_PHONE_RINGTONE.equals(preference.getKey())) {
+ ringtoneType = RingtoneManager.TYPE_RINGTONE;
+ } else if (KEY_WORK_NOTIFICATION_RINGTONE.equals(preference.getKey())) {
+ ringtoneType = RingtoneManager.TYPE_NOTIFICATION;
+ } else if (KEY_WORK_ALARM_RINGTONE.equals(preference.getKey())) {
+ ringtoneType = RingtoneManager.TYPE_ALARM;
+ } else {
+ return true;
+ }
+
+ preference.setSummary(updateRingtoneName(getManagedProfileContext(), ringtoneType));
+ return true;
+ }
+
+ // === Phone & notification ringtone ===
+
+ private boolean shouldShowRingtoneSettings() {
+ return !mHelper.isSingleVolume();
+ }
+
+ private CharSequence updateRingtoneName(Context context, int type) {
+ if (context == null) {
+ Log.e(TAG, "Unable to update ringtone name, no context provided");
+ return null;
+ }
+ Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context, type);
+ return Ringtone.getTitle(context, ringtoneUri, false /* followSettingsUri */,
+ true /* allowRemote */);
+ }
+
+ private Context getManagedProfileContext() {
+ if (mManagedProfileId == UserHandle.USER_NULL) {
+ return null;
+ }
+ return mHelper.createPackageContextAsUser(mManagedProfileId);
+ }
+
+ private DefaultRingtonePreference initWorkPreference(String key) {
+ DefaultRingtonePreference pref =
+ (DefaultRingtonePreference) mParent.getPreferenceScreen().findPreference(key);
+ pref.setOnPreferenceChangeListener(this);
+
+ // Required so that RingtonePickerActivity lists the work profile ringtones
+ pref.setUserId(mManagedProfileId);
+ return pref;
+ }
+
+ private void initWorkPreferences() {
+ mWorkPreferenceCategory = (PreferenceGroup) mParent.getPreferenceScreen()
+ .findPreference(KEY_WORK_CATEGORY);
+ mWorkUsePersonalSounds = (TwoStatePreference) mParent.getPreferenceScreen()
+ .findPreference(KEY_WORK_USE_PERSONAL_SOUNDS);
+ mWorkPhoneRingtonePreference = initWorkPreference(KEY_WORK_PHONE_RINGTONE);
+ mWorkNotificationRingtonePreference = initWorkPreference(KEY_WORK_NOTIFICATION_RINGTONE);
+ mWorkAlarmRingtonePreference = initWorkPreference(KEY_WORK_ALARM_RINGTONE);
+
+ if (!mVoiceCapable) {
+ mWorkPreferenceCategory.removePreference(mWorkPhoneRingtonePreference);
+ mWorkPhoneRingtonePreference = null;
+ }
+
+ Context managedProfileContext = getManagedProfileContext();
+ if (Settings.Secure.getIntForUser(managedProfileContext.getContentResolver(),
+ Settings.Secure.SYNC_PARENT_SOUNDS, 0, mManagedProfileId) == 1) {
+ enableWorkSyncSettings();
+ } else {
+ disableWorkSyncSettings();
+ }
+
+ mWorkUsePersonalSounds.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if ((boolean) newValue) {
+ UnifyWorkDialogFragment.show(mParent);
+ return false;
+ } else {
+ disableWorkSync();
+ return true;
+ }
+ }
+ });
+ }
+
+ void enableWorkSync() {
+ RingtoneManager.enableSyncFromParent(getManagedProfileContext());
+ enableWorkSyncSettings();
+ }
+
+ private void enableWorkSyncSettings() {
+ mWorkUsePersonalSounds.setChecked(true);
+
+ if (mWorkPhoneRingtonePreference != null) {
+ mWorkPhoneRingtonePreference.setSummary(
+ com.android.settings.R.string.work_sound_same_as_personal);
+ }
+ mWorkNotificationRingtonePreference.setSummary(
+ com.android.settings.R.string.work_sound_same_as_personal);
+ mWorkAlarmRingtonePreference.setSummary(
+ com.android.settings.R.string.work_sound_same_as_personal);
+ }
+
+ private void disableWorkSync() {
+ RingtoneManager.disableSyncFromParent(getManagedProfileContext());
+ disableWorkSyncSettings();
+ }
+
+ private void disableWorkSyncSettings() {
+ if (mWorkPhoneRingtonePreference != null) {
+ mWorkPhoneRingtonePreference.setEnabled(true);
+ }
+ mWorkNotificationRingtonePreference.setEnabled(true);
+ mWorkAlarmRingtonePreference.setEnabled(true);
+
+ updateWorkRingtoneSummaries();
+ }
+
+ private void updateWorkRingtoneSummaries() {
+ Context managedProfileContext = getManagedProfileContext();
+
+ if (mWorkPhoneRingtonePreference != null) {
+ mWorkPhoneRingtonePreference.setSummary(
+ updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_RINGTONE));
+ }
+ mWorkNotificationRingtonePreference.setSummary(
+ updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_NOTIFICATION));
+ mWorkAlarmRingtonePreference.setSummary(
+ updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_ALARM));
+ }
+
+ private void maybeRemoveWorkPreferences() {
+ if (mWorkPreferenceCategory == null) {
+ // No work preferences to remove
+ return;
+ }
+ mParent.getPreferenceScreen().removePreference(mWorkPreferenceCategory);
+ mWorkPreferenceCategory = null;
+ mWorkPhoneRingtonePreference = null;
+ mWorkNotificationRingtonePreference = null;
+ mWorkAlarmRingtonePreference = null;
+ }
+
+ public static class UnifyWorkDialogFragment extends InstrumentedDialogFragment
+ implements DialogInterface.OnClickListener {
+ private static final String TAG = "UnifyWorkDialogFragment";
+ private static final int REQUEST_CODE = 200;
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.DIALOG_UNIFY_SOUND_SETTINGS;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(com.android.settings.R.string.work_sync_dialog_title)
+ .setMessage(com.android.settings.R.string.work_sync_dialog_message)
+ .setPositiveButton(com.android.settings.R.string.work_sync_dialog_yes,
+ UnifyWorkDialogFragment.this)
+ .setNegativeButton(android.R.string.no, null)
+ .create();
+ }
+
+ public static void show(SoundSettings parent) {
+ FragmentManager fm = parent.getFragmentManager();
+ if (fm.findFragmentByTag(TAG) == null) {
+ UnifyWorkDialogFragment fragment = new UnifyWorkDialogFragment();
+ fragment.setTargetFragment(parent, REQUEST_CODE);
+ fragment.show(fm, TAG);
+ }
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ SoundSettings soundSettings = (SoundSettings) getTargetFragment();
+ if (soundSettings.isAdded()) {
+ soundSettings.enableWorkSync();
+ }
+ }
+ }
+
+}
diff --git a/src/com/android/settings/overlay/SurveyFeatureProvider.java b/src/com/android/settings/overlay/SurveyFeatureProvider.java
index 79e907f..907bed8 100644
--- a/src/com/android/settings/overlay/SurveyFeatureProvider.java
+++ b/src/com/android/settings/overlay/SurveyFeatureProvider.java
@@ -40,16 +40,46 @@
*
* @param activity The host activity to show the survey in.
* @param surveyId A unique Id representing a survey to download.
+ * @return A boolean indicating if a survey was shown or not.
*/
- void showSurveyIfAvailable(Activity activity, String surveyId);
+ boolean showSurveyIfAvailable(Activity activity, String surveyId);
/**
* A helper method to get the surveyId. Implementers should create a mapping of
* keys to surveyIds and provide them via this function.
*
* @param context A valid context.
- * @param key The key to get the surveyId for.
+ * @param simpleKey The simple name of the key to get the surveyId for.
* @return The unique Id as a string or null on error.
*/
- String getSurveyId(Context context, String key);
+ String getSurveyId(Context context, String simpleKey);
+
+ /**
+ * Removes the survey for {@code siteId} if it expired, then returns the expiration date (as a
+ * unix timestamp) for the remaining survey should it exist and be ready to show. Returns -1 if
+ * no valid survey exists after removing the potentially expired one.
+ *
+ * @param context the calling context.
+ * @param surveyId the site ID.
+ * @return the unix timestamp for the available survey for the given {@coe siteId} or -1 if
+ * there is none available.
+ */
+ long getSurveyExpirationDate(Context context, String surveyId);
+
+ /**
+ * Registers an activity to show surveys/prompts as soon as they are downloaded. The receiver
+ * should be unregistered prior to destroying the activity to avoid undefined behavior by
+ * calling {@link #unregisterReceiver(Activity, BroadcastReceiver)}.
+ * @param activity The activity that should show surveys once they are downloaded.
+ * @return the broadcast receiver listening for survey downloads. Must be unregistered before
+ * leaving the activity.
+ */
+ BroadcastReceiver createAndRegisterReceiver(Activity activity);
+
+ /**
+ * Unregisters the broadcast receiver for this activity. Should only be called once per activity
+ * after a call to {@link #createAndRegisterReceiver(Activity)}.
+ * @param activity The activity that was used to register the BroadcastReceiver.
+ */
+ void unregisterReceiver(Activity activity, BroadcastReceiver receiver);
}
diff --git a/src/com/android/settings/password/SetNewPasswordActivity.java b/src/com/android/settings/password/SetNewPasswordActivity.java
index 585f4f4..4692609 100644
--- a/src/com/android/settings/password/SetNewPasswordActivity.java
+++ b/src/com/android/settings/password/SetNewPasswordActivity.java
@@ -50,7 +50,8 @@
finish();
return;
}
- mSetNewPasswordController = SetNewPasswordController.create(this, this, getIntent());
+ mSetNewPasswordController = SetNewPasswordController.create(
+ this, this, getIntent(), getActivityToken());
mSetNewPasswordController.dispatchSetNewPasswordIntent();
}
diff --git a/src/com/android/settings/password/SetNewPasswordController.java b/src/com/android/settings/password/SetNewPasswordController.java
index 00cf33e..9443541 100644
--- a/src/com/android/settings/password/SetNewPasswordController.java
+++ b/src/com/android/settings/password/SetNewPasswordController.java
@@ -29,6 +29,7 @@
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.UserManager;
import com.android.internal.annotations.VisibleForTesting;
@@ -60,14 +61,15 @@
private final DevicePolicyManager mDevicePolicyManager;
private final Ui mUi;
- public static SetNewPasswordController create(Context context, Ui ui, Intent intent) {
+ public static SetNewPasswordController create(Context context, Ui ui, Intent intent,
+ IBinder activityToken) {
// Trying to figure out which user is setting new password. If it is
// ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or the calling user is not allowed to set
// separate profile challenge, it is the current user to set new password. Otherwise,
// it is the user who starts this activity setting new password.
int userId = ActivityManager.getCurrentUser();
if (ACTION_SET_NEW_PASSWORD.equals(intent.getAction())) {
- final int callingUserId = Utils.getSecureTargetUser(context.getActivityToken(),
+ final int callingUserId = Utils.getSecureTargetUser(activityToken,
UserManager.get(context), null, intent.getExtras()).getIdentifier();
final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
if (lockPatternUtils.isSeparateProfileChallengeAllowed(callingUserId)) {
diff --git a/src/com/android/settings/search/BaseSearchIndexProvider.java b/src/com/android/settings/search/BaseSearchIndexProvider.java
index 0fe1944..bb518ba 100644
--- a/src/com/android/settings/search/BaseSearchIndexProvider.java
+++ b/src/com/android/settings/search/BaseSearchIndexProvider.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.provider.SearchIndexableResource;
+import com.android.settings.core.PreferenceController;
import java.util.Collections;
import java.util.List;
@@ -46,4 +47,9 @@
public List<String> getNonIndexableKeys(Context context) {
return EMPTY_LIST;
}
+
+ @Override
+ public List<PreferenceController> getPreferenceControllers(Context context) {
+ return null;
+ }
}
diff --git a/src/com/android/settings/search/IndexDatabaseHelper.java b/src/com/android/settings/search/IndexDatabaseHelper.java
index cddee68..fcf5e7c 100644
--- a/src/com/android/settings/search/IndexDatabaseHelper.java
+++ b/src/com/android/settings/search/IndexDatabaseHelper.java
@@ -28,46 +28,48 @@
private static final String TAG = "IndexDatabaseHelper";
private static final String DATABASE_NAME = "search_index.db";
- private static final int DATABASE_VERSION = 115;
+ private static final int DATABASE_VERSION = 116;
private static final String INDEX = "index";
public interface Tables {
- public static final String TABLE_PREFS_INDEX = "prefs_index";
- public static final String TABLE_META_INDEX = "meta_index";
- public static final String TABLE_SAVED_QUERIES = "saved_queries";
+ String TABLE_PREFS_INDEX = "prefs_index";
+ String TABLE_META_INDEX = "meta_index";
+ String TABLE_SAVED_QUERIES = "saved_queries";
}
public interface IndexColumns {
- public static final String DOCID = "docid";
- public static final String LOCALE = "locale";
- public static final String DATA_RANK = "data_rank";
- public static final String DATA_TITLE = "data_title";
- public static final String DATA_TITLE_NORMALIZED = "data_title_normalized";
- public static final String DATA_SUMMARY_ON = "data_summary_on";
- public static final String DATA_SUMMARY_ON_NORMALIZED = "data_summary_on_normalized";
- public static final String DATA_SUMMARY_OFF = "data_summary_off";
- public static final String DATA_SUMMARY_OFF_NORMALIZED = "data_summary_off_normalized";
- public static final String DATA_ENTRIES = "data_entries";
- public static final String DATA_KEYWORDS = "data_keywords";
- public static final String CLASS_NAME = "class_name";
- public static final String SCREEN_TITLE = "screen_title";
- public static final String INTENT_ACTION = "intent_action";
- public static final String INTENT_TARGET_PACKAGE = "intent_target_package";
- public static final String INTENT_TARGET_CLASS = "intent_target_class";
- public static final String ICON = "icon";
- public static final String ENABLED = "enabled";
- public static final String DATA_KEY_REF = "data_key_reference";
- public static final String USER_ID = "user_id";
+ String DOCID = "docid";
+ String LOCALE = "locale";
+ String DATA_RANK = "data_rank";
+ String DATA_TITLE = "data_title";
+ String DATA_TITLE_NORMALIZED = "data_title_normalized";
+ String DATA_SUMMARY_ON = "data_summary_on";
+ String DATA_SUMMARY_ON_NORMALIZED = "data_summary_on_normalized";
+ String DATA_SUMMARY_OFF = "data_summary_off";
+ String DATA_SUMMARY_OFF_NORMALIZED = "data_summary_off_normalized";
+ String DATA_ENTRIES = "data_entries";
+ String DATA_KEYWORDS = "data_keywords";
+ String CLASS_NAME = "class_name";
+ String SCREEN_TITLE = "screen_title";
+ String INTENT_ACTION = "intent_action";
+ String INTENT_TARGET_PACKAGE = "intent_target_package";
+ String INTENT_TARGET_CLASS = "intent_target_class";
+ String ICON = "icon";
+ String ENABLED = "enabled";
+ String DATA_KEY_REF = "data_key_reference";
+ String USER_ID = "user_id";
+ String PAYLOAD_TYPE = "payload_type";
+ String PAYLOAD = "payload";
}
public interface MetaColumns {
- public static final String BUILD = "build";
+ String BUILD = "build";
}
public interface SavedQueriesColums {
- public static final String QUERY = "query";
- public static final String TIME_STAMP = "timestamp";
+ String QUERY = "query";
+ String TIME_STAMP = "timestamp";
}
private static final String CREATE_INDEX_TABLE =
@@ -110,6 +112,10 @@
IndexColumns.DATA_KEY_REF +
", " +
IndexColumns.USER_ID +
+ ", " +
+ IndexColumns.PAYLOAD_TYPE +
+ ", " +
+ IndexColumns.PAYLOAD +
");";
private static final String CREATE_META_TABLE =
diff --git a/src/com/android/settings/search/Indexable.java b/src/com/android/settings/search/Indexable.java
index e87d9dc..2ec4ac0 100644
--- a/src/com/android/settings/search/Indexable.java
+++ b/src/com/android/settings/search/Indexable.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.provider.SearchIndexableResource;
+import com.android.settings.core.PreferenceController;
import java.util.List;
@@ -65,5 +66,11 @@
* @return a list of {@link SearchIndexableRaw} references. Can be null.
*/
List<String> getNonIndexableKeys(Context context);
+
+ /**
+ * @param context
+ * @return a list of {@link PreferenceController} for ResultPayload data during Indexing.
+ */
+ List<PreferenceController> getPreferenceControllers(Context context);
}
}
diff --git a/src/com/android/settings/search2/DatabaseIndexingManager.java b/src/com/android/settings/search2/DatabaseIndexingManager.java
index 9bb4538..fa482ef 100644
--- a/src/com/android/settings/search2/DatabaseIndexingManager.java
+++ b/src/com/android/settings/search2/DatabaseIndexingManager.java
@@ -34,10 +34,12 @@
import android.provider.SearchIndexableResource;
import android.provider.SearchIndexablesContract;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
+import com.android.settings.core.PreferenceController;
import com.android.settings.search.IndexDatabaseHelper;
import com.android.settings.search.Indexable;
import com.android.settings.search.Ranking;
@@ -86,56 +88,6 @@
public class DatabaseIndexingManager {
private static final String LOG_TAG = "DatabaseIndexingManager";
- // Those indices should match the indices of SELECT_COLUMNS !
- public static final int COLUMN_INDEX_RANK = 0;
- public static final int COLUMN_INDEX_TITLE = 1;
- public static final int COLUMN_INDEX_SUMMARY_ON = 2;
- public static final int COLUMN_INDEX_SUMMARY_OFF = 3;
- public static final int COLUMN_INDEX_ENTRIES = 4;
- public static final int COLUMN_INDEX_KEYWORDS = 5;
- public static final int COLUMN_INDEX_CLASS_NAME = 6;
- public static final int COLUMN_INDEX_SCREEN_TITLE = 7;
- public static final int COLUMN_INDEX_ICON = 8;
- public static final int COLUMN_INDEX_INTENT_ACTION = 9;
- public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 10;
- public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 11;
- public static final int COLUMN_INDEX_ENABLED = 12;
- public static final int COLUMN_INDEX_KEY = 13;
- public static final int COLUMN_INDEX_USER_ID = 14;
-
- // If you change the order of columns here, you SHOULD change the COLUMN_INDEX_XXX values
- private static final String[] SELECT_COLUMNS = new String[] {
- IndexDatabaseHelper.IndexColumns.DATA_RANK, // 0
- IndexDatabaseHelper.IndexColumns.DATA_TITLE, // 1
- IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, // 2
- IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, // 3
- IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, // 4
- IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, // 5
- IndexDatabaseHelper.IndexColumns.CLASS_NAME, // 6
- IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, // 7
- IndexDatabaseHelper.IndexColumns.ICON, // 8
- IndexDatabaseHelper.IndexColumns.INTENT_ACTION, // 9
- IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, // 10
- IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, // 11
- IndexDatabaseHelper.IndexColumns.ENABLED, // 12
- IndexDatabaseHelper.IndexColumns.DATA_KEY_REF // 13
- };
-
- private static final String[] MATCH_COLUMNS_PRIMARY = {
- IndexDatabaseHelper.IndexColumns.DATA_TITLE,
- IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED,
- IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS
- };
-
- private static final String[] MATCH_COLUMNS_SECONDARY = {
- IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON,
- IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED,
- IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF,
- IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED,
- IndexDatabaseHelper.IndexColumns.DATA_ENTRIES
- };
-
-
private static final String NODE_NAME_PREFERENCE_SCREEN = "PreferenceScreen";
private static final String NODE_NAME_CHECK_BOX_PREFERENCE = "CheckBoxPreference";
private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference";
@@ -514,7 +466,7 @@
}
}
- private void indexOneSearchIndexableData(SQLiteDatabase database, String localeStr,
+ public void indexOneSearchIndexableData(SQLiteDatabase database, String localeStr,
SearchIndexableData data, Map<String, List<String>> nonIndexableKeys) {
if (data instanceof SearchIndexableResource) {
indexOneResource(database, localeStr, (SearchIndexableResource) data, nonIndexableKeys);
@@ -530,22 +482,22 @@
return;
}
- updateOneRowWithFilteredData(database, localeStr,
- raw.title,
- raw.summaryOn,
- raw.summaryOff,
- raw.entries,
- raw.className,
- raw.screenTitle,
- raw.iconResId,
- raw.rank,
- raw.keywords,
- raw.intentAction,
- raw.intentTargetPackage,
- raw.intentTargetClass,
- raw.enabled,
- raw.key,
- raw.userId);
+ DatabaseRow.Builder builder = new DatabaseRow.Builder();
+ builder.setLocale(localeStr)
+ .setEntries(raw.entries)
+ .setClassName(raw.className)
+ .setScreenTitle(raw.screenTitle)
+ .setIconResId(raw.iconResId)
+ .setRank(raw.rank)
+ .setIntentAction(raw.intentAction)
+ .setIntentTargetPackage(raw.intentTargetPackage)
+ .setIntentTargetClass(raw.intentTargetClass)
+ .setEnabled(raw.enabled)
+ .setKey(raw.key)
+ .setUserId(raw.userId);
+
+ updateOneRowWithFilteredData(database, builder, raw.title, raw.summaryOn, raw.summaryOff,
+ raw.keywords);
}
private void indexOneResource(SQLiteDatabase database, String localeStr,
@@ -622,25 +574,45 @@
final int outerDepth = parser.getDepth();
final AttributeSet attrs = Xml.asAttributeSet(parser);
- final String screenTitle = XMLParserUtil.getDataTitle(context, attrs);
+ final String screenTitle = XmlParserUtils.getDataTitle(context, attrs);
- String key = XMLParserUtil.getDataKey(context, attrs);
+ String key = XmlParserUtils.getDataKey(context, attrs);
String title;
String summary;
String keywords;
+ ResultPayload payload;
+
+ ArrayMap<String, PreferenceController> controllerUriMap = null;
+
+ if (fragmentName != null) {
+ controllerUriMap = (ArrayMap) DatabaseIndexingUtils
+ .getPreferenceControllerUriMap(fragmentName, context);
+ }
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing
// hyphens.
if (!nonIndexableKeys.contains(key)) {
- title = XMLParserUtil.getDataTitle(context, attrs);
- summary = XMLParserUtil.getDataSummary(context, attrs);
- keywords = XMLParserUtil.getDataKeywords(context, attrs);
+ title = XmlParserUtils.getDataTitle(context, attrs);
+ summary = XmlParserUtils.getDataSummary(context, attrs);
+ keywords = XmlParserUtils.getDataKeywords(context, attrs);
- updateOneRowWithFilteredData(database, localeStr, title, summary, null, null,
- fragmentName, screenTitle, iconResId, rank,
- keywords, intentAction, intentTargetPackage, intentTargetClass, true,
- key, -1 /* default user id */);
+ DatabaseRow.Builder builder = new DatabaseRow.Builder();
+ builder.setLocale(localeStr)
+ .setEntries(null)
+ .setClassName(fragmentName)
+ .setScreenTitle(screenTitle)
+ .setIconResId(iconResId)
+ .setRank(rank)
+ .setIntentAction(intentAction)
+ .setIntentTargetPackage(intentTargetPackage)
+ .setIntentTargetClass(intentTargetClass)
+ .setEnabled(true)
+ .setKey(key)
+ .setUserId(-1 /* default user id */);
+
+ updateOneRowWithFilteredData(database, builder, title, summary,
+ null /* summary off */, keywords);
}
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -651,43 +623,56 @@
nodeName = parser.getName();
- key = XMLParserUtil.getDataKey(context, attrs);
+ key = XmlParserUtils.getDataKey(context, attrs);
if (nonIndexableKeys.contains(key)) {
continue;
}
- title = XMLParserUtil.getDataTitle(context, attrs);
- keywords = XMLParserUtil.getDataKeywords(context, attrs);
+ title = XmlParserUtils.getDataTitle(context, attrs);
+ keywords = XmlParserUtils.getDataKeywords(context, attrs);
+
+ DatabaseRow.Builder builder = new DatabaseRow.Builder();
+ builder.setLocale(localeStr)
+ .setClassName(fragmentName)
+ .setScreenTitle(screenTitle)
+ .setIconResId(iconResId)
+ .setRank(rank)
+ .setIntentAction(intentAction)
+ .setIntentTargetPackage(intentTargetPackage)
+ .setIntentTargetClass(intentTargetClass)
+ .setEnabled(true)
+ .setKey(key)
+ .setUserId(-1 /* default user id */);
if (!nodeName.equals(NODE_NAME_CHECK_BOX_PREFERENCE)) {
- summary = XMLParserUtil.getDataSummary(context, attrs);
+ summary = XmlParserUtils.getDataSummary(context, attrs);
String entries = null;
if (nodeName.endsWith(NODE_NAME_LIST_PREFERENCE)) {
- entries = XMLParserUtil.getDataEntries(context, attrs);
+ entries = XmlParserUtils.getDataEntries(context, attrs);
}
+ payload = DatabaseIndexingUtils.getPayloadFromUriMap(controllerUriMap, key);
+
+ builder.setEntries(entries)
+ .setPayload(payload);
+
// Insert rows for the child nodes of PreferenceScreen
- updateOneRowWithFilteredData(database, localeStr, title, summary, null, entries,
- fragmentName, screenTitle, iconResId, rank,
- keywords, intentAction, intentTargetPackage, intentTargetClass,
- true, key, -1 /* default user id */);
+ updateOneRowWithFilteredData(database, builder, title, summary,
+ null /* summary off */, keywords);
} else {
- String summaryOn = XMLParserUtil.getDataSummaryOn(context, attrs);
- String summaryOff = XMLParserUtil.getDataSummaryOff(context, attrs);
+ String summaryOn = XmlParserUtils.getDataSummaryOn(context, attrs);
+ String summaryOff = XmlParserUtils.getDataSummaryOff(context, attrs);
if (TextUtils.isEmpty(summaryOn) && TextUtils.isEmpty(summaryOff)) {
- summaryOn = XMLParserUtil.getDataSummary(context, attrs);
+ summaryOn = XmlParserUtils.getDataSummary(context, attrs);
}
- updateOneRowWithFilteredData(database, localeStr, title, summaryOn, summaryOff,
- null, fragmentName, screenTitle, iconResId, rank,
- keywords, intentAction, intentTargetPackage, intentTargetClass,
- true, key, -1 /* default user id */);
+ updateOneRowWithFilteredData(database, builder, title, summaryOn, summaryOff,
+ keywords);
}
}
-
} catch (XmlPullParserException e) {
throw new RuntimeException("Error parsing PreferenceScreen", e);
} catch (IOException e) {
@@ -709,6 +694,7 @@
final List<SearchIndexableRaw> rawList = provider.getRawDataToIndex(context, enabled);
if (rawList != null) {
+
final int rawSize = rawList.size();
for (int i = 0; i < rawSize; i++) {
SearchIndexableRaw raw = rawList.get(i);
@@ -722,22 +708,22 @@
continue;
}
- updateOneRowWithFilteredData(database, localeStr,
- raw.title,
- raw.summaryOn,
- raw.summaryOff,
- raw.entries,
- className,
- raw.screenTitle,
- iconResId,
- rank,
- raw.keywords,
- raw.intentAction,
- raw.intentTargetPackage,
- raw.intentTargetClass,
- raw.enabled,
- raw.key,
- raw.userId);
+ DatabaseRow.Builder builder = new DatabaseRow.Builder();
+ builder.setLocale(localeStr)
+ .setEntries(raw.entries)
+ .setClassName(className)
+ .setScreenTitle(raw.screenTitle)
+ .setIconResId(iconResId)
+ .setRank(rank)
+ .setIntentAction(raw.intentAction)
+ .setIntentTargetPackage(raw.intentTargetPackage)
+ .setIntentTargetClass(raw.intentTargetClass)
+ .setEnabled(raw.enabled)
+ .setKey(raw.key)
+ .setUserId(raw.userId);
+
+ updateOneRowWithFilteredData(database, builder, raw.title, raw.summaryOn,
+ raw.summaryOff, raw.keywords);
}
}
@@ -766,70 +752,68 @@
}
}
- private void updateOneRowWithFilteredData(SQLiteDatabase database, String locale,
- String title, String summaryOn, String summaryOff, String entries,
- String className,
- String screenTitle, int iconResId, int rank, String keywords,
- String intentAction, String intentTargetPackage, String intentTargetClass,
- boolean enabled, String key, int userId) {
+ private void updateOneRowWithFilteredData(SQLiteDatabase database, DatabaseRow.Builder builder,
+ String title, String summaryOn, String summaryOff,String keywords) {
- final String updatedTitle = XMLParserUtil.normalizeHyphen(title);
- final String updatedSummaryOn = XMLParserUtil.normalizeHyphen(summaryOn);
- final String updatedSummaryOff = XMLParserUtil.normalizeHyphen(summaryOff);
+ final String updatedTitle = DatabaseIndexingUtils.normalizeHyphen(title);
+ final String updatedSummaryOn = DatabaseIndexingUtils.normalizeHyphen(summaryOn);
+ final String updatedSummaryOff = DatabaseIndexingUtils.normalizeHyphen(summaryOff);
- final String normalizedTitle = XMLParserUtil.normalizeString(updatedTitle);
- final String normalizedSummaryOn = XMLParserUtil.normalizeString(updatedSummaryOn);
- final String normalizedSummaryOff = XMLParserUtil.normalizeString(updatedSummaryOff);
+ final String normalizedTitle = DatabaseIndexingUtils.normalizeString(updatedTitle);
+ final String normalizedSummaryOn = DatabaseIndexingUtils.normalizeString(updatedSummaryOn);
+ final String normalizedSummaryOff = DatabaseIndexingUtils
+ .normalizeString(updatedSummaryOff);
- final String spaceDelimitedKeywords = XMLParserUtil.normalizeKeywords(keywords);
+ final String spaceDelimitedKeywords = DatabaseIndexingUtils.normalizeKeywords(keywords);
- updateOneRow(database, locale,
- updatedTitle, normalizedTitle, updatedSummaryOn, normalizedSummaryOn,
- updatedSummaryOff, normalizedSummaryOff, entries, className, screenTitle, iconResId,
- rank, spaceDelimitedKeywords, intentAction, intentTargetPackage, intentTargetClass,
- enabled, key, userId);
+ builder.setUpdatedTitle(updatedTitle)
+ .setUpdatedSummaryOn(updatedSummaryOn)
+ .setUpdatedSummaryOff(updatedSummaryOff)
+ .setNormalizedTitle(normalizedTitle)
+ .setNormalizedSummaryOn(normalizedSummaryOn)
+ .setNormalizedSummaryOff(normalizedSummaryOff)
+ .setSpaceDelimitedKeywords(spaceDelimitedKeywords);
+
+ updateOneRow(database, builder.build());
}
- private void updateOneRow(SQLiteDatabase database, String locale, String updatedTitle,
- String normalizedTitle, String updatedSummaryOn, String normalizedSummaryOn,
- String updatedSummaryOff, String normalizedSummaryOff, String entries, String className,
- String screenTitle, int iconResId, int rank, String spaceDelimitedKeywords,
- String intentAction, String intentTargetPackage, String intentTargetClass,
- boolean enabled, String key, int userId) {
+ private void updateOneRow(SQLiteDatabase database, DatabaseRow row) {
- if (TextUtils.isEmpty(updatedTitle)) {
+ if (TextUtils.isEmpty(row.updatedTitle)) {
return;
}
// The DocID should contains more than the title string itself (you may have two settings
// with the same title). So we need to use a combination of the title and the screenTitle.
- StringBuilder sb = new StringBuilder(updatedTitle);
- sb.append(screenTitle);
+ StringBuilder sb = new StringBuilder(row.updatedTitle);
+ sb.append(row.screenTitle);
int docId = sb.toString().hashCode();
ContentValues values = new ContentValues();
values.put(IndexDatabaseHelper.IndexColumns.DOCID, docId);
- values.put(IndexDatabaseHelper.IndexColumns.LOCALE, locale);
- values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, rank);
- values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, updatedTitle);
- values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, normalizedTitle);
- values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, updatedSummaryOn);
+ values.put(IndexDatabaseHelper.IndexColumns.LOCALE, row.locale);
+ values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, row.rank);
+ values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, row.updatedTitle);
+ values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, row.normalizedTitle);
+ values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, row.updatedSummaryOn);
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED,
- normalizedSummaryOn);
- values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, updatedSummaryOff);
+ row.normalizedSummaryOn);
+ values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, row.updatedSummaryOff);
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED,
- normalizedSummaryOff);
- values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, entries);
- values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, spaceDelimitedKeywords);
- values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, className);
- values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, screenTitle);
- values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, intentAction);
- values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, intentTargetPackage);
- values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, intentTargetClass);
- values.put(IndexDatabaseHelper.IndexColumns.ICON, iconResId);
- values.put(IndexDatabaseHelper.IndexColumns.ENABLED, enabled);
- values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, key);
- values.put(IndexDatabaseHelper.IndexColumns.USER_ID, userId);
+ row.normalizedSummaryOff);
+ values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, row.entries);
+ values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, row.spaceDelimitedKeywords);
+ values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, row.className);
+ values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, row.screenTitle);
+ values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, row.intentAction);
+ values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, row.intentTargetPackage);
+ values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, row.intentTargetClass);
+ values.put(IndexDatabaseHelper.IndexColumns.ICON, row.iconResId);
+ values.put(IndexDatabaseHelper.IndexColumns.ENABLED, row.enabled);
+ values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, row.key);
+ values.put(IndexDatabaseHelper.IndexColumns.USER_ID, row.userId);
+ values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, row.payloadType);
+ values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, row.payload);
database.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
}
@@ -960,4 +944,195 @@
whereArgs);
}
}
+
+ public static class DatabaseRow {
+ public final String locale;
+ public final String updatedTitle;
+ public final String normalizedTitle;
+ public final String updatedSummaryOn;
+ public final String normalizedSummaryOn;
+ public final String updatedSummaryOff;
+ public final String normalizedSummaryOff;
+ public final String entries;
+ public final String className;
+ public final String screenTitle;
+ public final int iconResId;
+ public final int rank;
+ public final String spaceDelimitedKeywords;
+ public final String intentAction;
+ public final String intentTargetPackage;
+ public final String intentTargetClass;
+ public final boolean enabled;
+ public final String key;
+ public final int userId;
+ public final int payloadType;
+ public final byte[] payload;
+
+ private DatabaseRow(Builder builder) {
+ locale = builder.mLocale;
+ updatedTitle = builder.mUpdatedTitle;
+ normalizedTitle = builder.mNormalizedTitle;
+ updatedSummaryOn = builder.mUpdatedSummaryOn;
+ normalizedSummaryOn = builder.mNormalizedSummaryOn;
+ updatedSummaryOff = builder.mUpdatedSummaryOff;
+ normalizedSummaryOff = builder.mNormalizedSummaryOff;
+ entries = builder.mEntries;
+ className = builder.mClassName;
+ screenTitle = builder.mScreenTitle;
+ iconResId = builder.mIconResId;
+ rank = builder.mRank;
+ spaceDelimitedKeywords = builder.mSpaceDelimitedKeywords;
+ intentAction = builder.mIntentAction;
+ intentTargetPackage = builder.mIntentTargetPackage;
+ intentTargetClass = builder.mIntentTargetClass;
+ enabled = builder.mEnabled;
+ key = builder.mKey;
+ userId = builder.mUserId;
+ payloadType = builder.mPayloadType;
+ payload = builder.mPayload != null ? ResultPayloadUtils.marshall(builder.mPayload)
+ : null;
+ }
+
+ public static class Builder {
+ private String mLocale;
+ private String mUpdatedTitle;
+ private String mNormalizedTitle;
+ private String mUpdatedSummaryOn;
+ private String mNormalizedSummaryOn;
+ private String mUpdatedSummaryOff;
+ private String mNormalizedSummaryOff;
+ private String mEntries;
+ private String mClassName;
+ private String mScreenTitle;
+ private int mIconResId;
+ private int mRank;
+ private String mSpaceDelimitedKeywords;
+ private String mIntentAction;
+ private String mIntentTargetPackage;
+ private String mIntentTargetClass;
+ private boolean mEnabled;
+ private String mKey;
+ private int mUserId;
+ @ResultPayload.PayloadType private int mPayloadType;
+ private ResultPayload mPayload;
+
+ public Builder setLocale(String locale) {
+ mLocale = locale;
+ return this;
+ }
+
+ public Builder setUpdatedTitle(String updatedTitle) {
+ mUpdatedTitle = updatedTitle;
+ return this;
+ }
+
+ public Builder setNormalizedTitle(String normalizedTitle) {
+ mNormalizedTitle = normalizedTitle;
+ return this;
+ }
+
+ public Builder setUpdatedSummaryOn(String updatedSummaryOn) {
+ mUpdatedSummaryOn = updatedSummaryOn;
+ return this;
+ }
+
+ public Builder setNormalizedSummaryOn(String normalizedSummaryOn) {
+ mNormalizedSummaryOn = normalizedSummaryOn;
+ return this;
+ }
+
+ public Builder setUpdatedSummaryOff(String updatedSummaryOff) {
+ mUpdatedSummaryOff = updatedSummaryOff;
+ return this;
+ }
+
+ public Builder setNormalizedSummaryOff(String normalizedSummaryOff) {
+ this.mNormalizedSummaryOff = normalizedSummaryOff;
+ return this;
+ }
+
+ public Builder setEntries(String entries) {
+ mEntries = entries;
+ return this;
+ }
+
+ public Builder setClassName(String className) {
+ mClassName = className;
+ return this;
+ }
+
+ public Builder setScreenTitle(String screenTitle) {
+ mScreenTitle = screenTitle;
+ return this;
+ }
+
+ public Builder setIconResId(int iconResId) {
+ mIconResId = iconResId;
+ return this;
+ }
+
+ public Builder setRank(int rank) {
+ mRank = rank;
+ return this;
+ }
+
+ public Builder setSpaceDelimitedKeywords(String spaceDelimitedKeywords) {
+ mSpaceDelimitedKeywords = spaceDelimitedKeywords;
+ return this;
+ }
+
+ public Builder setIntentAction(String intentAction) {
+ mIntentAction = intentAction;
+ return this;
+ }
+
+ public Builder setIntentTargetPackage(String intentTargetPackage) {
+ mIntentTargetPackage = intentTargetPackage;
+ return this;
+ }
+
+ public Builder setIntentTargetClass(String intentTargetClass) {
+ mIntentTargetClass = intentTargetClass;
+ return this;
+ }
+
+ public Builder setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ return this;
+ }
+
+ public Builder setKey(String key) {
+ mKey = key;
+ return this;
+ }
+
+ public Builder setUserId(int userId) {
+ mUserId = userId;
+ return this;
+ }
+
+ public Builder setPayload(ResultPayload payload) {
+ mPayload = payload;
+
+ if(mPayload != null) {
+ setPayloadType(mPayload.getType());
+ }
+ return this;
+ }
+
+ /**
+ * Payload type is added when a Payload is added to the Builder in {setPayload}
+ * @param payloadType PayloadType
+ * @return The Builder
+ */
+ private Builder setPayloadType(@ResultPayload.PayloadType int payloadType) {
+ mPayloadType = payloadType;
+ return this;
+ }
+
+ public DatabaseRow build() {
+ return new DatabaseRow(this);
+ }
+ }
+ }
}
diff --git a/src/com/android/settings/search2/DatabaseIndexingUtils.java b/src/com/android/settings/search2/DatabaseIndexingUtils.java
index a8f64df..c7a7f92 100644
--- a/src/com/android/settings/search2/DatabaseIndexingUtils.java
+++ b/src/com/android/settings/search2/DatabaseIndexingUtils.java
@@ -23,12 +23,19 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.net.Uri;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
+import com.android.settings.core.PreferenceController;
import com.android.settings.search.Indexable;
import java.lang.reflect.Field;
+import java.text.Normalizer;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
/**
* Utility class for {@like DatabaseIndexingManager} to handle the mapping between Payloads
@@ -36,17 +43,82 @@
*/
public class DatabaseIndexingUtils {
- private static final String LOG_TAG = "IndexingUtil";
+ private static final String TAG = "IndexingUtil";
private static final String FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER =
"SEARCH_INDEX_DATA_PROVIDER";
+ private static final String NON_BREAKING_HYPHEN = "\u2011";
+ private static final String EMPTY = "";
+ private static final String LIST_DELIMITERS = "[,]\\s*";
+ private static final String HYPHEN = "-";
+ private static final String SPACE = " ";
+
+ private static final Pattern REMOVE_DIACRITICALS_PATTERN
+ = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
+
+ /**
+ * @param className which wil provide the map between from {@link Uri}s to
+ * {@link PreferenceController}
+ * @param context
+ * @return A map between {@link Uri}s and {@link PreferenceController}s to get the payload
+ * types for Settings.
+ */
+ public static Map<String, PreferenceController> getPreferenceControllerUriMap(
+ String className, Context context) {
+ final Class<?> clazz = getIndexableClass(className);
+
+ if (clazz == null) {
+ Log.d(TAG, "SearchIndexableResource '" + className +
+ "' should implement the " + Indexable.class.getName() + " interface!");
+ return null;
+ }
+
+ // Will be non null only for a Local provider implementing a
+ // SEARCH_INDEX_DATA_PROVIDER field
+ final Indexable.SearchIndexProvider provider = getSearchIndexProvider(clazz);
+ List<PreferenceController> controllers =
+ provider.getPreferenceControllers(context);
+
+ if (controllers == null ) {
+ return null;
+ }
+
+ ArrayMap<String, PreferenceController> map = new ArrayMap<>();
+
+ for (PreferenceController controller : controllers) {
+ map.put(controller.getPreferenceKey(), controller);
+ }
+
+ return map;
+ }
+
+ /**
+ * @param uriMap Map between the {@link PreferenceController} keys and the controllers themselves.
+ * @param key The look up key
+ * @return The Payload from the {@link PreferenceController} specified by the key, if it exists.
+ * Otherwise null.
+ */
+ public static ResultPayload getPayloadFromUriMap(ArrayMap<String, PreferenceController> uriMap,
+ String key) {
+ if (uriMap == null) {
+ return null;
+ }
+
+ PreferenceController controller = uriMap.get(key);
+ if (controller == null) {
+ return null;
+ }
+
+ return controller.getResultPayload();
+ }
+
public static Class<?> getIndexableClass(String className) {
final Class<?> clazz;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
- Log.d(LOG_TAG, "Cannot find class: " + className);
+ Log.d(TAG, "Cannot find class: " + className);
return null;
}
return isIndexableClass(clazz) ? clazz : null;
@@ -61,15 +133,15 @@
final Field f = clazz.getField(FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER);
return (Indexable.SearchIndexProvider) f.get(null);
} catch (NoSuchFieldException e) {
- Log.d(LOG_TAG, "Cannot find field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
+ Log.d(TAG, "Cannot find field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
} catch (SecurityException se) {
- Log.d(LOG_TAG,
+ Log.d(TAG,
"Security exception for field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
} catch (IllegalAccessException e) {
- Log.d(LOG_TAG,
+ Log.d(TAG,
"Illegal access to field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
} catch (IllegalArgumentException e) {
- Log.d(LOG_TAG,
+ Log.d(TAG,
"Illegal argument when accessing field '" +
FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
}
@@ -115,4 +187,19 @@
return false;
}
}
+
+ public static String normalizeHyphen(String input) {
+ return (input != null) ? input.replaceAll(NON_BREAKING_HYPHEN, HYPHEN) : EMPTY;
+ }
+
+ public static String normalizeString(String input) {
+ final String nohyphen = (input != null) ? input.replaceAll(HYPHEN, EMPTY) : EMPTY;
+ final String normalized = Normalizer.normalize(nohyphen, Normalizer.Form.NFD);
+
+ return REMOVE_DIACRITICALS_PATTERN.matcher(normalized).replaceAll("").toLowerCase();
+ }
+
+ public static String normalizeKeywords(String input) {
+ return (input != null) ? input.replaceAll(LIST_DELIMITERS, SPACE) : EMPTY;
+ }
}
diff --git a/src/com/android/settings/search2/IntentPayload.java b/src/com/android/settings/search2/IntentPayload.java
index 1ef3797..3e1049e 100644
--- a/src/com/android/settings/search2/IntentPayload.java
+++ b/src/com/android/settings/search2/IntentPayload.java
@@ -18,7 +18,6 @@
import android.content.Intent;
import android.os.Parcel;
-import com.android.internal.annotations.VisibleForTesting;
/**
* Encapsulates the standard intent based results as seen in first party apps and Settings results.
diff --git a/src/com/android/settings/search2/ResultPayloadUtils.java b/src/com/android/settings/search2/ResultPayloadUtils.java
new file mode 100644
index 0000000..41d15e2
--- /dev/null
+++ b/src/com/android/settings/search2/ResultPayloadUtils.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ *
+ */
+
+package com.android.settings.search2;
+
+import android.os.BadParcelableException;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.io.StreamCorruptedException;
+
+/**
+ * Utility class to Marshall and Unmarshall the payloads stored in the SQLite Database
+ */
+public class ResultPayloadUtils {
+
+ private static final String TAG = "PayloadUtil";
+
+ public static byte[] marshall(ResultPayload payload) {
+ Parcel parcel = Parcel.obtain();
+ payload.writeToParcel(parcel, 0);
+ byte[] bytes = parcel.marshall();
+ parcel.recycle();
+ return bytes;
+ }
+
+ public static <T> T unmarshall(byte[] bytes, Parcelable.Creator<T> creator) {
+ T result;
+ Parcel parcel = unmarshall(bytes);
+ result = creator.createFromParcel(parcel);
+ parcel.recycle();
+ return result;
+ }
+
+ private static Parcel unmarshall(byte[] bytes) {
+ Parcel parcel = Parcel.obtain();
+ parcel.unmarshall(bytes, 0, bytes.length);
+ parcel.setDataPosition(0);
+ return parcel;
+ }
+}
diff --git a/src/com/android/settings/search2/XMLParserUtil.java b/src/com/android/settings/search2/XmlParserUtils.java
similarity index 75%
rename from src/com/android/settings/search2/XMLParserUtil.java
rename to src/com/android/settings/search2/XmlParserUtils.java
index dcb3cbb..748d4b0 100644
--- a/src/com/android/settings/search2/XMLParserUtil.java
+++ b/src/com/android/settings/search2/XmlParserUtils.java
@@ -30,19 +30,10 @@
/**
* Utility class to parse elements of XML preferences
*/
-public class XMLParserUtil {
-
- private static final String NON_BREAKING_HYPHEN = "\u2011";
- private static final String EMPTY = "";
- private static final String LIST_DELIMITERS = "[,]\\s*";
- private static final String HYPHEN = "-";
- private static final String SPACE = " ";
+public class XmlParserUtils {
private static final String ENTRIES_SEPARATOR = "|";
- private static final Pattern REMOVE_DIACRITICALS_PATTERN
- = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
-
public static String getDataKey(Context context, AttributeSet attrs) {
return getData(context, attrs,
com.android.internal.R.styleable.Preference,
@@ -83,7 +74,7 @@
return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords);
}
- public static String getData(Context context, AttributeSet set, int[] attrs, int resId) {
+ private static String getData(Context context, AttributeSet set, int[] attrs, int resId) {
final TypedArray sa = context.obtainStyledAttributes(set, attrs);
final TypedValue tv = sa.peekValue(resId);
@@ -98,7 +89,7 @@
return (data != null) ? data.toString() : null;
}
- public static String getDataEntries(Context context, AttributeSet set, int[] attrs, int resId) {
+ private static String getDataEntries(Context context, AttributeSet set, int[] attrs, int resId) {
final TypedArray sa = context.obtainStyledAttributes(set, attrs);
final TypedValue tv = sa.peekValue(resId);
@@ -119,19 +110,4 @@
}
return result.toString();
}
-
- public static String normalizeHyphen(String input) {
- return (input != null) ? input.replaceAll(NON_BREAKING_HYPHEN, HYPHEN) : EMPTY;
- }
-
- public static String normalizeString(String input) {
- final String nohyphen = (input != null) ? input.replaceAll(HYPHEN, EMPTY) : EMPTY;
- final String normalized = Normalizer.normalize(nohyphen, Normalizer.Form.NFD);
-
- return REMOVE_DIACRITICALS_PATTERN.matcher(normalized).replaceAll("").toLowerCase();
- }
-
- public static String normalizeKeywords(String input) {
- return (input != null) ? input.replaceAll(LIST_DELIMITERS, SPACE) : EMPTY;
- }
}
diff --git a/src/com/android/settings/survey/SurveyMixin.java b/src/com/android/settings/survey/SurveyMixin.java
new file mode 100644
index 0000000..5e0754a
--- /dev/null
+++ b/src/com/android/settings/survey/SurveyMixin.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+package com.android.settings.survey;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnPause;
+import com.android.settings.core.lifecycle.events.OnResume;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.overlay.SurveyFeatureProvider;
+
+/**
+ * attaches extra, survey related work to the onResume method of registered observable classes
+ * in settings. This allows new classes to automatically support settings provided the extend
+ * one of the relevant classes in com.android.settings.lifecycle.
+ */
+public class SurveyMixin implements LifecycleObserver, OnResume, OnPause {
+
+ private String mName;
+ private InstrumentedPreferenceFragment mFragment;
+ private BroadcastReceiver mReceiver;
+
+ /**
+ * A mixin that attempts to perform survey related tasks right before onResume is called
+ * in a Settings PreferenceFragment. This will allow for remote updating and creation of
+ * surveys.
+ * @param fragment The fragment that this mixin will be attached to.
+ * @param fragmentName The simple name of the fragment.
+ */
+ public SurveyMixin(InstrumentedPreferenceFragment fragment, String fragmentName) {
+ mName = fragmentName;
+ mFragment = fragment;
+ }
+
+ @Override
+ public void onResume() {
+ Activity activity = mFragment.getActivity();
+
+ // guard against the activity not existing yet or the feature being disabled
+ if (activity != null) {
+ SurveyFeatureProvider provider =
+ FeatureFactory.getFactory(activity).getSurveyFeatureProvider(activity);
+ if (provider != null) {
+
+ // Try to download a survey if there is none available, show the survey otherwise
+ String id = provider.getSurveyId(activity, mName);
+ if (provider.getSurveyExpirationDate(activity, id) <= -1) {
+ // register the receiver to show the survey on completion.
+ mReceiver = provider.createAndRegisterReceiver(activity);
+ provider.downloadSurvey(activity, id, "fakeData");
+ } else {
+ provider.showSurveyIfAvailable(activity, id);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onPause() {
+ Activity activity = mFragment.getActivity();
+ if (mReceiver != null && activity != null) {
+ SurveyFeatureProvider provider =
+ FeatureFactory.getFactory(activity).getSurveyFeatureProvider(activity);
+ provider.unregisterReceiver(activity, mReceiver);
+ }
+ }
+}
diff --git a/src/com/android/settings/widget/FooterPreference.java b/src/com/android/settings/widget/FooterPreference.java
new file mode 100644
index 0000000..4a0d128
--- /dev/null
+++ b/src/com/android/settings/widget/FooterPreference.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.widget;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.text.method.LinkMovementMethod;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+/**
+ * A custom preference acting as "footer" of a page. It has a field for icon and text. It is added
+ * to screen as the last preference.
+ */
+public class FooterPreference extends Preference {
+
+ static final int ORDER_FOOTER = Integer.MAX_VALUE - 1;
+ static final String KEY_FOOTER = "footer_preference";
+
+ public FooterPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init();
+ }
+
+ public FooterPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ public FooterPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public FooterPreference(Context context) {
+ super(context);
+ init();
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ TextView title = (TextView) holder.itemView.findViewById(android.R.id.title);
+ title.setMovementMethod(new LinkMovementMethod());
+ }
+
+ private void init() {
+ setLayoutResource(R.layout.preference_footer);
+ setIcon(R.drawable.ic_info_outline_24dp);
+ setKey(KEY_FOOTER);
+ setOrder(ORDER_FOOTER);
+ }
+}
diff --git a/src/com/android/settings/widget/FooterPreferenceMixin.java b/src/com/android/settings/widget/FooterPreferenceMixin.java
new file mode 100644
index 0000000..53e3d75
--- /dev/null
+++ b/src/com/android/settings/widget/FooterPreferenceMixin.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.widget;
+
+import android.content.Context;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.SetPreferenceScreen;
+
+public class FooterPreferenceMixin implements LifecycleObserver, SetPreferenceScreen {
+
+ private final PreferenceFragment mFragment;
+ private FooterPreference mFooterPreference;
+
+ public FooterPreferenceMixin(PreferenceFragment fragment, Lifecycle lifecycle) {
+ mFragment = fragment;
+ lifecycle.addObserver(this);
+ }
+
+ @Override
+ public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+ if (mFooterPreference != null) {
+ preferenceScreen.addPreference(mFooterPreference);
+ }
+ }
+
+ /**
+ * Creates a new {@link FooterPreference}.
+ */
+ public FooterPreference createFooterPreference() {
+ final PreferenceScreen screen = mFragment.getPreferenceScreen();
+ if (mFooterPreference != null && screen != null) {
+ screen.removePreference(mFooterPreference);
+ }
+ mFooterPreference = new FooterPreference(getPrefContext());
+
+ if (screen != null) {
+ screen.addPreference(mFooterPreference);
+ }
+ return mFooterPreference;
+ }
+
+ /**
+ * Returns an UI context with theme properly set for new Preference objects.
+ */
+ private Context getPrefContext() {
+ return mFragment.getPreferenceManager().getContext();
+ }
+
+ public boolean hasFooter() {
+ return mFooterPreference != null;
+ }
+}
+
diff --git a/src/com/android/settings/widget/PreferenceDividerDecoration.java b/src/com/android/settings/widget/PreferenceDividerDecoration.java
new file mode 100644
index 0000000..4466a3d
--- /dev/null
+++ b/src/com/android/settings/widget/PreferenceDividerDecoration.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.widget;
+
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.support.v4.view.ViewCompat;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceGroupAdapter;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration {
+
+ private Drawable mDivider;
+ private int mDividerHeight;
+
+ public void setDivider(Drawable divider) {
+ if (divider != null) {
+ mDividerHeight = divider.getIntrinsicHeight();
+ } else {
+ mDividerHeight = 0;
+ }
+ mDivider = divider;
+ }
+
+ public void setDividerHeight(int dividerHeight) {
+ mDividerHeight = dividerHeight;
+ }
+
+ @Override
+ public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ if (mDivider == null) {
+ return;
+ }
+ final int childCount = parent.getChildCount();
+ final int width = parent.getWidth();
+ for (int childViewIndex = 0; childViewIndex < childCount; childViewIndex++) {
+ final View view = parent.getChildAt(childViewIndex);
+ if (shouldDrawDividerAbove(view, parent)) {
+ int top = (int) ViewCompat.getY(view);
+ mDivider.setBounds(0, top, width, top + mDividerHeight);
+ mDivider.draw(c);
+ }
+ }
+ }
+
+ private boolean shouldDrawDividerAbove(View view, RecyclerView parent) {
+ final RecyclerView.Adapter adapter = parent.getAdapter();
+ if (adapter == null || !(adapter instanceof PreferenceGroupAdapter)) {
+ return false;
+ }
+ final PreferenceGroupAdapter prefAdapter = (PreferenceGroupAdapter) adapter;
+ final int adapterPosition = parent.getChildAdapterPosition(view);
+ if (adapterPosition == RecyclerView.NO_POSITION) {
+ return false;
+ }
+ final Preference pref = prefAdapter.getItem(adapterPosition);
+ if (pref instanceof PreferenceCategory) {
+ return adapterPosition != 0;
+ }
+ return pref instanceof FooterPreference;
+ }
+}
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index 9739ef9..01ae99c 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -19,14 +19,10 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Resources;
-import android.net.NetworkScoreManager;
-import android.net.NetworkScorerAppManager;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
-import android.os.UserManager;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.ListPreference;
@@ -35,12 +31,9 @@
import android.util.Log;
import android.widget.Toast;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.AppListSwitchPreference;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
-
-import java.util.Collection;
import java.util.List;
public class ConfigureWifiSettings extends SettingsPreferenceFragment
@@ -53,12 +46,9 @@
private static final String KEY_NOTIFY_OPEN_NETWORKS = "notify_open_networks";
private static final String KEY_SLEEP_POLICY = "sleep_policy";
private static final String KEY_CELLULAR_FALLBACK = "wifi_cellular_data_fallback";
- private static final String KEY_WIFI_ASSISTANT = "wifi_assistant";
+ private static final String KEY_ALLOW_RECOMMENDATIONS = "allow_recommendations";
private WifiManager mWifiManager;
- private NetworkScoreManager mNetworkScoreManager;
- private AppListSwitchPreference mWifiAssistantPreference;
-
private IntentFilter mFilter;
@Override
@@ -74,8 +64,6 @@
mFilter = new IntentFilter();
mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- mNetworkScoreManager =
- (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE);
}
@Override
@@ -119,15 +107,10 @@
}
}
- mWifiAssistantPreference = (AppListSwitchPreference) findPreference(KEY_WIFI_ASSISTANT);
- Collection<NetworkScorerAppManager.NetworkScorerAppData> scorers =
- new NetworkScorerAppManager(context).getAllValidScorers();
- if (UserManager.get(context).isAdminUser() && !scorers.isEmpty()) {
- mWifiAssistantPreference.setOnPreferenceChangeListener(this);
- initWifiAssistantPreference(scorers);
- } else if (mWifiAssistantPreference != null) {
- getPreferenceScreen().removePreference(mWifiAssistantPreference);
- }
+ SwitchPreference allowRecommendations =
+ (SwitchPreference) findPreference(KEY_ALLOW_RECOMMENDATIONS);
+ allowRecommendations.setChecked(Settings.Global.getInt(getContentResolver(),
+ Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) == 1);
ListPreference sleepPolicyPref = (ListPreference) findPreference(KEY_SLEEP_POLICY);
if (sleepPolicyPref != null) {
@@ -187,6 +170,10 @@
String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
Settings.Global.putString(getContentResolver(), settingName,
((SwitchPreference) preference).isChecked() ? "1" : null);
+ } else if (KEY_ALLOW_RECOMMENDATIONS.equals(key)) {
+ Settings.Global.putInt(getActivity().getContentResolver(),
+ Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+ ((SwitchPreference) preference).isChecked() ? 1 : 0);
} else {
return super.onPreferenceTreeClick(preference);
}
@@ -198,34 +185,6 @@
final Context context = getActivity();
String key = preference.getKey();
- if (KEY_WIFI_ASSISTANT.equals(key)) {
- NetworkScorerAppManager.NetworkScorerAppData wifiAssistant =
- new NetworkScorerAppManager(context).getScorer((String) newValue);
- if (wifiAssistant == null) {
- mNetworkScoreManager.setActiveScorer(null);
- return true;
- }
-
- Intent intent = new Intent();
- if (wifiAssistant.mConfigurationActivityClassName != null) {
- // App has a custom configuration activity; launch that.
- // This custom activity will be responsible for launching the system
- // dialog.
- intent.setClassName(wifiAssistant.mPackageName,
- wifiAssistant.mConfigurationActivityClassName);
- } else {
- // Fall back on the system dialog.
- intent.setAction(NetworkScoreManager.ACTION_CHANGE_ACTIVE);
- intent.putExtra(NetworkScoreManager.EXTRA_PACKAGE_NAME,
- wifiAssistant.mPackageName);
- }
-
- startActivity(intent);
- // Don't update the preference widget state until the child activity returns.
- // It will be updated in onResume after the activity finishes.
- return false;
- }
-
if (KEY_SLEEP_POLICY.equals(key)) {
try {
String stringValue = (String) newValue;
@@ -259,19 +218,6 @@
wifiIpAddressPref.setSelectable(false);
}
- private void initWifiAssistantPreference(
- Collection<NetworkScorerAppManager.NetworkScorerAppData> scorers) {
- int count = scorers.size();
- String[] packageNames = new String[count];
- int i = 0;
- for (NetworkScorerAppManager.NetworkScorerAppData scorer : scorers) {
- packageNames[i] = scorer.mPackageName;
- i++;
- }
- mWifiAssistantPreference.setPackageNames(packageNames,
- mNetworkScoreManager.getActiveScorerPackage());
- }
-
@Override
public int getMetricsCategory() {
return MetricsEvent.CONFIGURE_WIFI;
diff --git a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
deleted file mode 100644
index 68f28ee..0000000
--- a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.wifi;
-
-import android.app.Dialog;
-import android.net.wifi.WifiConfiguration;
-import android.os.Bundle;
-import android.support.v7.preference.PreferenceScreen;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import com.android.settings.R;
-import com.android.settings.SetupWizardUtils;
-import com.android.setupwizardlib.SetupWizardListLayout;
-import com.android.setupwizardlib.view.NavigationBar;
-
-/**
- * This customized version of WifiSettings is shown to the user only during Setup Wizard. Menu
- * is not shown, clicking on an access point will auto-advance to the next screen (once connected),
- * and, if the user opts to skip ahead without a wifi connection, a warning message alerts of
- * possible carrier data charges or missing software updates.
- */
-public class WifiSettingsForSetupWizard extends WifiSettings {
-
- private static final String TAG = "WifiSettingsForSetupWizard";
-
- private SetupWizardListLayout mLayout;
- private View mAddOtherNetworkItem;
- private TextView mEmptyFooter;
- private View mMacAddressFooter;
- private boolean mListLastEmpty = false;
-
- @Override
- public View onCreateView(final LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- mLayout = (SetupWizardListLayout)
- inflater.inflate(R.layout.setup_wifi_layout, container, false);
- final ListView list = mLayout.getListView();
-
- mAddOtherNetworkItem = inflater.inflate(R.layout.setup_wifi_add_network, list, false);
- list.addFooterView(mAddOtherNetworkItem, null, true);
- mAddOtherNetworkItem.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mWifiManager.isWifiEnabled()) {
- onAddNetworkPressed();
- }
- }
- });
-
- mMacAddressFooter = inflater.inflate(R.layout.setup_wifi_mac_address, list, false);
- list.addFooterView(mMacAddressFooter, null, false);
-
- final NavigationBar navigationBar = mLayout.getNavigationBar();
- if (navigationBar != null) {
- WifiSetupActivity activity = (WifiSetupActivity) getActivity();
- activity.onNavigationBarCreated(navigationBar);
- }
-
- return mLayout;
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- if (hasNextButton()) {
- getNextButton().setVisibility(View.GONE);
- }
-
- updateMacAddress();
- }
-
- @Override
- public void onAccessPointsChanged() {
- super.onAccessPointsChanged();
- PreferenceScreen preferenceScreen = getPreferenceScreen();
- updateFooter(preferenceScreen == null || preferenceScreen.getPreferenceCount() == 0);
- }
-
- @Override
- public void onWifiStateChanged(int state) {
- super.onWifiStateChanged(state);
- updateMacAddress();
- }
-
- @Override
- public void registerForContextMenu(View view) {
- // Suppressed during setup wizard
- }
-
- @Override
- /* package */ WifiEnabler createWifiEnabler() {
- // Not shown during setup wizard
- return null;
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- // Do not show menu during setup wizard
- }
-
- @Override
- public Dialog onCreateDialog(int dialogId) {
- final Dialog dialog = super.onCreateDialog(dialogId);
- SetupWizardUtils.applyImmersiveFlags(dialog);
- return dialog;
- }
-
- @Override
- protected void connect(final WifiConfiguration config, boolean isSavedNetwork) {
- WifiSetupActivity activity = (WifiSetupActivity) getActivity();
- activity.networkSelected();
- super.connect(config, isSavedNetwork);
- }
-
- @Override
- protected void connect(final int networkId, boolean isSavedNetwork) {
- WifiSetupActivity activity = (WifiSetupActivity) getActivity();
- activity.networkSelected();
- super.connect(networkId, isSavedNetwork);
- }
-
- @Override
- protected TextView initEmptyTextView() {
- final LayoutInflater inflater = LayoutInflater.from(getActivity());
- mEmptyFooter = (TextView) inflater.inflate(R.layout.setup_wifi_empty, getListView(), false);
- return mEmptyFooter;
- }
-
- protected void updateFooter(boolean isEmpty) {
- if (isEmpty != mListLastEmpty) {
- if (isEmpty) {
- setFooterView(mEmptyFooter);
- } else {
- LinearLayout layout = new LinearLayout(getContext());
- layout.setOrientation(LinearLayout.VERTICAL);
- layout.addView(mAddOtherNetworkItem);
- layout.addView(mMacAddressFooter);
- setFooterView(layout);
- }
- mListLastEmpty = isEmpty;
- }
- }
-
- @Override
- public View setPinnedHeaderView(int layoutResId) {
- // Pinned header is not supported in setup wizard
- return null;
- }
-
- @Override
- public void setPinnedHeaderView(View pinnedHeader) {
- // Pinned header is not supported in setup wizard
- }
-
- @Override
- protected void setProgressBarVisible(boolean visible) {
- if (mLayout != null) {
- if (visible) {
- mLayout.showProgressBar();
- } else {
- mLayout.hideProgressBar();
- }
- }
- }
-
- private void updateMacAddress() {
- if (mMacAddressFooter != null) {
- String macAddress = null;
- if (mWifiManager != null) {
- android.net.wifi.WifiInfo connectionInfo = mWifiManager.getConnectionInfo();
- if (connectionInfo != null) {
- macAddress = connectionInfo.getMacAddress();
- }
- }
- final TextView macAddressTextView =
- (TextView) mMacAddressFooter.findViewById(R.id.mac_address);
- macAddressTextView.setText(!TextUtils.isEmpty(macAddress) ?
- macAddress : getString(R.string.status_unavailable));
- }
- }
-}
diff --git a/src/com/android/settings/wifi/WifiSetupActivity.java b/src/com/android/settings/wifi/WifiSetupActivity.java
deleted file mode 100644
index f640b6e..0000000
--- a/src/com/android/settings/wifi/WifiSetupActivity.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.wifi;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.wifi.WifiManager;
-import android.os.Bundle;
-import android.support.v14.preference.PreferenceFragment;
-import android.util.Log;
-
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.ButtonBarHandler;
-import com.android.settings.R;
-import com.android.settings.SetupWizardUtils;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import com.android.setupwizardlib.view.NavigationBar;
-
-public class WifiSetupActivity extends WifiPickerActivity
- implements ButtonBarHandler, NavigationBar.NavigationBarListener {
- private static final String TAG = "WifiSetupActivity";
-
- // this boolean extra specifies whether to auto finish when connection is established
- private static final String EXTRA_AUTO_FINISH_ON_CONNECT = "wifi_auto_finish_on_connect";
-
- // This boolean extra specifies whether network is required
- private static final String EXTRA_IS_NETWORK_REQUIRED = "is_network_required";
-
- // This boolean extra specifies whether wifi is required
- private static final String EXTRA_IS_WIFI_REQUIRED = "is_wifi_required";
-
- // Whether auto finish is suspended until user connects to an access point
- private static final String EXTRA_REQUIRE_USER_NETWORK_SELECTION =
- "wifi_require_user_network_selection";
-
- // Key for whether the user selected network in saved instance state bundle
- private static final String PARAM_USER_SELECTED_NETWORK = "userSelectedNetwork";
-
- // Activity result when pressing the Skip button
- private static final int RESULT_SKIP = Activity.RESULT_FIRST_USER;
-
- // Whether to auto finish when the user selected a network and successfully connected
- private boolean mAutoFinishOnConnection;
- // Whether network is required to proceed. This is decided in SUW and passed in as an extra.
- private boolean mIsNetworkRequired;
- // Whether wifi is required to proceed. This is decided in SUW and passed in as an extra.
- private boolean mIsWifiRequired;
- // Whether the user connected to a network. This excludes the auto-connecting by the system.
- private boolean mUserSelectedNetwork;
- // Whether the device is connected to WiFi
- private boolean mWifiConnected;
-
- private NavigationBar mNavigationBar;
-
- private IntentFilter mFilter = new IntentFilter();
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // Refresh the connection state with the latest connection info. Use the connection info
- // from ConnectivityManager instead of the one attached in the intent to make sure
- // we have the most up-to-date connection state. b/17511772
- refreshConnectionState();
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- final Intent intent = getIntent();
- mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
-
- mAutoFinishOnConnection = intent.getBooleanExtra(EXTRA_AUTO_FINISH_ON_CONNECT, false);
- mIsNetworkRequired = intent.getBooleanExtra(EXTRA_IS_NETWORK_REQUIRED, false);
- mIsWifiRequired = intent.getBooleanExtra(EXTRA_IS_WIFI_REQUIRED, false);
- // Behave like the user already selected a network if we do not require selection
- mUserSelectedNetwork = !intent.getBooleanExtra(EXTRA_REQUIRE_USER_NETWORK_SELECTION, false);
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putBoolean(PARAM_USER_SELECTED_NETWORK, mUserSelectedNetwork);
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- mUserSelectedNetwork = savedInstanceState.getBoolean(PARAM_USER_SELECTED_NETWORK, true);
- }
-
- private boolean isWifiConnected() {
- final ConnectivityManager connectivity = (ConnectivityManager)
- getSystemService(Context.CONNECTIVITY_SERVICE);
- boolean wifiConnected = connectivity != null &&
- connectivity.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected();
- mWifiConnected = wifiConnected;
- return wifiConnected;
- }
-
- private void refreshConnectionState() {
- if (isWifiConnected()) {
- if (mAutoFinishOnConnection && mUserSelectedNetwork) {
- Log.d(TAG, "Auto-finishing with connection");
- finish(Activity.RESULT_OK);
- // Require a user selection before auto-finishing next time we are here. The user
- // can either connect to a different network or press "next" to proceed.
- mUserSelectedNetwork = false;
- }
- setNextButtonText(R.string.suw_next_button_label);
- setNextButtonEnabled(true);
- } else if (mIsWifiRequired || (mIsNetworkRequired && !isNetworkConnected())) {
- // We do not want the user to skip wifi setting if
- // - wifi is required, but wifi connection hasn't been established yet;
- // - or network is required, but no valid connection has been established.
- setNextButtonText(R.string.skip_label);
- setNextButtonEnabled(false);
- } else {
- // In other cases, user can choose to skip. Specifically these cases are
- // - wifi is not required;
- // - and network is not required;
- // - or network is required and a valid connection has been established.
- setNextButtonText(R.string.skip_label);
- setNextButtonEnabled(true);
- }
- }
-
- private void setNextButtonEnabled(boolean enabled) {
- if (mNavigationBar != null) {
- mNavigationBar.getNextButton().setEnabled(enabled);
- }
- }
-
- private void setNextButtonText(int resId) {
- if (mNavigationBar != null) {
- mNavigationBar.getNextButton().setText(resId);
- }
- }
-
- /* package */ void networkSelected() {
- Log.d(TAG, "Network selected by user");
- mUserSelectedNetwork = true;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- registerReceiver(mReceiver, mFilter);
- refreshConnectionState();
- }
-
- @Override
- public void onPause() {
- unregisterReceiver(mReceiver);
- super.onPause();
- }
-
- @Override
- protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
- resid = SetupWizardUtils.getTheme(getIntent());
- super.onApplyThemeResource(theme, resid, first);
- }
-
- @Override
- protected boolean isValidFragment(String fragmentName) {
- return WifiSettingsForSetupWizard.class.getName().equals(fragmentName);
- }
-
- @Override
- /* package */ Class<? extends PreferenceFragment> getWifiSettingsClass() {
- return WifiSettingsForSetupWizard.class;
- }
-
- /**
- * Complete this activity and return the results to the caller.
- */
- public void finish(int resultCode) {
- Log.d(TAG, "finishing, resultCode=" + resultCode);
- setResult(resultCode);
- finish();
- }
-
- public void onNavigationBarCreated(final NavigationBar bar) {
- mNavigationBar = bar;
- bar.setNavigationBarListener(this);
- SetupWizardUtils.setImmersiveMode(this);
- }
-
- @Override
- public void onNavigateBack() {
- onBackPressed();
- }
-
- @Override
- public void onNavigateNext() {
- if (mWifiConnected) {
- finish(RESULT_OK);
- } else {
- // Warn of possible data charges if there is a network connection, or lack of updates
- // if there is none.
- final int message = isNetworkConnected() ? R.string.wifi_skipped_message :
- R.string.wifi_and_mobile_skipped_message;
- WifiSkipDialog.newInstance(message).show(getFragmentManager(), "dialog");
- }
- }
-
- /**
- * @return True if there is a valid network connection, whether it is via WiFi, mobile data or
- * other means.
- */
- private boolean isNetworkConnected() {
- final ConnectivityManager connectivity = (ConnectivityManager)
- getSystemService(Context.CONNECTIVITY_SERVICE);
- if (connectivity == null) {
- return false;
- }
- final NetworkInfo info = connectivity.getActiveNetworkInfo();
- return info != null && info.isConnected();
- }
-
- public static class WifiSkipDialog extends InstrumentedDialogFragment {
- public static WifiSkipDialog newInstance(int messageRes) {
- final Bundle args = new Bundle();
- args.putInt("messageRes", messageRes);
- final WifiSkipDialog dialog = new WifiSkipDialog();
- dialog.setArguments(args);
- return dialog;
- }
-
- public WifiSkipDialog() {
- // no-arg constructor for fragment
- }
-
- @Override
- public int getMetricsCategory() {
- return MetricsProto.MetricsEvent.DIALOG_WIFI_SKIP;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- int messageRes = getArguments().getInt("messageRes");
- final AlertDialog dialog = new AlertDialog.Builder(getActivity())
- .setMessage(messageRes)
- .setCancelable(false)
- .setPositiveButton(R.string.wifi_skip_anyway,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- WifiSetupActivity activity = (WifiSetupActivity) getActivity();
- activity.finish(RESULT_SKIP);
- }
- })
- .setNegativeButton(R.string.wifi_dont_skip,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- }
- })
- .create();
- SetupWizardUtils.applyImmersiveFlags(dialog);
- return dialog;
- }
- }
-}
diff --git a/tests/robotests/assets/grandfather_not_in_search_index_provider_registry b/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
index 29f3816..a95fc0b 100644
--- a/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
+++ b/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
@@ -1,3 +1,2 @@
com.android.settings.display.ScreenZoomPreferenceFragmentForSetupWizard
-com.android.settings.wifi.WifiSettingsForSetupWizard
com.android.settings.print.PrintServiceSettingsFragment
diff --git a/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
new file mode 100644
index 0000000..4d8101f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.TwoStatePreference;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.DefaultRingtonePreference;
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+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.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.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+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 WorkSoundPreferenceControllerTest {
+
+ private static final String KEY_WORK_CATEGORY = "sound_work_settings_section";
+ private static final String KEY_WORK_USE_PERSONAL_SOUNDS = "work_use_personal_sounds";
+ private static final String KEY_WORK_PHONE_RINGTONE = "work_ringtone";
+ private static final String KEY_WORK_NOTIFICATION_RINGTONE = "work_notification_ringtone";
+ private static final String KEY_WORK_ALARM_RINGTONE = "work_alarm_ringtone";
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private AudioHelper mAudioHelper;
+ @Mock
+ private SoundSettings mFragment;
+
+ private WorkSoundPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+ mController = new WorkSoundPreferenceController(mContext, mFragment, null, mAudioHelper);
+ }
+
+ @Test
+ public void isAvailable_managedProfileAndNotSingleVolume_shouldReturnTrue() {
+ when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+ when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
+ .thenReturn(UserHandle.myUserId());
+ when(mAudioHelper.isSingleVolume()).thenReturn(false);
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_noManagedProfile_shouldReturnFalse() {
+ when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+ when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
+ .thenReturn(UserHandle.USER_NULL);
+ when(mAudioHelper.isSingleVolume()).thenReturn(false);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_singleVolume_shouldReturnFalse() {
+ when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+ when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
+ .thenReturn(UserHandle.myUserId());
+ when(mAudioHelper.isSingleVolume()).thenReturn(true);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void onResume_available_shouldAddPreferenceCategory() {
+ when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+ when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
+ .thenReturn(UserHandle.myUserId());
+ when(mAudioHelper.isSingleVolume()).thenReturn(false);
+ when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+ when(mScreen.findPreference(KEY_WORK_CATEGORY))
+ .thenReturn(mock(PreferenceGroup.class));
+ when(mScreen.findPreference(KEY_WORK_USE_PERSONAL_SOUNDS))
+ .thenReturn(mock(TwoStatePreference.class));
+ when(mScreen.findPreference(KEY_WORK_PHONE_RINGTONE))
+ .thenReturn(mock(DefaultRingtonePreference.class));
+ when(mScreen.findPreference(KEY_WORK_NOTIFICATION_RINGTONE))
+ .thenReturn(mock(DefaultRingtonePreference.class));
+ when(mScreen.findPreference(KEY_WORK_ALARM_RINGTONE))
+ .thenReturn(mock(DefaultRingtonePreference.class));
+ when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext);
+
+ mController.onResume();
+
+ verify(mFragment).addPreferencesFromResource(R.xml.sound_work_settings);
+ }
+
+ @Test
+ public void onResume_notAvailable_shouldNotAddPreferenceCategory() {
+ when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+ when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
+ .thenReturn(UserHandle.USER_NULL);
+ when(mAudioHelper.isSingleVolume()).thenReturn(true);
+ when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+
+ mController.onResume();
+
+ verify(mFragment, never()).addPreferencesFromResource(anyInt());
+ }
+
+ @Test
+ public void onPreferenceChange_shouldUpdateSummary() {
+ final Preference preference = mock(Preference.class);
+ when(preference.getKey()).thenReturn(KEY_WORK_PHONE_RINGTONE);
+
+ mController.onPreferenceChange(preference, "hello");
+
+ verify(preference).setSummary(anyString());
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java b/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java
new file mode 100644
index 0000000..8b363b0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java
@@ -0,0 +1,616 @@
+/*
+ * 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.
+ *
+ */
+
+package com.android.settings.search;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.provider.SearchIndexableResource;
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.search2.DatabaseIndexingManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class DatabaseIndexingManagerTest {
+ private final String localeStr = "en_US";
+
+ private final int rank = 42;
+ private final String title = "title\u2011title";
+ private final String updatedTitle = "title-title";
+ private final String normalizedTitle = "titletitle";
+ private final String summaryOn = "summary\u2011on";
+ private final String updatedSummaryOn = "summary-on";
+ private final String normalizedSummaryOn = "summaryon";
+ private final String summaryOff = "summary\u2011off";
+ private final String updatedSummaryOff ="summary-off";
+ private final String normalizedSummaryOff = "summaryoff";
+ private final String entries = "entries";
+ private final String keywords = "keywords, keywordss, keywordsss";
+ private final String spaceDelimittedKeywords = "keywords keywordss keywordsss";
+ private final String screenTitle = "screen title";
+ private final String className = "class name";
+ private final int iconResId = 0xff;
+ private final String action = "action";
+ private final String targetPackage = "target package";
+ private final String targetClass = "target class";
+ private final String packageName = "package name";
+ private final String key = "key";
+ private final int userId = -1;
+ private final boolean enabled = true;
+
+ private Context mContext;
+ private DatabaseIndexingManager mManager;
+ private SQLiteDatabase mDb;
+
+ @Before
+ public void setUp() {
+ mContext = ShadowApplication.getInstance().getApplicationContext();
+ mManager = spy(new DatabaseIndexingManager(mContext, mContext.getPackageName()));
+ mDb = IndexDatabaseHelper.getInstance(mContext).getWritableDatabase();
+ }
+
+ @After
+ public void cleanUp() {
+ Field instance;
+ Class clazz = IndexDatabaseHelper.class;
+ try {
+ instance = clazz.getDeclaredField("sSingleton");
+ instance.setAccessible(true);
+ instance.set(null, null);
+ } catch (Exception e) {
+ throw new RuntimeException();
+ }
+ }
+
+ @Test
+ public void testDatabaseSchema() {
+ Cursor dbCursor = mDb.query("prefs_index", null, null, null, null, null, null);
+ List<String> columnNames = new ArrayList<>(Arrays.asList(dbCursor.getColumnNames()));
+ // Note that docid is not included.
+ List<String> expColumnNames = new ArrayList<>(Arrays.asList(new String[ ]{
+ "locale",
+ "data_rank",
+ "data_title",
+ "data_title_normalized",
+ "data_summary_on",
+ "data_summary_on_normalized",
+ "data_summary_off",
+ "data_summary_off_normalized",
+ "data_entries",
+ "data_keywords",
+ "class_name",
+ "screen_title",
+ "intent_action",
+ "intent_target_package",
+ "intent_target_class",
+ "icon",
+ "enabled",
+ "data_key_reference",
+ "user_id",
+ "payload_type",
+ "payload"
+ }));
+ // Prevent database schema regressions
+ assertThat(columnNames).containsAllIn(expColumnNames);
+ }
+
+ // Tests for the flow: IndexOneRaw -> UpdateOneRowWithFilteredData -> UpdateOneRow
+
+ @Test
+ public void testInsertRawColumn_RowInserted() {
+ SearchIndexableRaw raw = getFakeRaw();
+ mManager.indexOneSearchIndexableData(mDb, localeStr, raw, null /* Non-indexable keys */);
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
+ assertThat(cursor.getCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void testInsertRawColumn_RowMatches() {
+ SearchIndexableRaw raw = getFakeRaw();
+ mManager.indexOneSearchIndexableData(mDb, localeStr, raw, null /* Non-indexable keys */);
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
+ cursor.moveToPosition(0);
+
+ // Locale
+ assertThat(cursor.getString(0)).isEqualTo(localeStr);
+ // Data Rank
+ assertThat(cursor.getInt(1)).isEqualTo(raw.rank);
+ // Data Title
+ assertThat(cursor.getString(2)).isEqualTo(updatedTitle);
+ // Normalized Title
+ assertThat(cursor.getString(3)).isEqualTo(normalizedTitle);
+ // Summary On
+ assertThat(cursor.getString(4)).isEqualTo(updatedSummaryOn);
+ // Summary On Normalized
+ assertThat(cursor.getString(5)).isEqualTo(normalizedSummaryOn);
+ // Summary Off
+ assertThat(cursor.getString(6)).isEqualTo(updatedSummaryOff);
+ // Summary off normalized
+ assertThat(cursor.getString(7)).isEqualTo(normalizedSummaryOff);
+ // Entries
+ assertThat(cursor.getString(8)).isEqualTo(raw.entries);
+ // Keywords
+ assertThat(cursor.getString(9)).isEqualTo(spaceDelimittedKeywords);
+ // Screen Title
+ assertThat(cursor.getString(10)).isEqualTo(raw.screenTitle);
+ // Class Name
+ assertThat(cursor.getString(11)).isEqualTo(raw.className);
+ // Icon
+ assertThat(cursor.getInt(12)).isEqualTo(raw.iconResId);
+ // Intent Action
+ assertThat(cursor.getString(13)).isEqualTo(raw.intentAction);
+ // Target Package
+ assertThat(cursor.getString(14)).isEqualTo(raw.intentTargetPackage);
+ // Target Class
+ assertThat(cursor.getString(15)).isEqualTo(raw.intentTargetClass);
+ // Enabled
+ assertThat(cursor.getInt(16) == 1).isEqualTo(raw.enabled);
+ // Data ref key
+ assertThat(cursor.getString(17)).isNotNull();
+ // User Id
+ assertThat(cursor.getInt(18)).isEqualTo(raw.userId);
+ // Payload Type - default is 0
+ assertThat(cursor.getInt(19)).isEqualTo(0);
+ // Payload
+ assertThat(cursor.getBlob(20)).isNull();
+ }
+
+ @Test
+ public void testInsertRawColumnMismatchedLocale_NoRowInserted() {
+ SearchIndexableRaw raw = getFakeRaw("ca-fr");
+ mManager.indexOneSearchIndexableData(mDb, localeStr, raw, null /* Non-indexable keys */);
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
+ assertThat(cursor.getCount()).isEqualTo(0);
+ }
+
+ // Tests for the flow: IndexOneResource -> IndexFromResource ->
+ // UpdateOneRowWithFilteredData -> UpdateOneRow
+
+ @Test
+ public void testNullResource_NothingInserted() {
+ mManager.indexOneSearchIndexableData(mDb, localeStr, null /* searchIndexableResource */,
+ new HashMap<String, List<String>>());
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
+ assertThat(cursor.getCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void testAddResource_RowsInserted() {
+ SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
+ mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
+ new HashMap<String, List<String>>());
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
+ assertThat(cursor.getCount()).isEqualTo(6);
+ }
+
+ @Test
+ public void testAddResourceHeader_RowsMatch() {
+ SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
+ mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
+ new HashMap<String, List<String>>());
+
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
+ cursor.moveToPosition(1);
+
+ // Locale
+ assertThat(cursor.getString(0)).isEqualTo(localeStr);
+ // Data Rank
+ assertThat(cursor.getInt(1)).isEqualTo(rank);
+ // Data Title
+ assertThat(cursor.getString(2)).isEqualTo("Apps");
+ // Normalized Title
+ assertThat(cursor.getString(3)).isEqualTo("apps");
+ // Summary On
+ assertThat(cursor.getString(4)).isEqualTo("Manage apps, set up quick launch shortcuts");
+ // Summary On Normalized
+ assertThat(cursor.getString(5)).isEqualTo("manage apps, set up quick launch shortcuts");
+ // Summary Off - only on for checkbox preferences
+ assertThat(cursor.getString(6)).isEmpty();
+ // Summary off normalized - only on for checkbox preferences
+ assertThat(cursor.getString(7)).isEmpty();
+ // Entries - only on for list preferences
+ assertThat(cursor.getString(8)).isNull();
+ // Keywords
+ assertThat(cursor.getString(9)).isEmpty();
+ // Screen Title
+ assertThat(cursor.getString(10)).isEqualTo("Apps");
+ // Class Name
+ assertThat(cursor.getString(11)).isEqualTo(className);
+ // Icon
+ assertThat(cursor.getInt(12)).isEqualTo(iconResId);
+ // Intent Action
+ assertThat(cursor.getString(13)).isEqualTo(action);
+ // Target Package
+ assertThat(cursor.getString(14)).isEqualTo(targetPackage);
+ // Target Class
+ assertThat(cursor.getString(15)).isEqualTo(targetClass);
+ // Enabled
+ assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
+ // Data ref key
+ assertThat(cursor.getString(17)).isEqualTo("applications_settings");
+ // User Id
+ assertThat(cursor.getInt(18)).isEqualTo(userId);
+ // Payload Type - default is 0
+ assertThat(cursor.getInt(19)).isEqualTo(0);
+ // Payload - should be updated to real payloads as controllers are added
+ assertThat(cursor.getBlob(20)).isNull();
+ }
+
+ @Test
+ public void testAddResourceCustomSetting_RowsMatch() {
+ SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
+ mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
+ new HashMap<String, List<String>>());
+
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
+ cursor.moveToPosition(0);
+
+ // Locale
+ assertThat(cursor.getString(0)).isEqualTo(localeStr);
+ // Data Rank
+ assertThat(cursor.getInt(1)).isEqualTo(rank);
+ // Data Title
+ assertThat(cursor.getString(2)).isEqualTo("Swipe for notifications");
+ // Normalized Title
+ assertThat(cursor.getString(3)).isEqualTo("swipe for notifications");
+ // Summary On
+ assertThat(cursor.getString(4)).isEqualTo("To check your notifications, " +
+ "swipe down on the fingerprint sensor on the back of your phone.");
+ // Summary On Normalized
+ assertThat(cursor.getString(5)).isEqualTo("to check your notifications, " +
+ "swipe down on the fingerprint sensor on the back of your phone.");
+ // Summary Off - only on for checkbox preferences
+ assertThat(cursor.getString(6)).isEmpty();
+ // Summary off normalized - only on for checkbox preferences
+ assertThat(cursor.getString(7)).isEmpty();
+ // Entries - only on for list preferences
+ assertThat(cursor.getString(8)).isNull();
+ // Keywords
+ assertThat(cursor.getString(9)).isEmpty();
+ // Screen Title
+ assertThat(cursor.getString(10)).isEqualTo("Gestures");
+ // Class Name
+ assertThat(cursor.getString(11)).isEqualTo(className);
+ // Icon
+ assertThat(cursor.getInt(12)).isEqualTo(iconResId);
+ // Intent Action
+ assertThat(cursor.getString(13)).isEqualTo(action);
+ // Target Package
+ assertThat(cursor.getString(14)).isEqualTo(targetPackage);
+ // Target Class
+ assertThat(cursor.getString(15)).isEqualTo(targetClass);
+ // Enabled
+ assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
+ // Data ref key
+ assertThat(cursor.getString(17)).isEqualTo("gesture_swipe_down_fingerprint");
+ // User Id
+ assertThat(cursor.getInt(18)).isEqualTo(userId);
+ // Payload Type - default is 0
+ assertThat(cursor.getInt(19)).isEqualTo(0);
+ // Payload - should be updated to real payloads as controllers are added
+ assertThat(cursor.getBlob(20)).isNull();
+ }
+
+ @Test
+ public void testAddResourceCheckboxPreference_RowsMatch() {
+ SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
+ mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
+ new HashMap<String, List<String>>());
+
+ /* Should return 6 results, with the following titles:
+ * Advanced Settings, Apps, Manage Apps, Preferred install location, Running Services
+ */
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
+ cursor.moveToPosition(0);
+ // Locale
+ assertThat(cursor.getString(0)).isEqualTo(localeStr);
+ // Data Rank
+ assertThat(cursor.getInt(1)).isEqualTo(rank);
+ // Data Title
+ assertThat(cursor.getString(2)).isEqualTo("Advanced settings");
+ // Normalized Title
+ assertThat(cursor.getString(3)).isEqualTo("advanced settings");
+ // Summary On
+ assertThat(cursor.getString(4)).isEqualTo("Enable more settings options");
+ // Summary On Normalized
+ assertThat(cursor.getString(5)).isEqualTo("enable more settings options");
+ // Summary Off
+ assertThat(cursor.getString(6)).isEqualTo("Enable more settings options");
+ // Summary Off
+ assertThat(cursor.getString(7)).isEqualTo("enable more settings options");
+ // Entries - only on for list preferences
+ assertThat(cursor.getString(8)).isNull();
+ // Keywords
+ assertThat(cursor.getString(9)).isEmpty();
+ // Screen Title
+ assertThat(cursor.getString(10)).isEqualTo("Apps");
+ // Class Name
+ assertThat(cursor.getString(11)).isEqualTo(className);
+ // Icon
+ assertThat(cursor.getInt(12)).isEqualTo(iconResId);
+ // Intent Action
+ assertThat(cursor.getString(13)).isEqualTo(action);
+ // Target Package
+ assertThat(cursor.getString(14)).isEqualTo(targetPackage);
+ // Target Class
+ assertThat(cursor.getString(15)).isEqualTo(targetClass);
+ // Enabled
+ assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
+ // Data ref key
+ assertThat(cursor.getString(17)).isEqualTo("toggle_advanced_settings");
+ // User Id
+ assertThat(cursor.getInt(18)).isEqualTo(userId);
+ // Payload Type - default is 0
+ assertThat(cursor.getInt(19)).isEqualTo(0);
+ // Payload - should be updated to real payloads as controllers are added
+ assertThat(cursor.getBlob(20)).isNull();
+ }
+
+ @Test
+ public void testAddResourceListPreference_RowsMatch() {
+ SearchIndexableResource resource = getFakeResource(R.xml.application_settings);
+ mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
+ new HashMap<String, List<String>>());
+
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
+ cursor.moveToPosition(3);
+ // Locale
+ assertThat(cursor.getString(0)).isEqualTo(localeStr);
+ // Data Rank
+ assertThat(cursor.getInt(1)).isEqualTo(rank);
+ // Data Title
+ assertThat(cursor.getString(2)).isEqualTo("Preferred install location");
+ // Normalized Title
+ assertThat(cursor.getString(3)).isEqualTo("preferred install location");
+ // Summary On
+ assertThat(cursor.getString(4)).isEqualTo("Change the preferred installation location for new apps");
+ // Summary On Normalized
+ assertThat(cursor.getString(5)).isEqualTo("change the preferred installation location for new apps");
+ // Summary Off - only on for checkbox preferences
+ assertThat(cursor.getString(6)).isEmpty();
+ // Summary off normalized - only on for checkbox preferences
+ assertThat(cursor.getString(7)).isEmpty();
+ // Entries - only on for list preferences
+ assertThat(cursor.getString(8)).isEqualTo("Internal device storage|Removable SD card|" +
+ "Let the system decide|");
+ // Keywords
+ assertThat(cursor.getString(9)).isEmpty();
+ // Screen Title
+ assertThat(cursor.getString(10)).isEqualTo("Apps");
+ // Class Name
+ assertThat(cursor.getString(11)).isEqualTo(className);
+ // Icon
+ assertThat(cursor.getInt(12)).isEqualTo(iconResId);
+ // Intent Action
+ assertThat(cursor.getString(13)).isEqualTo(action);
+ // Target Package
+ assertThat(cursor.getString(14)).isEqualTo(targetPackage);
+ // Target Class
+ assertThat(cursor.getString(15)).isEqualTo(targetClass);
+ // Enabled
+ assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
+ // Data ref key
+ assertThat(cursor.getString(17)).isEqualTo("app_install_location");
+ // User Id
+ assertThat(cursor.getInt(18)).isEqualTo(userId);
+ // Payload Type - default is 0
+ assertThat(cursor.getInt(19)).isEqualTo(0);
+ // Payload - should be updated to real payloads as controllers are added
+ assertThat(cursor.getBlob(20)).isNull();
+ }
+
+ // Tests for the flow: IndexOneResource -> IndexFromProvider -> IndexFromResource ->
+ // UpdateOneRowWithFilteredData -> UpdateOneRow
+
+ @Test
+ public void testResourceProvider_RowInserted() {
+ SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
+ resource.xmlResId = 0;
+ resource.className = "com.android.settings.display.ScreenZoomSettings";
+
+ mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
+ new HashMap<String, List<String>>());
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
+ assertThat(cursor.getCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void testResourceProvider_Matches() {
+ SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
+ resource.xmlResId = 0;
+ resource.className = "com.android.settings.display.ScreenZoomSettings";
+
+ mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
+ new HashMap<String, List<String>>());
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
+ cursor.moveToPosition(0);
+
+ // Locale
+ assertThat(cursor.getString(0)).isEqualTo(localeStr);
+ // Data Rank
+ assertThat(cursor.getInt(1)).isEqualTo(rank);
+ // Data Title
+ assertThat(cursor.getString(2)).isEqualTo("Display size");
+ // Normalized Title
+ assertThat(cursor.getString(3)).isEqualTo("display size");
+ // Summary On
+ assertThat(cursor.getString(4)).isEmpty();
+ // Summary On Normalized
+ assertThat(cursor.getString(5)).isEmpty();
+ // Summary Off - only on for checkbox preferences
+ assertThat(cursor.getString(6)).isEmpty();
+ // Summary off normalized - only on for checkbox preferences
+ assertThat(cursor.getString(7)).isEmpty();
+ // Entries - only on for list preferences
+ assertThat(cursor.getString(8)).isNull();
+ // Keywords
+ assertThat(cursor.getString(9)).isEqualTo("display density screen zoom scale scaling");
+ // Screen Title
+ assertThat(cursor.getString(10)).isEqualTo("Display size");
+ // Class Name
+ assertThat(cursor.getString(11))
+ .isEqualTo("com.android.settings.display.ScreenZoomSettings");
+ // Icon
+ assertThat(cursor.getInt(12)).isEqualTo(iconResId);
+ // Intent Action
+ assertThat(cursor.getString(13)).isNull();
+ // Target Package
+ assertThat(cursor.getString(14)).isNull();
+ // Target Class
+ assertThat(cursor.getString(15)).isNull();
+ // Enabled
+ assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
+ // Data ref key
+ assertThat(cursor.getString(17)).isNull();
+ // User Id
+ assertThat(cursor.getInt(18)).isEqualTo(userId);
+ // Payload Type - default is 0
+ assertThat(cursor.getInt(19)).isEqualTo(0);
+ // Payload - should be updated to real payloads as controllers are added
+ assertThat(cursor.getBlob(20)).isNull();
+ }
+
+ @Test
+ public void testResourceProvider_ResourceRowInserted() {
+ SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
+ resource.xmlResId = 0;
+ resource.className = "com.android.settings.LegalSettings";
+
+ mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
+ new HashMap<String, List<String>>());
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
+ assertThat(cursor.getCount()).isEqualTo(2);
+ }
+
+ @Test
+ public void testResourceProvider_ResourceRowMatches() {
+ SearchIndexableResource resource = getFakeResource(R.xml.gesture_settings);
+ resource.xmlResId = 0;
+ resource.className = "com.android.settings.LegalSettings";
+
+ mManager.indexOneSearchIndexableData(mDb, localeStr, resource,
+ new HashMap<String, List<String>>());
+ Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index ORDER BY data_title", null);
+ cursor.moveToPosition(0);
+
+ // Locale
+ assertThat(cursor.getString(0)).isEqualTo(localeStr);
+ // Data Rank
+ assertThat(cursor.getInt(1)).isEqualTo(rank);
+ // Data Title
+ assertThat(cursor.getString(2)).isEqualTo("Legal information");
+ // Normalized Title
+ assertThat(cursor.getString(3)).isEqualTo("legal information");
+ // Summary On
+ assertThat(cursor.getString(4)).isEmpty();
+ // Summary On Normalized
+ assertThat(cursor.getString(5)).isEmpty();
+ // Summary Off - only on for checkbox preferences
+ assertThat(cursor.getString(6)).isEmpty();
+ // Summary off normalized - only on for checkbox preferences
+ assertThat(cursor.getString(7)).isEmpty();
+ // Entries - only on for list preferences
+ assertThat(cursor.getString(8)).isNull();
+ // Keywords
+ assertThat(cursor.getString(9)).isEmpty();
+ // Screen Title
+ assertThat(cursor.getString(10)).isEqualTo("Legal information");
+ // Class Name
+ assertThat(cursor.getString(11))
+ .isEqualTo("com.android.settings.LegalSettings");
+ // Icon
+ assertThat(cursor.getInt(12)).isEqualTo(iconResId);
+ // Intent Action
+ assertThat(cursor.getString(13)).isNull();
+ // Target Package
+ assertThat(cursor.getString(14)).isNull();
+ // Target Class
+ assertThat(cursor.getString(15)).isNull();
+ // Enabled
+ assertThat(cursor.getInt(16) == 1).isEqualTo(enabled);
+ // Data ref key
+ assertThat(cursor.getString(17)).isNull();
+ // User Id
+ assertThat(cursor.getInt(18)).isEqualTo(userId);
+ // Payload Type - default is 0
+ assertThat(cursor.getInt(19)).isEqualTo(0);
+ // Payload - should be updated to real payloads as controllers are added
+ assertThat(cursor.getBlob(20)).isNull();
+ }
+
+ // Util functions
+
+ private SearchIndexableRaw getFakeRaw() {
+ return getFakeRaw(localeStr);
+ }
+
+ private SearchIndexableRaw getFakeRaw(String localeStr) {
+ SearchIndexableRaw data = new SearchIndexableRaw(mContext);
+ data.locale = new Locale(localeStr);
+ data.rank = rank;
+ data.title = title;
+ data.summaryOn = summaryOn;
+ data.summaryOff = summaryOff;
+ data.entries = entries;
+ data.keywords = keywords;
+ data.screenTitle = screenTitle;
+ data.className = className;
+ data.packageName = packageName;
+ data.iconResId = iconResId;
+ data.intentAction = action;
+ data.intentTargetPackage = targetPackage;
+ data.intentTargetClass = targetClass;
+ data.key = key;
+ data.userId = userId;
+ data.enabled = enabled;
+ return data;
+ }
+
+ private SearchIndexableResource getFakeResource(int xml) {
+ SearchIndexableResource sir = new SearchIndexableResource(mContext);
+ sir.rank = rank;
+ sir.xmlResId = xml;
+ sir.className = className;
+ sir.packageName = packageName;
+ sir.iconResId = iconResId;
+ sir.intentAction = action;
+ sir.intentTargetPackage = targetPackage;
+ sir.intentTargetClass = targetClass;
+ sir.enabled = enabled;
+ return sir;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/search/DatabaseRowTest.java b/tests/robotests/src/com/android/settings/search/DatabaseRowTest.java
new file mode 100644
index 0000000..34626bd
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search/DatabaseRowTest.java
@@ -0,0 +1,150 @@
+/*
+ * 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 static for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.settings.search;
+
+import android.content.Intent;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.search2.DatabaseIndexingManager.DatabaseRow;
+import com.android.settings.search2.DatabaseIndexingManager.DatabaseRow.Builder;
+import com.android.settings.search2.IntentPayload;
+import com.android.settings.search2.ResultPayload;
+import com.android.settings.search2.ResultPayloadUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class DatabaseRowTest {
+ private Builder builder;
+
+ private static final String LOCALE = "locale";
+ private static final String UPDATED_TITLE = "updated title";
+ private static final String NORMALIZED_TITLE = "normal title";
+ private static final String UPDATED_SUMMARY_ON = "updated summary on";
+ private static final String NORMALIZED_SUMMARY_ON = "normalized summary on";
+ private static final String UPDATED_SUMMARY_OFF = "updated summary off";
+ private static final String NORMALIZED_SUMMARY_OFF = "normalized summary off";
+ private static final String ENTRIES = "entries";
+ private static final String CLASS_NAME = "class name";
+ private static final String SCREEN_TITLE = "sceen title";
+ private static final int ICON_RES_ID = 0xff;
+ private static final int RANK = 1;
+ private static final String SPACE_DELIMITED_KEYWORDS = "keywords";
+ private static final String INTENT_ACTION = "intent action";
+ private static final String INTENT_TARGET_PACKAGE = "target package";
+ private static final String INTENT_TARGET_CLASS = "target class";
+ private static final boolean ENABLED = true;
+ private static final String KEY = "key";
+ private static final int USER_ID = 1;
+ private static IntentPayload intentPayload;
+
+ private final String EXTRA_KEY = "key";
+ private final String EXTRA_VALUE = "value";
+
+ @Before
+ public void setUp() {
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_KEY, EXTRA_VALUE);
+ intentPayload = new IntentPayload(intent);
+
+ builder = new DatabaseRow.Builder();
+ }
+
+ @Test
+ public void testFullRowBuild_NonNull() {
+ DatabaseRow row = generateRow();
+ assertThat(row).isNotNull();
+ }
+
+ @Test
+ public void testPrimativesBuild_NoDataLoss() {
+ DatabaseRow row = generateRow();
+
+ assertThat(row.locale).isEqualTo(LOCALE);
+ assertThat(row.updatedTitle).isEqualTo(UPDATED_TITLE);
+ assertThat(row.normalizedTitle).isEqualTo(NORMALIZED_TITLE);
+ assertThat(row.updatedSummaryOn).isEqualTo(UPDATED_SUMMARY_ON);
+ assertThat(row.normalizedSummaryOn).isEqualTo(NORMALIZED_SUMMARY_ON);
+ assertThat(row.updatedSummaryOff).isEqualTo(UPDATED_SUMMARY_OFF);
+ assertThat(row.normalizedSummaryOff).isEqualTo(NORMALIZED_SUMMARY_OFF);
+ assertThat(row.entries).isEqualTo(ENTRIES);
+ assertThat(row.className).isEqualTo(CLASS_NAME);
+ assertThat(row.screenTitle).isEqualTo(SCREEN_TITLE);
+ assertThat(row.iconResId).isEqualTo(ICON_RES_ID);
+ assertThat(row.rank).isEqualTo(RANK);
+ assertThat(row.spaceDelimitedKeywords).isEqualTo(SPACE_DELIMITED_KEYWORDS);
+ assertThat(row.intentAction).isEqualTo(INTENT_ACTION);
+ assertThat(row.intentTargetClass).isEqualTo(INTENT_TARGET_CLASS);
+ assertThat(row.intentTargetPackage).isEqualTo(INTENT_TARGET_PACKAGE);
+ assertThat(row.enabled).isEqualTo(ENABLED);
+ assertThat(row.userId).isEqualTo(USER_ID);
+ assertThat(row.key).isEqualTo(KEY);
+ assertThat(row.payloadType).isEqualTo(ResultPayload.PayloadType.INTENT);
+ }
+
+ @Test
+ public void testPayload_PayloadTypeAdded() {
+ DatabaseRow row = generateRow();
+ byte[] marshalledPayload = row.payload;
+ IntentPayload payload = ResultPayloadUtils.unmarshall(marshalledPayload,
+ IntentPayload.CREATOR);
+
+ Intent intent = payload.intent;
+ assertThat(intent.getExtra(EXTRA_KEY)).isEqualTo(EXTRA_VALUE);
+ }
+
+ @Test
+ public void TestNullPayload_NoCrash() {
+ Builder builder = new Builder();
+ builder.setPayload(null);
+ DatabaseRow row = builder.build();
+
+ assertThat(row.payload).isNull();
+ }
+
+ private DatabaseRow generateRow() {
+ builder.setLocale(LOCALE)
+ .setUpdatedTitle(UPDATED_TITLE)
+ .setNormalizedTitle(NORMALIZED_TITLE)
+ .setUpdatedSummaryOn(UPDATED_SUMMARY_ON)
+ .setNormalizedSummaryOn(NORMALIZED_SUMMARY_ON)
+ .setUpdatedSummaryOff(UPDATED_SUMMARY_OFF)
+ .setNormalizedSummaryOff(NORMALIZED_SUMMARY_OFF)
+ .setEntries(ENTRIES)
+ .setClassName(CLASS_NAME)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIconResId(ICON_RES_ID)
+ .setRank(RANK)
+ .setSpaceDelimitedKeywords(SPACE_DELIMITED_KEYWORDS)
+ .setIntentAction(INTENT_ACTION)
+ .setIntentTargetPackage(INTENT_TARGET_PACKAGE)
+ .setIntentTargetClass(INTENT_TARGET_CLASS)
+ .setEnabled(ENABLED)
+ .setKey(KEY)
+ .setUserId(USER_ID)
+ .setPayload(intentPayload);
+
+ return(builder.build());
+ }
+}
+;
diff --git a/tests/robotests/src/com/android/settings/search/ResultPayloadUtilsTest.java b/tests/robotests/src/com/android/settings/search/ResultPayloadUtilsTest.java
new file mode 100644
index 0000000..3875d86
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search/ResultPayloadUtilsTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ *
+ */
+
+package com.android.settings.search;
+
+import android.content.Intent;
+import android.os.BadParcelableException;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.search2.IntentPayload;
+import com.android.settings.search2.ResultPayloadUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import java.io.StreamCorruptedException;
+
+import static com.google.common.truth.Truth.assertThat;
+import static junit.framework.Assert.fail;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ResultPayloadUtilsTest {
+ private IntentPayload payload;
+
+ private final String EXTRA_KEY = "key";
+ private final String EXTRA_VALUE = "value";
+
+ @Before
+ public void setUp() {
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_KEY, EXTRA_VALUE);
+ payload = new IntentPayload(intent);
+ }
+
+ @Test
+ public void testUnmarshallBadData_ExceptionThrown() {
+ byte[] badData = "I'm going to fail :)".getBytes();
+ try {
+ ResultPayloadUtils.unmarshall(badData, IntentPayload.CREATOR);
+ fail("unmarshall should throw exception");
+ } catch ( RuntimeException e) {
+ assertThat(e).isNotNull();
+ }
+ }
+
+ @Test
+ public void testMarshallIntentPayload_NonEmptyArray() {
+ byte[] marshalledPayload = ResultPayloadUtils.marshall(payload);
+ assertThat(marshalledPayload).isNotNull();
+ assertThat(marshalledPayload).isNotEmpty();
+ }
+
+ @Test
+ public void testUnmarshall_PreservedData() {
+ byte[] marshalledPayload = ResultPayloadUtils.marshall(payload);
+ IntentPayload newPayload = ResultPayloadUtils.unmarshall(marshalledPayload,
+ IntentPayload.CREATOR);
+
+ String originalIntentExtra = payload.intent.getStringExtra(EXTRA_KEY);
+ String copiedIntentExtra = newPayload.intent.getStringExtra(EXTRA_KEY);
+ assertThat(originalIntentExtra).isEqualTo(copiedIntentExtra);
+ }
+
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/search/SearchResultBuilderTest.java b/tests/robotests/src/com/android/settings/search/SearchResultBuilderTest.java
index 5649a95..f83b595 100644
--- a/tests/robotests/src/com/android/settings/search/SearchResultBuilderTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchResultBuilderTest.java
@@ -100,24 +100,18 @@
}
@Test
- public void testNoRank_BuildSearchResultException() {
+ public void testNoRank_BuildSearchResult_pass() {
mBuilder.addTitle(mTitle)
.addSummary(mSummary)
.addBreadcrumbs(mBreadcrumbs)
.addIcon(mIcon)
.addPayload(mResultPayload);
- SearchResult result = null;
- try {
- result = mBuilder.build();
- } catch (IllegalArgumentException e) {
- // passes.
- }
- assertThat(result).isNull();
+ assertThat(mBuilder.build()).isNotNull();
}
@Test
- public void testNoIcon_BuildSearchResultException() {
+ public void testNoIcon_BuildSearchResult_pass() {
mBuilder.addTitle(mTitle)
.addSummary(mSummary)
.addRank(mRank)
diff --git a/tests/robotests/src/com/android/settings/search/XmlParserUtilTest.java b/tests/robotests/src/com/android/settings/search/XmlParserUtilTest.java
new file mode 100644
index 0000000..d0c691c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search/XmlParserUtilTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ *
+ */
+
+package com.android.settings.search;
+
+import android.content.res.XmlResourceParser;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.R;
+
+import com.android.settings.search2.XmlParserUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+import org.xmlpull.v1.XmlPullParser;
+
+import static com.google.common.truth.Truth.assertThat;
+
+/**
+ * These tests use a series of preferences that have specific attributes which are sometimes
+ * uncommon (such as summaryOn).
+ *
+ * If changing a preference file breaks a test in this test file, please replace its reference
+ * with another preference with a matchin replacement attribute.
+ */
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class XmlParserUtilTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = ShadowApplication.getInstance().getApplicationContext();
+ }
+
+ @Test
+ public void testDataTitleValid_ReturnsPreferenceTitle() {
+ XmlResourceParser parser = getChildByType(R.xml.gesture_settings,
+ "com.android.settings.gestures.GesturePreference");
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String title = XmlParserUtils.getDataTitle(mContext, attrs);
+ String expTitle = mContext.getString(R.string.fingerprint_swipe_for_notifications_title);
+ assertThat(title).isEqualTo(expTitle);
+ }
+
+ @Test
+ public void testDataKeywordsValid_ReturnsPreferenceKeywords() {
+ XmlResourceParser parser = getParentPrimedParser(R.xml.gesture_settings);
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String keywords = XmlParserUtils.getDataKeywords(mContext, attrs);
+ String expKeywords = mContext.getString(R.string.keywords_gesture);
+ assertThat(keywords).isEqualTo(expKeywords);
+ }
+
+ @Test
+ public void testDataKeyValid_ReturnsPreferenceKey() {
+ XmlResourceParser parser = getChildByType(R.xml.gesture_settings,
+ "com.android.settings.gestures.GesturePreference");
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String key = XmlParserUtils.getDataKey(mContext, attrs);
+ String expKey = "gesture_swipe_down_fingerprint";
+ assertThat(key).isEqualTo(expKey);
+ }
+
+ @Test
+ public void testDataSummaryValid_ReturnsPreferenceSummary() {
+ XmlResourceParser parser = getChildByType(R.xml.gesture_settings,
+ "com.android.settings.gestures.GesturePreference");
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String summary = XmlParserUtils.getDataSummary(mContext, attrs);
+ String expSummary = mContext.getString(R.string.fingerprint_swipe_for_notifications_summary);
+ assertThat(summary).isEqualTo(expSummary);
+
+ }
+
+ @Test
+ public void testDataSummaryOnValid_ReturnsPreferenceSummaryOn() {
+ XmlResourceParser parser = getChildByType(R.xml.application_settings, "CheckBoxPreference");
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String summary = XmlParserUtils.getDataSummaryOn(mContext, attrs);
+ String expSummary = mContext.getString(R.string.advanced_settings_summary);
+ assertThat(summary).isEqualTo(expSummary);
+ }
+
+ @Test
+ public void testDataSummaryOffValid_ReturnsPreferenceSummaryOff() {
+ XmlResourceParser parser = getChildByType(R.xml.application_settings, "CheckBoxPreference");
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String summary = XmlParserUtils.getDataSummaryOff(mContext, attrs);
+ String expSummary = mContext.getString(R.string.advanced_settings_summary);
+ assertThat(summary).isEqualTo(expSummary);
+ }
+
+ @Test
+ public void testDataEntriesValid_ReturnsPreferenceEntries() {
+ XmlResourceParser parser = getChildByType(R.xml.application_settings, "ListPreference");
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String entries = XmlParserUtils.getDataEntries(mContext, attrs);
+ String[] expEntries = mContext.getResources()
+ .getStringArray(R.array.app_install_location_entries);
+ for (int i = 0; i < expEntries.length; i++) {
+ assertThat(entries).contains(expEntries[i]);
+ }
+ }
+
+ // Null checks
+
+ @Test
+ public void testDataKeyInvalid_ReturnsNull() {
+ XmlResourceParser parser = getParentPrimedParser(R.xml.gesture_settings);
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String key = XmlParserUtils.getDataKey(mContext, attrs);
+ assertThat(key).isNull();
+ }
+
+ @Test
+ public void testDataSummaryInvalid_ReturnsNull() {
+ XmlResourceParser parser = getParentPrimedParser(R.xml.gesture_settings);
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String summary = XmlParserUtils.getDataSummary(mContext, attrs);
+ assertThat(summary).isNull();
+ }
+
+ @Test
+ public void testDataSummaryOffInvalid_ReturnsNull() {
+ XmlResourceParser parser = getParentPrimedParser(R.xml.gesture_settings);
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String summaryOff = XmlParserUtils.getDataSummaryOff(mContext, attrs);
+ assertThat(summaryOff).isNull();
+ }
+
+ @Test
+ public void testDataEntriesInvalid_ReturnsNull() {
+ XmlResourceParser parser = getParentPrimedParser(R.xml.gesture_settings);
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ String entries = XmlParserUtils.getDataEntries(mContext, attrs);
+ assertThat(entries).isNull();
+ }
+
+ /**
+ * @param resId the ID for the XML preference
+ * @return an XML resource parser that points to the start tag
+ */
+ private XmlResourceParser getParentPrimedParser(int resId) {
+ XmlResourceParser parser = null;
+ try {
+ parser = mContext.getResources().getXml(resId);
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ }
+ } catch (Exception e) {
+
+ }
+ return parser;
+ }
+
+ private XmlResourceParser getChildByType(int resId, String xmlType) {
+ XmlResourceParser parser = null;
+ try {
+ parser = mContext.getResources().getXml(resId);
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ }
+ while(parser.getName() != xmlType) {
+ parser.next();
+ }
+ } catch (Exception e) {
+
+ }
+ return parser;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/survey/SurveyMixinTest.java b/tests/robotests/src/com/android/settings/survey/SurveyMixinTest.java
new file mode 100644
index 0000000..20c50ce
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/survey/SurveyMixinTest.java
@@ -0,0 +1,143 @@
+package com.android.settings.survey;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.overlay.SurveyFeatureProvider;
+import com.android.settings.testutils.FakeFeatureFactory;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SurveyMixinTest {
+
+ private static final String FAKE_KEY = "fake_key";
+ private static final String FAKE_SURVEY_ID = "fake_id";
+
+ private FakeFeatureFactory mFactory;
+ private Context mContext;
+ private SurveyFeatureProvider mProvider;
+ @Mock
+ private BroadcastReceiver mReceiver;
+ @Mock
+ private InstrumentedPreferenceFragment mFragment;
+
+ @Before
+ public void setUp() {
+ // set up the fakefeature factory to mock out the survey provider
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application.getApplicationContext());
+ FakeFeatureFactory.setupForTest(mContext);
+ mFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+ mProvider = mFactory.getSurveyFeatureProvider(mContext);
+ when(mProvider.getSurveyId(any(), eq(FAKE_KEY))).thenReturn(FAKE_SURVEY_ID);
+ }
+
+ @Test
+ public void onResume_triesRegisteringReceiverAndDownloadingWhenNoSurveyDetected() {
+ // Pretend there is no survey in memory
+ when(mProvider.getSurveyExpirationDate(any(), any())).thenReturn(-1L);
+
+ // Pretend we are an activity that is starting up
+ Activity temp = Robolectric.setupActivity(Activity.class);
+ when(mFragment.getActivity()).thenReturn(temp);
+ SurveyMixin mixin = new SurveyMixin(mFragment, FAKE_KEY);
+ mixin.onResume();
+
+ // Verify that a download was attempted
+ verify(mProvider, times(1)).downloadSurvey(any(), any(), any());
+ // Verify that we registered a receiver for download completion broadcasts
+ verify(mProvider, times(1)).createAndRegisterReceiver(any());
+ // Verify we did not try to show a survey
+ verify(mProvider, never()).showSurveyIfAvailable(any(), any());
+ }
+
+ @Test
+ public void onResume_triesShowingSurveyWhenOneIsPresent() {
+ // Pretend there is a survey in memory
+ when(mProvider.getSurveyExpirationDate(any(), any())).thenReturn(0L);
+
+ // Pretend we are an activity that is starting up
+ Activity temp = Robolectric.setupActivity(Activity.class);
+ when(mFragment.getActivity()).thenReturn(temp);
+ SurveyMixin mixin = new SurveyMixin(mFragment, FAKE_KEY);
+ mixin.onResume();
+
+ // Verify that a download was not attempted
+ verify(mProvider, never()).downloadSurvey(any(), any(), any());
+ // Verify that we did not register a receiver
+ verify(mProvider, never()).createAndRegisterReceiver(any());
+ // Verify we tried to show a survey
+ verify(mProvider, times(1)).showSurveyIfAvailable(any(), any());
+ }
+
+ @Test
+ public void onResume_doesNothingWhenActivityIsNull() {
+ // Pretend the activity died somewhere in the process
+ when(mFragment.getActivity()).thenReturn(null);
+ SurveyMixin mixin = new SurveyMixin(mFragment, FAKE_KEY);
+ mixin.onResume();
+
+ // Verify we don't try showing or downloading a survey
+ verify(mProvider, never()).showSurveyIfAvailable(any(), any());
+ verify(mProvider, never()).downloadSurvey(any(), any(), any());
+ }
+
+ @Test
+ public void onPause_removesReceiverWhenInstantiated() {
+ // Pretend there is a survey in memory
+ when(mProvider.getSurveyExpirationDate(any(), any())).thenReturn(-1L);
+
+ // Pretend we are an activity that starts and stops
+ Activity temp = Robolectric.setupActivity(Activity.class);
+ when(mFragment.getActivity()).thenReturn(temp);
+ when(mProvider.createAndRegisterReceiver(any())).thenReturn(mReceiver);
+ SurveyMixin mixin = new SurveyMixin(mFragment, FAKE_KEY);
+ mixin.onResume();
+ mixin.onPause();
+
+ // Verify we remove the receiver
+ verify(mProvider, times(1)).unregisterReceiver(any(), any());
+ }
+
+ @Test
+ public void onPause_doesNothingWhenActivityOrReceiverNull() {
+ // Pretend there is a survey in memory
+ when(mProvider.getSurveyExpirationDate(any(), any())).thenReturn(-1L);
+
+ // Pretend we are an activity that fails to create a receiver properly
+ Activity temp = Robolectric.setupActivity(Activity.class);
+ when(mFragment.getActivity()).thenReturn(temp);
+ SurveyMixin mixin = new SurveyMixin(mFragment, FAKE_KEY);
+ mixin.onPause();
+
+ // Verify we do nothing
+ verify(mProvider, never()).unregisterReceiver(any(), any());
+
+ // pretend the activity died before onPause
+ when(mFragment.getActivity()).thenReturn(null);
+ mixin.onPause();
+
+ // Verify we do nothing
+ verify(mProvider, never()).unregisterReceiver(any(), any());
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/widget/FooterPreferenceMixinTest.java b/tests/robotests/src/com/android/settings/widget/FooterPreferenceMixinTest.java
new file mode 100644
index 0000000..21ebb25
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/FooterPreferenceMixinTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.widget;
+
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+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;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class FooterPreferenceMixinTest {
+
+ @Mock
+ private PreferenceFragment mFragment;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Lifecycle mLifecycle;
+ private FooterPreferenceMixin mMixin;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mLifecycle = new Lifecycle();
+ when(mFragment.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
+ when(mFragment.getPreferenceManager().getContext())
+ .thenReturn(ShadowApplication.getInstance().getApplicationContext());
+ mMixin = new FooterPreferenceMixin(mFragment, mLifecycle);
+ }
+
+ @Test
+ public void createFooter_screenNotAvailable_noCrash() {
+ assertThat(mMixin.createFooterPreference()).isNotNull();
+ }
+
+ @Test
+ public void createFooter_screenAvailable_canAttachToScreen() {
+ when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+
+ final FooterPreference preference = mMixin.createFooterPreference();
+
+ assertThat(preference).isNotNull();
+ verify(mScreen).addPreference(preference);
+ }
+
+ @Test
+ public void createFooter_screenAvailableDelayed_canAttachToScreen() {
+ final FooterPreference preference = mMixin.createFooterPreference();
+
+ mLifecycle.setPreferenceScreen(mScreen);
+
+ assertThat(preference).isNotNull();
+ verify(mScreen).addPreference(preference);
+ }
+
+ @Test
+ public void createFooterTwice_screenAvailable_replaceOldFooter() {
+ when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+
+ mMixin.createFooterPreference();
+ mMixin.createFooterPreference();
+
+ verify(mScreen).removePreference(any(FooterPreference.class));
+ verify(mScreen, times(2)).addPreference(any(FooterPreference.class));
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/widget/FooterPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/FooterPreferenceTest.java
new file mode 100644
index 0000000..8dbcc20
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/FooterPreferenceTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.widget;
+
+import android.content.Context;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.text.method.LinkMovementMethod;
+import android.view.LayoutInflater;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class FooterPreferenceTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = ShadowApplication.getInstance().getApplicationContext();
+ }
+
+ @Test
+ public void createNewPreference_shouldSetKeyAndOrder() {
+ final FooterPreference preference = new FooterPreference(mContext);
+
+ assertThat(preference.getKey()).isEqualTo(FooterPreference.KEY_FOOTER);
+ assertThat(preference.getOrder()).isEqualTo(FooterPreference.ORDER_FOOTER);
+ }
+
+ @Test
+ public void bindPreference_shouldLinkifyContent() {
+ final FooterPreference preference = new FooterPreference(mContext);
+ final PreferenceViewHolder holder = new PreferenceViewHolder(
+ LayoutInflater.from(mContext).inflate(R.layout.preference_footer, null));
+
+ preference.onBindViewHolder(holder);
+ assertThat(((TextView) holder.findViewById(android.R.id.title)).getMovementMethod())
+ .isInstanceOf(LinkMovementMethod.class);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/widget/PreferenceDividerDecorationTest.java b/tests/robotests/src/com/android/settings/widget/PreferenceDividerDecorationTest.java
new file mode 100644
index 0000000..f69de54
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/PreferenceDividerDecorationTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceGroupAdapter;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+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.annotation.Config;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.never;
+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 PreferenceDividerDecorationTest {
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock
+ private Drawable mDrawable;
+ @Mock
+ private Canvas mCanvas;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private RecyclerView mRecyclerView;
+ @Mock
+ private PreferenceGroupAdapter mAdapter;
+ @Mock
+ private PreferenceCategory mPrefCategory;
+ @Mock
+ private Preference mNormalPref;
+ @Mock
+ private FooterPreference mFooterPref;
+ private PreferenceDividerDecoration mDecoration;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mDecoration = new PreferenceDividerDecoration();
+ mDecoration.setDivider(mDrawable);
+ mDecoration.setDividerHeight(3);
+ }
+
+ @Test
+ public void drawOver_footerPreference_shouldDrawDivider() {
+ when(mRecyclerView.getAdapter()).thenReturn(mAdapter);
+ when(mRecyclerView.getChildCount()).thenReturn(1);
+ when(mAdapter.getItem(anyInt())).thenReturn(mFooterPref);
+
+ mDecoration.onDrawOver(mCanvas, mRecyclerView, null /* state */);
+
+ verify(mDrawable).draw(mCanvas);
+ }
+
+ @Test
+ public void drawOver_preferenceCategory_shouldSkipFirst() {
+ when(mRecyclerView.getAdapter()).thenReturn(mAdapter);
+ when(mRecyclerView.getChildCount()).thenReturn(3);
+ when(mAdapter.getItem(anyInt())).thenReturn(mPrefCategory);
+ when(mRecyclerView.getChildAdapterPosition(any(View.class)))
+ .thenReturn(0)
+ .thenReturn(1)
+ .thenReturn(2);
+
+ mDecoration.onDrawOver(mCanvas, mRecyclerView, null /* state */);
+
+ // 3 prefCategory, should skip first draw
+ verify(mDrawable, times(2)).draw(mCanvas);
+ }
+
+ @Test
+ public void drawOver_preference_doNotDrawDivider() {
+ when(mRecyclerView.getAdapter()).thenReturn(mAdapter);
+ when(mRecyclerView.getChildCount()).thenReturn(1);
+ when(mAdapter.getItem(anyInt())).thenReturn(mNormalPref);
+
+ mDecoration.onDrawOver(mCanvas, mRecyclerView, null /* state */);
+
+ verify(mDrawable, never()).draw(mCanvas);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/widget/RingProgressBarTest.java b/tests/robotests/src/com/android/settings/widget/RingProgressBarTest.java
index b7a5fd9..1a7161c 100644
--- a/tests/robotests/src/com/android/settings/widget/RingProgressBarTest.java
+++ b/tests/robotests/src/com/android/settings/widget/RingProgressBarTest.java
@@ -16,21 +16,21 @@
package com.android.settings.widget;
-import static junit.framework.Assert.assertEquals;
-
import android.content.Context;
import android.view.View.MeasureSpec;
+import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-@RunWith(RobolectricTestRunner.class)
+import static junit.framework.Assert.assertEquals;
+
+@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class RingProgressBarTest {
diff --git a/tests/unit/src/com/android/settings/fingerprint/FingerprintEnrollIntroductionTest.java b/tests/unit/src/com/android/settings/fingerprint/FingerprintEnrollIntroductionTest.java
new file mode 100644
index 0000000..235ba1e
--- /dev/null
+++ b/tests/unit/src/com/android/settings/fingerprint/FingerprintEnrollIntroductionTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.fingerprint;
+
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintManager;
+import android.test.ActivityUnitTestCase;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FingerprintEnrollIntroductionTest
+ extends ActivityUnitTestCase<FingerprintEnrollIntroduction> {
+
+ private TestContext mContext;
+
+ @Mock
+ private FingerprintManager mFingerprintManager;
+
+ private FingerprintEnrollIntroduction mActivity;
+
+ public FingerprintEnrollIntroductionTest() {
+ super(FingerprintEnrollIntroduction.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+ mContext = new TestContext(getInstrumentation().getTargetContext());
+ setActivityContext(mContext);
+
+ getInstrumentation().runOnMainSync(() -> {
+ final Intent intent = new Intent();
+ mActivity = startActivity(intent,
+ null /* savedInstanceState */, null /* lastNonConfigurationInstance */);
+ });
+ }
+
+ public void testMaxFingerprint_shouldShowErrorMessage() {
+ final int max = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
+ doReturn(generateFingerprintList(max)).when(mFingerprintManager)
+ .getEnrolledFingerprints(anyInt());
+
+ getInstrumentation().runOnMainSync(() -> {
+ getInstrumentation().callActivityOnCreate(mActivity, null);
+ getInstrumentation().callActivityOnResume(mActivity);
+ });
+
+ final TextView errorTextView = (TextView) mActivity.findViewById(R.id.error_text);
+ assertNotNull(errorTextView.getText().toString());
+
+ final Button nextButton = (Button) mActivity.findViewById(R.id.fingerprint_next_button);
+ assertEquals(View.GONE, nextButton.getVisibility());
+ }
+
+ private List<Fingerprint> generateFingerprintList(int num) {
+ ArrayList<Fingerprint> list = new ArrayList<>();
+ for (int i = 0; i < num; i++) {
+ list.add(new Fingerprint("Fingerprint " + i, 0, i, 0));
+ }
+ return list;
+ }
+
+ public class TestContext extends ContextWrapper {
+
+ public TestContext(Context base) {
+ super(base);
+ }
+
+ @Override
+ public Object getSystemService(String name) {
+ if (Context.FINGERPRINT_SERVICE.equals(name)) {
+ return mFingerprintManager;
+ }
+ return super.getSystemService(name);
+ }
+ }
+}