Merge "Remove dynamic location settings footer" into sc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6a4b8d5..437ffbe 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -107,6 +107,7 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_DREAM_STATE" />
<uses-permission android:name="android.permission.READ_DREAM_SUPPRESSION" />
+ <uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION" />
<application android:label="@string/settings_label"
android:icon="@drawable/ic_launcher_settings"
@@ -1233,7 +1234,6 @@
<activity android:name=".applications.InstalledAppOpenByDefaultActivity"
android:label="@string/application_info_label"
- android:permission="android.permission.OPEN_APP_OPEN_BY_DEFAULT_SETTINGS"
android:exported="true">
<intent-filter android:priority="1">
<action android:name="com.android.settings.APP_OPEN_BY_DEFAULT_SETTINGS" />
diff --git a/res/drawable/ic_homepage_search.xml b/res/drawable/ic_homepage_search.xml
index 3895b6b..3da1cc7 100644
--- a/res/drawable/ic_homepage_search.xml
+++ b/res/drawable/ic_homepage_search.xml
@@ -20,7 +20,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="?android:attr/colorAccent">
+ android:tint="?android:attr/textColorSecondary">
<path
android:fillColor="#FF000000"
android:pathData="M20.49,19l-5.73,-5.73C15.53,12.2 16,10.91 16,9.5C16,5.91 13.09,3 9.5,3S3,5.91 3,9.5C3,13.09 5.91,16 9.5,16c1.41,0 2.7,-0.47 3.77,-1.24L19,20.49L20.49,19zM5,9.5C5,7.01 7.01,5 9.5,5S14,7.01 14,9.5S11.99,14 9.5,14S5,11.99 5,9.5z"/>
diff --git a/res/drawable/ic_refresh_24dp.xml b/res/drawable/ic_refresh_24dp.xml
deleted file mode 100644
index 9b78fcd..0000000
--- a/res/drawable/ic_refresh_24dp.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2021 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24"
- android:tint="?android:attr/colorAccent">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M13,9v2h7V4h-2v2.74C16.53,5.07 14.4,4 12,4c-2.21,0 -4.21,0.9 -5.66,2.34S4,9.79 4,12c0,4.42 3.58,8 8,8 2.21,0 4.21,-0.9 5.66,-2.34l-1.42,-1.42C15.15,17.33 13.65,18 12,18c-3.31,0 -6,-2.69 -6,-6 0,-1.65 0.67,-3.15 1.76,-4.24C8.85,6.67 10.35,6 12,6c2.21,0 4.15,1.21 5.19,3H13z"/>
-</vector>
diff --git a/res/drawable/ic_repair_24dp.xml b/res/drawable/ic_repair_24dp.xml
new file mode 100644
index 0000000..da351fc
--- /dev/null
+++ b/res/drawable/ic_repair_24dp.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/black"
+ android:pathData="M12,5c3.53,0 6.44,2.61 6.93,6h2.02c-0.5,-4.5 -4.31,-8 -8.95,-8c-4.97,0 -9,4.03 -9,9c0,3.48 1.98,6.5 4.87,8H5v2h6v-6H9v2.33C6.64,17.2 5,14.79 5,12C5,8.13 8.13,5 12,5z"/>
+ <path
+ android:fillColor="@android:color/black"
+ android:pathData="M22.16,16.5c0,1.93 -1.57,3.5 -3.5,3.5c-0.41,0 -0.8,-0.08 -1.16,-0.21l-2.34,2.33L13.04,20l2.33,-2.34c-0.13,-0.36 -0.21,-0.75 -0.21,-1.16c0,-1.93 1.57,-3.5 3.5,-3.5c0.58,0 1.12,0.16 1.6,0.41l-2.7,2.7l1.49,1.49l2.7,-2.7C22,15.38 22.16,15.92 22.16,16.5z"/>
+</vector>
diff --git a/res/drawable/ic_trash_can.xml b/res/drawable/ic_trash_can.xml
new file mode 100644
index 0000000..ed4a4cb
--- /dev/null
+++ b/res/drawable/ic_trash_can.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M15,3V4H20V6H19V19C19,20.1 18.1,21 17,21H7C5.9,21 5,20.1 5,19V6H4V4H9V3H15ZM7,19H17V6H7V19ZM9,8H11V17H9V8ZM15,8H13V17H15V8Z"
+ android:fillColor="#5F6368"
+ android:fillType="evenOdd"/>
+</vector>
diff --git a/res/drawable/ic_warning_circle_24dp.xml b/res/drawable/ic_warning_circle_24dp.xml
new file mode 100644
index 0000000..54e2ab4
--- /dev/null
+++ b/res/drawable/ic_warning_circle_24dp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="?android:attr/colorError"
+ android:pathData="M11,15h2v2h-2v-2zM11,7h2v6h-2L11,7zM11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/>
+</vector>
diff --git a/res/layout/app_launch_progress.xml b/res/layout/app_launch_progress.xml
new file mode 100644
index 0000000..28fe406
--- /dev/null
+++ b/res/layout/app_launch_progress.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<ProgressBar
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@android:style/Widget.Material.ProgressBar.Horizontal"
+ android:id="@+id/scan_links_progressbar"
+ android:paddingTop="8dp"
+ android:paddingStart="24dp"
+ android:paddingEnd="24dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
\ No newline at end of file
diff --git a/res/layout/app_launch_verified_links_title.xml b/res/layout/app_launch_verified_links_title.xml
new file mode 100644
index 0000000..a230edc
--- /dev/null
+++ b/res/layout/app_launch_verified_links_title.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingStart="?android:attr/dialogPreferredPadding"
+ android:paddingEnd="?android:attr/dialogPreferredPadding"
+ android:paddingTop="@*android:dimen/dialog_padding_top_material">
+
+ <TextView
+ android:id="@+id/dialog_title"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAlignment="center"
+ style="?android:attr/windowTitleStyle" />
+
+ <TextView
+ android:paddingTop="12dp"
+ android:id="@+id/dialog_message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/TextAppearance.DialogMessage" />
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/horizontal_preference.xml b/res/layout/horizontal_preference.xml
index 9358cff..e50fc3f 100644
--- a/res/layout/horizontal_preference.xml
+++ b/res/layout/horizontal_preference.xml
@@ -22,7 +22,7 @@
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:orientation="horizontal"
- android:paddingStart="@dimen/preference_no_icon_padding_start"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<TextView
diff --git a/res/layout/more_settings_button.xml b/res/layout/more_settings_button.xml
new file mode 100644
index 0000000..4bbe119
--- /dev/null
+++ b/res/layout/more_settings_button.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="20dip"
+ android:layout_marginBottom="20dip"
+ style="@style/ActionPrimaryButton"
+ settings:allowDividerBelow="true"
+ android:gravity="center" />
+
+</LinearLayout>
diff --git a/res/layout/one_handed_header.xml b/res/layout/one_handed_header.xml
index 2104e40..3fa8183 100644
--- a/res/layout/one_handed_header.xml
+++ b/res/layout/one_handed_header.xml
@@ -21,7 +21,7 @@
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:scaleType="centerCrop"
+ android:scaleType="centerInside"
android:cropToPadding="true"
android:src="@drawable/one_handed_guideline"
android:contentDescription="@null" />
diff --git a/res/layout/preference_widget_info.xml b/res/layout/preference_widget_info.xml
new file mode 100644
index 0000000..39c2aca
--- /dev/null
+++ b/res/layout/preference_widget_info.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<ImageView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/settings_button"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:background="?android:attr/selectableItemBackground"
+ android:scaleType="center"
+ android:src="@drawable/ic_info_outline_24"
+ android:contentDescription="@string/settings_button" />
\ No newline at end of file
diff --git a/res/layout/preference_widget_warning.xml b/res/layout/preference_widget_warning.xml
new file mode 100644
index 0000000..ea54afe
--- /dev/null
+++ b/res/layout/preference_widget_warning.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<!-- Warning button -->
+<ImageView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/warning_button"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:paddingStart="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:background="?android:attr/selectableItemBackground"
+ android:scaleType="center"
+ android:src="@drawable/ic_warning_circle_24dp"
+ android:contentDescription="@string/warning_button_text" />
diff --git a/res/layout/search_bar.xml b/res/layout/search_bar.xml
index 63f1c95..7cdf04d 100644
--- a/res/layout/search_bar.xml
+++ b/res/layout/search_bar.xml
@@ -19,10 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/search_bar_margin"
- android:layout_marginStart="@dimen/search_bar_margin"
- android:layout_marginEnd="@dimen/search_bar_margin"
- android:layout_marginBottom="@dimen/search_bar_margin_bottom">
+ android:layout_margin="@dimen/search_bar_margin">
<com.google.android.material.card.MaterialCardView
android:id="@+id/search_bar"
@@ -34,7 +31,7 @@
android:id="@+id/search_action_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/search_bar_height"
- android:layout_marginStart="-2dp"
+ android:paddingStart="4dp"
android:background="@drawable/search_bar_selected_background"
android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset"
android:navigationIcon="@drawable/ic_homepage_search">
@@ -43,16 +40,11 @@
style="@style/TextAppearance.SearchBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingStart="-4dp"
android:layout_gravity="start"
android:text="@string/search_menu"/>
</Toolbar>
</com.google.android.material.card.MaterialCardView>
- <ImageView
- android:id="@+id/account_avatar"
- android:layout_width="@dimen/avatar_length"
- android:layout_height="@dimen/avatar_length"
- android:layout_gravity="center_vertical"
- android:contentDescription="@string/search_bar_account_avatar_content_description"/>
</LinearLayout>
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index d9bcb83..4fd62fd 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -65,34 +65,26 @@
android:orientation="vertical"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed">
- <LinearLayout
- android:id="@+id/contextual_suggestion_content"
+ <ImageView
+ android:id="@+id/account_avatar"
+ android:layout_width="@dimen/avatar_length"
+ android:layout_height="@dimen/avatar_length"
+ android:layout_marginTop="@dimen/avatar_margin_top"
+ android:layout_marginEnd="@dimen/avatar_margin_end"
+ android:layout_gravity="end"
+ android:visibility="invisible"
+ android:accessibilityTraversalAfter="@id/homepage_title"
+ android:contentDescription="@string/search_bar_account_avatar_content_description"/>
+
+ <TextView
+ android:id="@+id/homepage_title"
+ android:text="@string/settings_label"
+ style="@style/HomepageTitleText"/>
+
+ <FrameLayout
+ android:id="@+id/suggestion_content"
android:layout_width="match_parent"
- android:layout_height="@dimen/suggestion_height"
- android:paddingHorizontal="@dimen/suggestion_padding_horizontal"
- android:paddingVertical="@dimen/suggestion_padding_vertical"
- android:orientation="vertical"
- android:gravity="bottom"
- android:visibility="gone">
-
- <TextView
- android:id="@+id/suggestion_title"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:text="@string/settings_label"
- style="@style/ContextualSuggestionText"/>
-
- <Button
- android:id="@+id/suggestion_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/suggestion_button_margin_top"
- android:paddingHorizontal="@dimen/suggestion_button_padding_horizontal"
- android:visibility="gone"
- style="@style/ActionPrimaryButton"/>
-
- </LinearLayout>
+ android:layout_height="wrap_content"/>
<include layout="@layout/search_bar"/>
diff --git a/res/layout/supported_links_dialog_item.xml b/res/layout/supported_links_dialog_item.xml
new file mode 100644
index 0000000..bbd2857
--- /dev/null
+++ b/res/layout/supported_links_dialog_item.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<CheckedTextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:ellipsize="marquee"
+ android:gravity="center_vertical"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:textAlignment="viewStart"
+ android:textAppearance="?android:attr/textAppearanceListItemSmall"
+ android:textColor="?android:attr/textColorAlertDialogListItem"
+ android:drawableLeft="?android:attr/listChoiceIndicatorMultiple" />
+
diff --git a/res/layout/verified_links_widget.xml b/res/layout/verified_links_widget.xml
new file mode 100644
index 0000000..322ddd5
--- /dev/null
+++ b/res/layout/verified_links_widget.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <include layout="@layout/preference_widget_info"
+ android:id="@+id/verified_links_widget" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/vpn_dialog.xml b/res/layout/vpn_dialog.xml
index 73f669b..9e264f9 100644
--- a/res/layout/vpn_dialog.xml
+++ b/res/layout/vpn_dialog.xml
@@ -13,218 +13,254 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingTop="0dp"
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp" >
+ <TextView
android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <LinearLayout android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:padding="24dp">
+ android:layout_height="wrap_content"
+ android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small"
+ android:id="@+id/dialog_alert_subtitle"
+ android:text="@string/vpn_insecure_dialog_subtitle"
+ android:textColor="?android:attr/colorError"
+ android:visibility="gone"
+ android:includeFontPadding="false"
+ android:padding="0dp" />
- <LinearLayout android:id="@+id/editor"
- android:layout_width="match_parent"
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:visibility="gone">
+ android:paddingTop="24dp">
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_name"
- android:labelFor="@+id/name"/>
- <EditText style="@style/vpn_value" android:id="@+id/name"
- android:inputType="textCapWords"/>
-
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_type"
- android:labelFor="@+id/type"/>
- <Spinner style="@style/vpn_value"
- android:id="@+id/type"
- android:prompt="@string/vpn_type"
- android:entries="@array/vpn_types"/>
-
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_server"
- android:labelFor="@+id/server"/>
- <EditText style="@style/vpn_value" android:id="@+id/server"/>
-
- <CheckBox style="@style/vpn_value" android:id="@+id/mppe"
- android:text="@string/vpn_mppe"
- android:singleLine="false"
- android:visibility="gone"/>
-
- <LinearLayout android:id="@+id/l2tp"
+ <LinearLayout android:id="@+id/editor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
+
<TextView style="@style/vpn_label"
- android:text="@string/vpn_l2tp_secret"
- android:labelFor="@+id/l2tp_secret"/>
- <EditText style="@style/vpn_value" android:id="@+id/l2tp_secret"
- android:password="true"
- android:hint="@string/vpn_not_used"/>
+ android:text="@string/vpn_name"
+ android:labelFor="@+id/name"/>
+ <EditText style="@style/vpn_value"
+ android:id="@+id/name"
+ android:inputType="textCapWords"/>
+
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_type"
+ android:labelFor="@+id/type"/>
+ <Spinner style="@style/vpn_value"
+ android:id="@+id/type"
+ android:prompt="@string/vpn_type"
+ android:entries="@array/vpn_types"/>
+
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_server"
+ android:labelFor="@+id/server"/>
+ <EditText style="@style/vpn_value"
+ android:id="@+id/server"/>
+
+ <CheckBox style="@style/vpn_value"
+ android:id="@+id/mppe"
+ android:text="@string/vpn_mppe"
+ android:singleLine="false"
+ android:visibility="gone"/>
+
+ <LinearLayout android:id="@+id/l2tp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:visibility="gone">
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_l2tp_secret"
+ android:labelFor="@+id/l2tp_secret"/>
+ <EditText style="@style/vpn_value"
+ android:id="@+id/l2tp_secret"
+ android:password="true"
+ android:hint="@string/vpn_not_used"/>
+ </LinearLayout>
+
+ <LinearLayout android:id="@+id/options_ipsec_identity"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:visibility="gone">
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_ipsec_identifier"
+ android:labelFor="@+id/ipsec_identifier"/>
+ <EditText style="@style/vpn_value"
+ android:id="@+id/ipsec_identifier"
+ android:hint="@string/vpn_not_used"/>
+ </LinearLayout>
+
+ <LinearLayout android:id="@+id/ipsec_psk"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:visibility="gone">
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_ipsec_secret"
+ android:labelFor="@+id/ipsec_secret"/>
+ <EditText style="@style/vpn_value"
+ android:id="@+id/ipsec_secret"
+ android:password="true"/>
+ </LinearLayout>
+
+ <LinearLayout android:id="@+id/ipsec_user"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:visibility="gone">
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_ipsec_user_cert"
+ android:labelFor="@+id/ipsec_user_cert"/>
+ <Spinner style="@style/vpn_value"
+ android:id="@+id/ipsec_user_cert"
+ android:prompt="@string/vpn_ipsec_user_cert" />
+ </LinearLayout>
+
+ <LinearLayout android:id="@+id/ipsec_peer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:visibility="gone">
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_ipsec_ca_cert"
+ android:labelFor="@+id/ipsec_ca_cert"/>
+ <Spinner style="@style/vpn_value"
+ android:id="@+id/ipsec_ca_cert"
+ android:prompt="@string/vpn_ipsec_ca_cert" />
+
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_ipsec_server_cert"
+ android:labelFor="@+id/ipsec_server_cert"/>
+ <Spinner style="@style/vpn_value"
+ android:id="@+id/ipsec_server_cert"
+ android:prompt="@string/vpn_ipsec_server_cert" />
+ </LinearLayout>
+
+ <CheckBox style="@style/vpn_value"
+ android:id="@+id/show_options"
+ android:singleLine="false"
+ android:text="@string/vpn_show_options"/>
</LinearLayout>
- <LinearLayout android:id="@+id/options_ipsec_identity"
+ <LinearLayout android:id="@+id/options"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_ipsec_identifier"
- android:labelFor="@+id/ipsec_identifier"/>
- <EditText style="@style/vpn_value" android:id="@+id/ipsec_identifier"
- android:hint="@string/vpn_not_used"/>
+ <LinearLayout android:id="@+id/network_options"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_search_domains"
+ android:labelFor="@+id/search_domains"/>
+ <EditText style="@style/vpn_value"
+ android:id="@+id/search_domains"
+ android:hint="@string/vpn_not_used"/>
+
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_dns_servers"
+ android:labelFor="@+id/dns_servers"/>
+ <EditText style="@style/vpn_value"
+ android:id="@+id/dns_servers"
+ android:hint="@string/vpn_not_used"/>
+
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_routes"
+ android:labelFor="@+id/routes"/>
+ <EditText style="@style/vpn_value"
+ android:id="@+id/routes"
+ android:hint="@string/vpn_not_used"/>
+ </LinearLayout>
+
+ <TextView android:id="@+id/vpn_proxy_settings_title"
+ style="@style/vpn_label"
+ android:text="@string/proxy_settings_title"
+ android:labelFor="@+id/vpn_proxy_settings" />
+
+ <Spinner android:id="@+id/vpn_proxy_settings"
+ style="@style/vpn_value"
+ android:prompt="@string/proxy_settings_title"
+ android:entries="@array/vpn_proxy_settings" />
+
+ <LinearLayout
+ android:id="@+id/vpn_proxy_fields"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:visibility="gone" >
+
+ <TextView
+ style="@style/vpn_label"
+ android:text="@string/proxy_hostname_label"
+ android:labelFor="@+id/vpn_proxy_host" />
+
+ <EditText
+ android:id="@+id/vpn_proxy_host"
+ style="@style/vpn_value"
+ android:hint="@string/proxy_hostname_hint"
+ android:inputType="textNoSuggestions" />
+
+ <TextView
+ style="@style/vpn_label"
+ android:text="@string/proxy_port_label"
+ android:labelFor="@+id/vpn_proxy_port" />
+
+ <EditText
+ android:id="@+id/vpn_proxy_port"
+ style="@style/vpn_value"
+ android:hint="@string/proxy_port_hint"
+ android:inputType="number" />
+ </LinearLayout>
</LinearLayout>
- <LinearLayout android:id="@+id/ipsec_psk"
+ <LinearLayout android:id="@+id/userpass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:visibility="gone">
+ android:orientation="vertical">
+
<TextView style="@style/vpn_label"
- android:text="@string/vpn_ipsec_secret"
- android:labelFor="@+id/ipsec_secret"/>
- <EditText style="@style/vpn_value" android:id="@+id/ipsec_secret"
+ android:text="@string/vpn_username"
+ android:labelFor="@+id/username"/>
+ <EditText style="@style/vpn_value"
+ android:id="@+id/username"/>
+
+ <TextView style="@style/vpn_label"
+ android:text="@string/vpn_password"
+ android:labelFor="@+id/password"/>
+ <EditText style="@style/vpn_value"
+ android:id="@+id/password"
android:password="true"/>
+
+ <CheckBox style="@style/vpn_value"
+ android:id="@+id/save_login"
+ android:singleLine="false"
+ android:text="@string/vpn_save_login"/>
</LinearLayout>
- <LinearLayout android:id="@+id/ipsec_user"
+ <LinearLayout android:id="@+id/connect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:visibility="gone">
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_ipsec_user_cert"
- android:labelFor="@+id/ipsec_user_cert"/>
- <Spinner style="@style/vpn_value" android:id="@+id/ipsec_user_cert"
- android:prompt="@string/vpn_ipsec_user_cert" />
- </LinearLayout>
-
- <LinearLayout android:id="@+id/ipsec_peer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:visibility="gone">
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_ipsec_ca_cert"
- android:labelFor="@+id/ipsec_ca_cert"/>
- <Spinner style="@style/vpn_value" android:id="@+id/ipsec_ca_cert"
- android:prompt="@string/vpn_ipsec_ca_cert" />
-
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_ipsec_server_cert"
- android:labelFor="@+id/ipsec_server_cert"/>
- <Spinner style="@style/vpn_value" android:id="@+id/ipsec_server_cert"
- android:prompt="@string/vpn_ipsec_server_cert" />
- </LinearLayout>
-
- <CheckBox style="@style/vpn_value" android:id="@+id/show_options"
- android:singleLine="false"
- android:text="@string/vpn_show_options"/>
- </LinearLayout>
-
- <LinearLayout android:id="@+id/options"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:visibility="gone">
- <LinearLayout android:id="@+id/network_options"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_search_domains"
- android:labelFor="@+id/search_domains"/>
- <EditText style="@style/vpn_value" android:id="@+id/search_domains"
- android:hint="@string/vpn_not_used"/>
-
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_dns_servers"
- android:labelFor="@+id/dns_servers"/>
- <EditText style="@style/vpn_value" android:id="@+id/dns_servers"
- android:hint="@string/vpn_not_used"/>
-
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_routes"
- android:labelFor="@+id/routes"/>
- <EditText style="@style/vpn_value" android:id="@+id/routes"
- android:hint="@string/vpn_not_used"/>
- </LinearLayout>
-
- <TextView android:id="@+id/vpn_proxy_settings_title"
- style="@style/vpn_label"
- android:text="@string/proxy_settings_title"
- android:labelFor="@+id/vpn_proxy_settings" />
-
- <Spinner android:id="@+id/vpn_proxy_settings"
- style="@style/vpn_value"
- android:prompt="@string/proxy_settings_title"
- android:entries="@array/vpn_proxy_settings" />
-
- <LinearLayout
- android:id="@+id/vpn_proxy_fields"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:visibility="gone" >
-
- <TextView
- style="@style/vpn_label"
- android:text="@string/proxy_hostname_label"
- android:labelFor="@+id/vpn_proxy_host" />
-
- <EditText
- android:id="@+id/vpn_proxy_host"
- style="@style/vpn_value"
- android:hint="@string/proxy_hostname_hint"
- android:inputType="textNoSuggestions" />
-
- <TextView
- style="@style/vpn_label"
- android:text="@string/proxy_port_label"
- android:labelFor="@+id/vpn_proxy_port" />
-
- <EditText
- android:id="@+id/vpn_proxy_port"
- style="@style/vpn_value"
- android:hint="@string/proxy_port_hint"
- android:inputType="number" />
+ android:animateLayoutChanges="true">
+ <CheckBox style="@style/vpn_value"
+ android:id="@+id/always_on_vpn"
+ android:singleLine="false"
+ android:text="@string/vpn_menu_lockdown"/>
+ <TextView style="@style/vpn_warning"
+ android:id="@+id/always_on_invalid_reason"
+ android:singleLine="false"
+ android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
-
- <LinearLayout android:id="@+id/userpass"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_username"
- android:labelFor="@+id/username"/>
- <EditText style="@style/vpn_value" android:id="@+id/username"/>
-
- <TextView style="@style/vpn_label"
- android:text="@string/vpn_password"
- android:labelFor="@+id/password"/>
- <EditText style="@style/vpn_value" android:id="@+id/password"
- android:password="true"/>
-
- <CheckBox style="@style/vpn_value" android:id="@+id/save_login"
- android:singleLine="false"
- android:text="@string/vpn_save_login"/>
- </LinearLayout>
-
- <LinearLayout android:id="@+id/connect"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:animateLayoutChanges="true">
- <CheckBox style="@style/vpn_value" android:id="@+id/always_on_vpn"
- android:singleLine="false"
- android:text="@string/vpn_menu_lockdown"/>
- <TextView style="@style/vpn_warning" android:id="@+id/always_on_invalid_reason"
- android:singleLine="false"
- android:visibility="gone"/>
- </LinearLayout>
- </LinearLayout>
-</ScrollView>
+ </ScrollView>
+</LinearLayout>
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 4eb0afd..b2f9a89 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -21,7 +21,7 @@
<color name="homepage_support_background">#3F5FBD</color>
<color name="homepage_card_dismissal_background">@*android:color/material_grey_900</color>
<color name="contextual_card_background">@*android:color/material_grey_900</color>
- <color name="search_bar_background">@*android:color/material_grey_800</color>
+ <color name="search_bar_background">@*android:color/material_grey_900</color>
<!-- Dialog background color. -->
<color name="dialog_background">@*android:color/material_grey_800</color>
<color name="notification_importance_selection_bg">@*android:color/material_grey_800</color>
diff --git a/res/values/config.xml b/res/values/config.xml
index 984906f..2546d8d 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -509,4 +509,17 @@
<!-- Cell broacast receiver package name -->
<string name="config_cell_broadcast_receiver_package" translatable="false">com.android.cellbroadcastreceiver.module</string>
+
+ <!-- TODO(b/174964885): These media Uri are not defined in framework yet. Replace with framework defined variables once it's available. -->
+ <!-- Media Uri to view images storage category. -->
+ <string name="config_images_storage_category_uri" translatable="false">content://com.android.providers.media.documents/root/images_root</string>
+
+ <!-- Media Uri to view videos storage category. -->
+ <string name="config_videos_storage_category_uri" translatable="false">content://com.android.providers.media.documents/root/videos_root</string>
+
+ <!-- Media Uri to view audios storage category. -->
+ <string name="config_audios_storage_category_uri" translatable="false">content://com.android.providers.media.documents/root/audio_root</string>
+
+ <!-- Media Uri to view documents & other storage category. -->
+ <string name="config_documents_and_other_storage_category_uri" translatable="false">content://com.android.providers.media.documents/root/documents_root</string>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 0ee39cd..e0e0219 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -131,25 +131,21 @@
<dimen name="switchbar_subsettings_margin_start">72dp</dimen>
<dimen name="switchbar_subsettings_margin_end">16dp</dimen>
- <!-- Search bar and avatar -->
- <dimen name="search_bar_margin">24dp</dimen>
- <dimen name="search_bar_margin_bottom">16dp</dimen>
- <dimen name="search_bar_height">48dp</dimen>
- <dimen name="search_bar_text_size">16sp</dimen>
- <dimen name="search_bar_card_elevation">2dp</dimen>
- <dimen name="search_bar_content_inset">64dp</dimen>
- <dimen name="avatar_length">@dimen/search_bar_height</dimen>
+ <!-- Search bar -->
+ <dimen name="search_bar_margin">16dp</dimen>
+ <dimen name="search_bar_height">52dp</dimen>
+ <dimen name="search_bar_text_size">20sp</dimen>
+ <dimen name="search_bar_corner_radius">28dp</dimen>
+ <dimen name="search_bar_content_inset">56dp</dimen>
- <!-- Contextual suggestions -->
- <dimen name="suggestion_height">232dp</dimen>
- <dimen name="suggestion_padding_horizontal">24dp</dimen>
- <dimen name="suggestion_padding_vertical">8dp</dimen>
- <dimen name="suggestion_button_margin_top">16dp</dimen>
- <dimen name="suggestion_button_padding_horizontal">24dp</dimen>
+ <!-- Avatar -->
+ <dimen name="avatar_length">48dp</dimen>
+ <dimen name="avatar_margin_top">56dp</dimen>
+ <dimen name="avatar_margin_end">24dp</dimen>
- <!-- Tool bar text -->
- <dimen name="tool_bar_max_text_size">36sp</dimen>
- <dimen name="tool_bar_min_text_size">24sp</dimen>
+ <!-- Homepage title -->
+ <dimen name="homepage_title_margin_bottom">8dp</dimen>
+ <dimen name="homepage_title_margin_horizontal">24dp</dimen>
<!-- Dimensions for Wifi Assistant Card -->
<dimen name="wifi_assistant_padding_top_bottom">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1acd110..e65806b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -844,6 +844,8 @@
<string name="security_settings_face_settings_use_face_for_apps">App sign-in \u0026 payments</string>
<!-- Title for a category shown for the face settings page, followed by items that the user can toggle on/off to require/disable. -->
<string name="security_settings_face_settings_require_category">Requirements for face unlock</string>
+ <!-- Title for a category shown for the face settings page, followed by items that the user can toggle on/off to require/disable. [CHAR LIMIT=50] -->
+ <string name="security_settings_face_settings_preferences_category">When using face unlock</string>
<!-- Text shown on a toggle which disables/enables face unlock, depending if the user's eyes are open. [CHAR LIMIT=30] -->
<string name="security_settings_face_settings_require_attention">Require eyes to be open</string>
<!-- Text shown on the details of a toggle which disables/enables face unlock, depending if the user's eyes are open. [CHAR LIMIT=70] -->
@@ -854,6 +856,8 @@
<string name="security_settings_face_settings_require_confirmation_details">When using face unlock in apps, always require confirmation step</string>
<!-- Button text in face settings which removes the user's faces from the device [CHAR LIMIT=20] -->
<string name="security_settings_face_settings_remove_face_data">Delete face data</string>
+ <!-- Button text in face settings which removes the user's face model from the device [CHAR LIMIT=40] -->
+ <string name="security_settings_face_settings_remove_face_model">Delete face model</string>
<!-- Button text in face settings which lets the user enroll their face [CHAR LIMIT=40] -->
<string name="security_settings_face_settings_enroll">Set up face unlock</string>
<!-- Text shown in face settings explaining what your face can be used for. [CHAR LIMIT=NONE] -->
@@ -866,6 +870,10 @@
<string name="security_settings_face_settings_remove_dialog_title">Delete face data?</string>
<!-- Dialog contents shown when the user removes an enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_remove_dialog_details">The face data used by face unlock will be permanently and securely deleted. After removal, you will need your PIN, pattern, or password to unlock your phone, sign in to apps, and confirm payments.</string>
+ <!-- Dialog title shown when the user chooses to delete an existing enrolled face model. [CHAR LIMIT=35] -->
+ <string name="security_settings_face_settings_remove_model_dialog_title">Delete face model?</string>
+ <!-- Dialog contents shown when the user chooses to delete an existing enrolled face model. [CHAR LIMIT=NONE] -->
+ <string name="security_settings_face_settings_remove_model_dialog_details">Your face model will be permanently and securely deleted.\n\nAfter deletion, you will need your fingerprint, PIN, pattern, or password to unlock your phone or for authentication in apps.</string>
<!-- Subtitle shown for contextual setting face enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_context_subtitle">Use face unlock to unlock your phone</string>
@@ -1069,6 +1077,25 @@
<!-- Button to confirm the last removing the last fingerprint. [CHAR LIMIT=20]-->
<string name="fingerprint_last_delete_confirm">Yes, remove</string>
+ <!-- Title of the combined biometrics settings screen. [CHAR LIMIT=40] -->
+ <string name="security_settings_biometrics_title">Face \u0026 fingerprint unlock</string>
+ <!-- Summary of the current biometrics setting when no biometrics have been enrolled. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_summary_none">Tap to set up</string>
+ <!-- Summary of the current biometrics setting when the user has enrolled a face but no fingerprint. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_summary_face">Face only</string>
+ <!-- Summary of the current biometrics setting when the user has enrolled a fingerprint but no face. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_summary_fingerprint">Fingerprint only</string>
+ <!-- Summary of the current biometrics setting when the user has enrolled both a face and a fingerprint. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_summary_both">Face and fingerprint</string>
+ <!-- Description shown on the combined biometrics settings screen. [CHAR LIMIT=NONE] -->
+ <string name="security_settings_biometrics_description">When you set up face and fingerprint unlock, your phone will ask for your fingerprint when you wear a mask or are in a dark area</string>
+ <!-- Title of a section on the biometrics settings screen for setting up different types of authentication. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_types_category">Ways to unlock</string>
+ <!-- Title of a section on the biometrics settings screen for adjusting authentication preferences. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_preferences_category">Use face or fingerprint for</string>
+ <!-- Title of a section on the biometrics settings screen for adjusting authentication preferences. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_preference_use_with_apps">Authentication in apps</string>
+
<!-- Title of the preferences category for preference items to control encryption -->
<string name="crypt_keeper_settings_title">Encryption</string>
@@ -1333,15 +1360,15 @@
<string name="face_unlock_title">You can unlock your phone using your face. For security, this option requires a backup screen lock.</string>
<!-- Title for preference that guides the user through creating a backup unlock pattern for biometrics unlock [CHAR LIMIT=45]-->
- <string name="biometrics_unlock_set_unlock_pattern">Biometrics + Pattern</string>
+ <string name="biometrics_unlock_set_unlock_pattern">Pattern \u2022 Face \u2022 Fingerprint</string>
<!-- Title for preference that guides the user through creating a backup unlock PIN for biometrics unlock [CHAR LIMIT=45]-->
- <string name="biometrics_unlock_set_unlock_pin">Biometrics + PIN</string>
+ <string name="biometrics_unlock_set_unlock_pin">PIN \u2022 Face \u2022 Fingerprint</string>
<!-- Title for preference that guides the user through creating a backup unlock password for biometrics unlock [CHAR LIMIT=45]-->
- <string name="biometrics_unlock_set_unlock_password">Biometrics + Password</string>
+ <string name="biometrics_unlock_set_unlock_password">Password \u2022 Face \u2022 Fingerprint</string>
<!-- Title for preference that guides the user to skip face unlock setup [CHAR LIMIT=60]-->
- <string name="biometrics_unlock_skip_biometrics">Continue without biometrics</string>
+ <string name="biometrics_unlock_skip_biometrics">Continue without face or fingerprint</string>
<!-- Message shown in screen lock picker while setting up the new screen lock with biometrics option. [CHAR LIMIT=NONE] -->
- <string name="biometrics_unlock_title">You can unlock your phone using your biometrics. For security, this option requires a backup screen lock.</string>
+ <string name="biometrics_unlock_title">You can unlock your phone using your face or fingerprint. For security, this option requires a backup screen lock.</string>
<!-- Summary for preference that has been disabled by because of the DevicePolicyAdmin, or because device encryption is enabled, or because there are credentials in the credential storage [CHAR LIMIT=50] -->
<string name="unlock_set_unlock_disabled_summary">Disabled by admin, encryption policy, or
@@ -2319,6 +2346,8 @@
<string name="wifi_details_title">Network details</string>
<!-- Wifi details preference title to display router IP subnet mask -->
<string name="wifi_details_subnet_mask">Subnet mask</string>
+ <!-- Wifi details preference title to display wifi type info [CHAR LIMIT=50]-->
+ <string name="wifi_type_title">TYPE</string>
<!-- Wifi details preference title to display router DNS info -->
<string name="wifi_details_dns">DNS</string>
<!-- Wifi details preference category title for IPv6 information -->
@@ -2354,6 +2383,12 @@
<string name="wifi_gateway">Gateway</string>
<!-- Label for the network prefix of the network [CHAR LIMIT=25]-->
<string name="wifi_network_prefix_length">Network prefix length</string>
+ <!-- Summary for the WiFi Type WIFI_STANDARD_11AX [CHAR LIMIT=50]-->
+ <string name="wifi_type_11AX">Wi\u2011Fi 6</string>
+ <!-- Summary for the WiFi Type WIFI_STANDARD_11AC [CHAR LIMIT=50]-->
+ <string name="wifi_type_11AC">Wi\u2011Fi 5</string>
+ <!-- Summary for the WiFi Type WIFI_STANDARD_11N [CHAR LIMIT=50]-->
+ <string name="wifi_type_11N">Wi\u2011Fi 4</string>
<!-- Wi-Fi p2p / Wi-Fi Direct settings -->
<!-- Used in the 1st-level settings screen to launch Wi-fi Direct settings [CHAR LIMIT=25] -->
@@ -2964,6 +2999,8 @@
<string name="wallpaper_settings_title">Wallpaper</string>
<!-- Styles & Wallpapers settings title [CHAR LIMIT=30] -->
<string name="style_and_wallpaper_settings_title">Styles & wallpapers</string>
+ <!-- Summary for the top level Styles & wallpapers Settings [CHAR LIMIT=NONE]-->
+ <string name="wallpaper_dashboard_summary">Colors, app grid</string>
<!-- Wallpaper settings summary when default wallpaper is used [CHAR LIMIT=NONE] -->
<string name="wallpaper_settings_summary_default">Default</string>
<!-- Wallpaper settings summary when wallpaper has been updated [CHAR LIMIT=NONE] -->
@@ -3403,22 +3440,6 @@
<!-- Section header above list of external storage devices [CHAR LIMIT=30]-->
<string name="storage_external_title">Portable storage</string>
- <!-- Label for the settings activity for controlling apps that can schedule alarms [CHAR LIMIT=30] -->
- <string name="alarms_and_reminders_label">Alarms and reminders</string>
- <!-- Label for the switch to toggler the permission for scheduling alarms [CHAR LIMIT=50] -->
- <string name="alarms_and_reminders_switch_title">Allow to set alarms or reminders</string>
- <!-- Title for the setting screen for controlling apps that can schedule alarms [CHAR LIMIT=30] -->
- <string name="alarms_and_reminders_title">Alarms and reminders</string>
- <!-- Description that appears below the alarms_and_reminders switch [CHAR LIMIT=NONE] -->
- <string name="alarms_and_reminders_footer_title">
- Allow this app to schedule alarms or other timing based events.
- This will allow the app to wake up and run even when you are not using the device.
- Note that revoking this permission may cause the app to malfunction, specifically any alarms
- that the app has scheduled will no longer work.
- </string>
- <!-- Keywords for setting screen for controlling apps that can schedule alarms [CHAR LIMIT=100] -->
- <string name="keywords_alarms_and_reminders">schedule, alarm, reminder, event</string>
-
<!-- Summary of a single storage volume, constrasting available and total storage space. [CHAR LIMIT=48]-->
<string name="storage_volume_summary"><xliff:g id="used" example="1.2GB">%1$s</xliff:g> used of <xliff:g id="total" example="32GB">%2$s</xliff:g></string>
<!-- Summary of a single storage volume used space. [CHAR LIMIT=24] -->
@@ -4084,6 +4105,18 @@
<!-- [CHAR LIMIT=60] Date&Time settings screen, toggle button title -->
<string name="location_time_zone_detection_toggle_title">Use location to set time zone</string>
+ <!-- [CHAR LIMIT=60] Date&Time settings screen, title of the dialog shown when user tries to
+ enable GeoTZ when Location toggle is off. -->
+ <string name="location_time_zone_detection_location_is_off_dialog_title">Device location needed</string>
+ <!-- [CHAR LIMIT=NONE] Date&Time settings screen, message on the dialog shown when user tries to
+ enable GeoTZ when Location toggle is off. -->
+ <string name="location_time_zone_detection_location_is_off_dialog_message">To set the time zone using your location, turn on location, then update time zone settings</string>
+ <!-- [CHAR LIMIT=30] Date&Time settings screen, button on a dialog shown when user tries to
+ enable GeoTZ, but Location toggle is off, which leads to Location settings page. -->
+ <string name="location_time_zone_detection_location_is_off_dialog_ok_button">Location settings</string>
+ <!-- [CHAR LIMIT=30] Date&Time settings screen, button on a dialog shown when user tries to
+ enable GeoTZ, but Location toggle is off, which closes the dialog. -->
+ <string name="location_time_zone_detection_location_is_off_dialog_cancel_button">Cancel</string>
<!-- [CHAR LIMIT=NONE] Location settings screen, summary when location time zone detection is not
applicable due to other settings like the "automatic time zone detection enabled" setting
being set to "off". -->
@@ -5070,7 +5103,7 @@
<!-- Title for the accessibility magnification switch shortcut dialog. [CHAR LIMIT=48] -->
<string name="accessibility_magnification_switch_shortcut_title">Switch to accessibility button?</string>
<!-- Message for the accessibility magnification switch shortcut dialog. [CHAR LIMIT=none] -->
- <string name="accessibility_magnification_switch_shortcut_message">Using triple-tap to magnify part of the screen causes typing and other delays.\n\nThe accessibility button floats on your screen over other apps. Tap it to magnify.</string>
+ <string name="accessibility_magnification_switch_shortcut_message">Using triple-tap to magnify part of your screen causes typing and other delays.\n\nThe accessibility button floats on your screen over other apps. Tap it to magnify.</string>
<!-- Title for the switch shortcut button in accessibility switch shortcut dialog to change the config shortcut value. [CHAR LIMIT=45] -->
<string name="accessibility_magnification_switch_shortcut_positive_button">Switch to accessibility button</string>
<!-- Title for the cancel button in accessibility switch shortcut dialog to keep the config shortcut value. [CHAR LIMIT=54] -->
@@ -6403,6 +6436,10 @@
<!-- Title of preference to enter the VPN settings activity -->
<string name="vpn_settings_title">VPN</string>
+ <!-- Title of preference to enter the VPN settings activity [CHAR LIMIT=30] -->
+ <string name="vpn_settings_insecure_single">Not secure</string>
+ <!-- Title of preference to enter the VPN settings activity [CHAR LIMIT=30] -->
+ <string name="vpn_settings_insecure_multiple"><xliff:g id="vpn_count" example="1">%d</xliff:g> not secure</string>
<!-- Title of Adaptive connectivity. Adaptive connectivity is a feature which automatically manages network connections for better battery life and performance. [CHAR LIMIT=60] -->
<string name="adaptive_connectivity_title">Adaptive connectivity</string>
@@ -7059,6 +7096,8 @@
<string name="vpn_always_on_summary_not_supported">Not supported by this app</string>
<!-- Preference summary for a VPN app that is set to be always-on. [CHAR LIMIT=40] -->
<string name="vpn_always_on_summary_active">Always-on active</string>
+ <!-- Preference summary for a VPN app that has an insecure type. [CHAR LIMIT=40] -->
+ <string name="vpn_insecure_summary">not secure VPN</string>
<!-- Preference title for the toggle that controls whether to force all network connections to
go through VPN. [CHAR LIMIT=40] -->
<string name="vpn_require_connection">Block connections without VPN</string>
@@ -7066,6 +7105,9 @@
[CHAR LIMIT=40] -->
<string name="vpn_require_connection_title">Require VPN connection?</string>
+ <!-- Dialog subtitle warning for a VPN app that has an insecure type. [CHAR LIMIT=100] -->
+ <string name="vpn_insecure_dialog_subtitle">This VPN is not secure. Update to an IKEv2 VPN</string>
+
<!-- Summary describing the always-on VPN feature. [CHAR LIMIT=NONE] -->
<string name="vpn_lockdown_summary">Select a VPN profile to always remain connected to. Network traffic will only be allowed when connected to this VPN.</string>
<!-- List item indicating that no always-on VPN is selected. [CHAR LIMIT=64] -->
@@ -7272,6 +7314,12 @@
<!-- Summary for the emergency info preference [CHAR LIMIT=40] -->
<string name="emergency_info_summary">Info & contacts for <xliff:g id="user_name" example="Jason">%1$s</xliff:g></string>
+ <!-- Button label for opening an arbitrary app [CHAR LIMIT=60] -->
+ <string name="open_app_button">Open <xliff:g id="app_name" example="Safety">%1$s</xliff:g></string>
+
+ <!-- Title for more settings button, clicking this button will open a new page containing more settings related to current page. [CHAR LIMIT=60] -->
+ <string name="more_settings_button">More Settings</string>
+
<!-- Application Restrictions screen title [CHAR LIMIT=45] -->
<string name="application_restrictions">Allow apps and content</string>
<!-- Applications with restrictions header [CHAR LIMIT=45] -->
@@ -7503,6 +7551,8 @@
<string name="help_uri_nfc_and_payment_settings" translatable="false"></string>
<!-- url for battery page if battery is not present -->
<string name="help_url_battery_missing" translatable="false"></string>
+ <!-- url for vpn page if connected vpn is not a secure type -->
+ <string name="help_url_insecure_vpn" translatable="false"></string>
<!-- User account title [CHAR LIMIT=30] -->
<string name="user_account_title">Account for content</string>
@@ -7769,10 +7819,10 @@
<string name="app_and_notification_dashboard_summary">Recent apps, default apps</string>
<!-- Toast shown when an app in the work profile attempts to open notification settings. The apps in the work profile cannot access notification settings. [CHAR LIMIT=NONE] -->
<string name="notification_settings_work_profile">Notification access is not available for apps in the work profile.</string>
- <!-- Title for setting tile leading to account settings [CHAR LIMIT=40]-->
- <string name="account_dashboard_title">Accounts</string>
- <!-- Summary for account settings tiles when there is no accounts on device [CHAR LIMIT=NONE]-->
- <string name="account_dashboard_default_summary">No accounts added</string>
+ <!-- Title for setting tile leading to saved autofill passwords, autofill, and account settings [CHAR LIMIT=40]-->
+ <string name="account_dashboard_title">Passwords and accounts</string>
+ <!-- Summary for setting tile leading to saved autofill passwords, autofill, and account settings [CHAR LIMIT=NONE]-->
+ <string name="account_dashboard_default_summary">Saved passwords, autofill, synced accounts</string>
<!-- Title for setting tile leading to setting UI which allows user set default app to
handle actions such as open web page, making phone calls, default SMS apps [CHAR LIMIT=40]-->
<string name="app_default_dashboard_title">Default apps</string>
@@ -8392,6 +8442,9 @@
<!-- Configure Notifications Settings title. [CHAR LIMIT=30] -->
<string name="configure_notification_settings">Notifications</string>
+ <!-- Summary for the top level Notifications Settings [CHAR LIMIT=NONE]-->
+ <string name="notification_dashboard_summary">Notification history, conversations</string>
+
<!-- notification header - settings for conversation type notifications -->
<string name="conversation_notifs_category">Conversation</string>
@@ -9575,6 +9628,9 @@
settings button -->
<string name="notification_app_settings_button">Notification settings</string>
+ <!-- Content description for help icon button [CHAR LIMIT=20] -->
+ <string name="warning_button_text">Warning</string>
+
<!-- Generic label for suggestion card's ok button [CHAR LIMIT=20] -->
<string name="suggestion_button_text">Ok</string>
@@ -10524,6 +10580,9 @@
<!-- Summary for Display settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
<string name="display_dashboard_summary_with_style">Styles, wallpapers, screen timeout, font size</string>
+ <!-- Summary for the top level Display Settings [CHAR LIMIT=NONE]-->
+ <string name="display_dashboard_summary_2">Screen timeout, font size</string>
+
<!-- Summary for Display settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
<string name="display_dashboard_nowallpaper_summary">Sleep, font size</string>
@@ -11222,6 +11281,9 @@
<!-- Preference title for "Safety & emergency" settings page [CHAR LIMIT=60]-->
<string name="emergency_settings_preference_title">Safety & emergency</string>
+ <!-- Summary for the top level Safety & emergency Settings [CHAR LIMIT=NONE]-->
+ <string name="emergency_dashboard_summary">Emergency SOS, medical info, alerts</string>
+
<!-- Title text for edge to edge navigation [CHAR LIMIT=60] -->
<string name="edge_to_edge_navigation_title">Gesture navigation</string>
<!-- Summary text for edge to edge navigation [CHAR LIMIT=NONE] -->
@@ -11275,8 +11337,8 @@
<!-- Title text for swiping downwards on the bottom of the screen for notifications [CHAR LIMIT=60]-->
<string name="swipe_bottom_to_notifications_title">Swipe for notifications</string>
- <!-- Summary text for swiping downwards on the bottom of the screen for notifications [CHAR LIMIT=80]-->
- <string name="swipe_bottom_to_notifications_summary">Swipe down on the bottom edge of the screen to show your notifications</string>
+ <!-- Summary text for swiping downwards on the bottom of the screen for notifications [CHAR LIMIT=NONE]-->
+ <string name="swipe_bottom_to_notifications_summary">Swipe down on the bottom edge of the screen to show your notifications.\nYou can\'t use one-handed mode when this feature is turned on.</string>
<!-- Preference and settings suggestion title text for one handed [CHAR LIMIT=60] -->
<string name="one_handed_title">One-Handed mode</string>
@@ -11531,6 +11593,25 @@
<!-- Button label to allow the user to view additional information [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=2416766240581561009] -->
<string name="learn_more">Learn more</string>
+ <!-- Financed device Privacy --> <skip />
+
+ <!-- Title of setting on security settings screen on a financed device. This will take the user to a screen with information about what a device administrator can control and their impact on the user's privacy on a financed device. Shown on financed-managed devices only. [CHAR LIMIT=NONE] -->
+ <string name="financed_privacy_settings">Financed device info</string>
+ <!-- Section header. This section shows what information a device administrator can see on a financed device. [CHAR LIMIT=60] -->
+ <string name="financed_privacy_exposure_category">Types of information your device administrator can see</string>
+ <!-- Label explaining that the device administrator can see data associated on the user's financed device. [CHAR LIMIT=NONE] -->
+ <string name="financed_privacy_data">Data associated with your account, such as email and calendar info</string>
+ <!-- Section header. This section shows what changes a device administrator made to a financed device. [CHAR LIMIT=60] -->
+ <string name="financed_privacy_exposure_changes_category">Changes made by your device administrator</string>
+ <!-- Label explaining that the device admin can lock the device and change the user's password on their financed device. [CHAR LIMIT=NONE] -->
+ <string name="financed_privacy_lock_device">Device administrator can lock this device and reset password</string>
+ <!-- Label explaining that the device admin can wipe the device remotely for a financed device. [CHAR LIMIT=NONE] -->
+ <string name="financed_privacy_wipe_device">Device administrator can delete all device data</string>
+ <!-- Label explaining that the device admin configured the device to wipe itself when an incorrect password is entered too many times on a financed device. [CHAR LIMIT=NONE] -->
+ <string name="financed_privacy_failed_password_wipe_device">Failed password attempts before deleting device data</string>
+ <!-- Financed Privacy settings activity header, summarizing the changes a credit provider can make to a financed device. [CHAR LIMIT=NONE] -->
+ <string name="financed_privacy_header">Your credit provider can change settings and install software on this device.\n\nTo learn more, contact your creditor provider.</string>
+
<!-- Strings for displaying which applications were set as default for specific actions. -->
<!-- Title for the apps that have been set as default handlers of camera-related intents. [CHAR LIMIT=30] -->
<plurals name="default_camera_app_title">
@@ -11573,6 +11654,39 @@
<!-- Preference label for the Files storage section. [CHAR LIMIT=50] -->
<string name="storage_files">Files</string>
+ <!-- Preference label for the Images storage section. [CHAR LIMIT=50] -->
+ <string name="storage_images">Images</string>
+
+ <!-- Preference label for the Videos storage section. [CHAR LIMIT=50] -->
+ <string name="storage_videos">Videos</string>
+
+ <!-- Preference label for the Audios storage section. [CHAR LIMIT=50] -->
+ <string name="storage_audios">Audios</string>
+
+ <!-- Preference label for the Apps storage section. [CHAR LIMIT=50] -->
+ <string name="storage_apps">Apps</string>
+
+ <!-- Preference label for the Documents & other storage section. [CHAR LIMIT=50] -->
+ <string name="storage_documents_and_other">Documents & other</string>
+
+ <!-- Preference label for the System storage section. [CHAR LIMIT=50] -->
+ <string name="storage_system">System</string>
+
+ <!-- Preference label for the Trash storage section. [CHAR LIMIT=50] -->
+ <string name="storage_trash">Trash</string>
+
+ <!-- Dialog title for the Trash storage section. [CHAR LIMIT=50] -->
+ <string name="storage_trash_dialog_title">Empty trash?</string>
+
+ <!-- Dialog message for the Trash storage section. [CHAR LIMIT=NONE] -->
+ <string name="storage_trash_dialog_ask_message">There are <xliff:g id="total" example="520MB">%1$s</xliff:g> of files in the trash. All items will be deleted forever, and you won\u2019t be able to restore them.</string>
+
+ <!-- Dialog message for the Trash storage section. [CHAR LIMIT=NONE] -->
+ <string name="storage_trash_dialog_empty_message">Trash is empty</string>
+
+ <!-- Dialog confirm button to empty all trash files. [CHAR LIMIT=50] -->
+ <string name="storage_trash_dialog_confirm">Empty trash</string>
+
<!-- Summary of a single storage volume used space. [CHAR LIMIT=24] -->
<string name="storage_size_large_alternate"><xliff:g id="number" example="128">^1</xliff:g><small> <font size="20"><xliff:g id="unit" example="KB">^2</xliff:g></font></small></string>
<!-- Summary of a single storage volume total space. [CHAR LIMIT=48]-->
@@ -11612,6 +11726,12 @@
<string name="autofill_app">Autofill service</string>
<!-- Preference category for showing auto-fill services with saved passwords. [CHAR LIMIT=60] -->
<string name="autofill_passwords">Passwords</string>
+ <!-- Summary for passwords settings that shows how many passwords are saved for each autofill
+ service. [CHAR LIMIT=NONE] -->
+ <plurals name="autofill_passwords_count">
+ <item quantity="one"><xliff:g id="count">%1$d</xliff:g> password</item>
+ <item quantity="other"><xliff:g id="count">%1$d</xliff:g> passwords</item>
+ </plurals>
<!-- Keywords for the auto-fill feature. [CHAR LIMIT=NONE] -->
<string name="autofill_keywords">auto, fill, autofill, password</string>
@@ -12855,10 +12975,12 @@
<string name="category_name_brightness">Brightness</string>
<!-- Lock screen category name in Display Settings [CHAR LIMIT=none] -->
<string name="category_name_lock_display">Lock Display</string>
- <!-- Visibility category name in Display Settings [CHAR LIMIT=none] -->
- <string name="category_name_visibility">Visibility</string>
+ <!-- Appearance category name in Display Settings [CHAR LIMIT=none] -->
+ <string name="category_name_appearance">Appearance</string>
<!-- Color category name in Display Settings [CHAR LIMIT=none] -->
<string name="category_name_color">Color</string>
+ <!-- Name of Other display controls category in Display Settings [CHAR LIMIT=none] -->
+ <string name="category_name_display_controls">Other Display Controls</string>
<!-- Others category name [CHAR LIMIT=none] -->
<string name="category_name_others">Others</string>
<!-- General category name [CHAR LIMIT=none] -->
@@ -12938,8 +13060,11 @@
<string name="extra_app_info_label" translatable="false"></string>
<!-- Title for toggle controlling whether notifications are shown when an app pastes from clipboard. [CHAR LIMIT=50] -->
- <string name="show_clip_access_notification">Copy & paste notifications</string>
+ <string name="show_clip_access_notification">Show clipboard access</string>
<!-- Summary for toggle controlling whether notifications are shown when an app pastes from clipboard. [CHAR LIMIT=NONE] -->
- <string name="show_clip_access_notification_summary">Show a message when apps access text or data you have copied</string>
+ <string name="show_clip_access_notification_summary">Show a message when apps access text, images, or other content you\u2019ve copied</string>
+
+ <!-- All apps screen title, entry name on Apps page for the user to go to the all apps page. [CHAR LIMIT=30] -->
+ <string name="all_apps">All apps</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0d773f1..8ca72db 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -310,6 +310,7 @@
<style name="TextAppearance.SearchBar"
parent="@*android:style/TextAppearance.DeviceDefault.Widget.Toolbar.Subtitle">
<item name="android:textSize">@dimen/search_bar_text_size</item>
+ <item name="android:textColor">?android:attr/textColorTertiary</item>
<item name="android:singleLine">true</item>
</style>
@@ -418,7 +419,6 @@
</style>
<style name="ActionPrimaryButton" parent="android:Widget.DeviceDefault.Button.Colored"/>
-
<style name="ActionSecondaryButton" parent="android:Widget.DeviceDefault.Button"/>
<style name="LockPatternContainerStyle">
@@ -481,11 +481,8 @@
</style>
<style name="SearchBarStyle">
- <item name="android:layout_marginEnd">@dimen/search_bar_margin</item>
- <item name="cardCornerRadius">34dp</item>
- <item name="enforceMaterialTheme">true</item>
- <item name="cardElevation">3dp</item>
- <item name="shapeAppearance">@null</item>
+ <item name="cardCornerRadius">@dimen/search_bar_corner_radius</item>
+ <item name="cardElevation">0dp</item>
</style>
<style name="ConditionCardBorderlessButton"
@@ -789,13 +786,11 @@
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
</style>
- <style name="ContextualSuggestionText"
- parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
- <item name="android:autoSizeTextType">uniform</item>
- <item name="android:autoSizeMaxTextSize">@dimen/tool_bar_max_text_size</item>
- <item name="android:autoSizeMinTextSize">@dimen/tool_bar_min_text_size</item>
- <item name="android:maxLines">3</item>
- <item name="android:gravity">bottom</item>
+ <style name="HomepageTitleText" parent="ToolbarText">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginBottom">@dimen/homepage_title_margin_bottom</item>
+ <item name="android:layout_marginHorizontal">@dimen/homepage_title_margin_horizontal</item>
</style>
<style name="RequestManageCredentialsButtonPanel">
@@ -883,16 +878,7 @@
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
- <style name="ToolbarText.Collapsed"
- parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
- </style>
-
- <style name="ToolbarText"
- parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
- <item name="android:textSize">@dimen/tool_bar_max_text_size</item>
- </style>
-
- <style name="ToolbarText.MoreThanTwoLines">
- <item name="android:textSize">@dimen/tool_bar_min_text_size</item>
- </style>
+ <style name="ToolbarText.Collapsed" parent="CollapsingToolbarTitle.Collapsed"/>
+ <style name="ToolbarText" parent="CollapsingToolbarTitle"/>
+ <style name="ToolbarText.MoreThanTwoLines" parent="CollapsingToolbarTitle.MoreThanTwoLines"/>
</resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index bed02c8..d7b3257 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -23,10 +23,7 @@
<item name="android:windowIsFloating">true</item>
</style>
- <style name="Theme.SettingsBase" parent="@android:style/Theme.DeviceDefault.Settings" />
-
<style name="Theme.Settings" parent="Theme.SettingsBase">
- <item name="preferenceTheme">@style/PreferenceTheme</item>
<item name="android:clipToPadding">false</item>
<item name="android:clipChildren">false</item>
<item name="android:listPreferredItemHeight">72dip</item>
diff --git a/res/xml/accounts_dashboard_settings.xml b/res/xml/accounts_dashboard_settings.xml
index d2affc7..c50eca4 100644
--- a/res/xml/accounts_dashboard_settings.xml
+++ b/res/xml/accounts_dashboard_settings.xml
@@ -22,27 +22,57 @@
settings:keywords="@string/keywords_accounts">
<PreferenceCategory
- android:key="dashboard_tile_placeholder"
- android:order="30"/>
+ android:key="passwords_category"
+ android:order="10"
+ android:persistent="false"
+ android:title="@string/autofill_passwords"
+ settings:controller="com.android.settings.applications.autofill.PasswordsPreferenceController"
+ settings:keywords="@string/autofill_keywords" />
- <SwitchPreference
- android:key="auto_sync_account_data"
- android:title="@string/auto_sync_account_title"
- android:summary="@string/auto_sync_account_summary"
- android:order="102"
- settings:allowDividerAbove="true"/>
+ <PreferenceCategory
+ android:key="default_service_category"
+ android:order="20"
+ android:title="@string/autofill_app">
- <SwitchPreference
- android:key="auto_sync_work_account_data"
- android:title="@string/account_settings_menu_auto_sync_work"
- android:summary="@string/auto_sync_account_summary"
- settings:forWork="true"
- android:order="103"/>
+ <com.android.settings.widget.GearPreference
+ android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
+ android:key="default_autofill_main"
+ android:title="@string/autofill_app"
+ settings:keywords="@string/autofill_keywords">
+ <extra
+ android:name="for_work"
+ android:value="false" />
+ </com.android.settings.widget.GearPreference>
+ </PreferenceCategory>
- <SwitchPreference
- android:key="auto_sync_personal_account_data"
- android:title="@string/account_settings_menu_auto_sync_personal"
- android:summary="@string/auto_sync_account_summary"
- android:order="104"/>
+ <PreferenceCategory
+ android:key="accounts_category"
+ android:order="100"
+ android:title="@string/account_settings">
+
+ <PreferenceCategory
+ android:key="dashboard_tile_placeholder"
+ android:order="130"/>
+
+ <SwitchPreference
+ android:key="auto_sync_account_data"
+ android:title="@string/auto_sync_account_title"
+ android:summary="@string/auto_sync_account_summary"
+ android:order="202"
+ settings:allowDividerAbove="true"/>
+
+ <SwitchPreference
+ android:key="auto_sync_work_account_data"
+ android:title="@string/account_settings_menu_auto_sync_work"
+ android:summary="@string/auto_sync_account_summary"
+ settings:forWork="true"
+ android:order="203"/>
+
+ <SwitchPreference
+ android:key="auto_sync_personal_account_data"
+ android:title="@string/account_settings_menu_auto_sync_personal"
+ android:summary="@string/auto_sync_account_summary"
+ android:order="204"/>
+ </PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/accounts_personal_dashboard_settings.xml b/res/xml/accounts_personal_dashboard_settings.xml
index db57e3d..3d88cf9 100644
--- a/res/xml/accounts_personal_dashboard_settings.xml
+++ b/res/xml/accounts_personal_dashboard_settings.xml
@@ -23,20 +23,50 @@
settings:keywords="@string/keywords_accounts">
<PreferenceCategory
- android:key="dashboard_tile_placeholder"
- android:order="30"/>
+ android:key="passwords_category"
+ android:order="10"
+ android:persistent="false"
+ android:title="@string/autofill_passwords"
+ settings:controller="com.android.settings.applications.autofill.PasswordsPreferenceController"
+ settings:keywords="@string/autofill_keywords" />
- <SwitchPreference
- android:key="auto_sync_account_data"
- android:title="@string/auto_sync_account_title"
- android:summary="@string/auto_sync_account_summary"
+ <PreferenceCategory
+ android:key="default_service_category"
+ android:order="20"
+ android:title="@string/autofill_app">
+
+ <com.android.settings.widget.GearPreference
+ android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
+ android:key="default_autofill_main"
+ android:title="@string/autofill_app"
+ settings:keywords="@string/autofill_keywords">
+ <extra
+ android:name="for_work"
+ android:value="false" />
+ </com.android.settings.widget.GearPreference>
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="accounts_category"
android:order="100"
- settings:allowDividerAbove="true"/>
+ android:title="@string/account_settings">
- <SwitchPreference
- android:key="auto_sync_personal_account_data"
- android:title="@string/account_settings_menu_auto_sync_personal"
- android:summary="@string/auto_sync_account_summary"
- android:order="110"/>
+ <PreferenceCategory
+ android:key="dashboard_tile_placeholder"
+ android:order="130"/>
+
+ <SwitchPreference
+ android:key="auto_sync_account_data"
+ android:title="@string/auto_sync_account_title"
+ android:summary="@string/auto_sync_account_summary"
+ android:order="200"
+ settings:allowDividerAbove="true"/>
+
+ <SwitchPreference
+ android:key="auto_sync_personal_account_data"
+ android:title="@string/account_settings_menu_auto_sync_personal"
+ android:summary="@string/auto_sync_account_summary"
+ android:order="210"/>
+ </PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/accounts_work_dashboard_settings.xml b/res/xml/accounts_work_dashboard_settings.xml
index b27357d..29e71e2 100644
--- a/res/xml/accounts_work_dashboard_settings.xml
+++ b/res/xml/accounts_work_dashboard_settings.xml
@@ -23,20 +23,50 @@
settings:keywords="@string/keywords_accounts">
<PreferenceCategory
- android:key="dashboard_tile_placeholder"
- android:order="30"/>
+ android:key="passwords_category"
+ android:order="10"
+ android:persistent="false"
+ android:title="@string/autofill_passwords"
+ settings:controller="com.android.settings.applications.autofill.PasswordsPreferenceController"
+ settings:keywords="@string/autofill_keywords" />
- <SwitchPreference
- android:key="auto_sync_account_data"
- android:title="@string/auto_sync_account_title"
- android:summary="@string/auto_sync_account_summary"
+ <com.android.settings.widget.WorkOnlyCategory
+ android:key="autofill_work_app_defaults"
+ android:order="30"
+ android:title="@string/default_for_work">
+
+ <com.android.settings.widget.GearPreference
+ android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
+ android:key="default_autofill_work"
+ android:title="@string/autofill_app"
+ settings:searchable="false">
+ <extra
+ android:name="for_work"
+ android:value="true" />
+ </com.android.settings.widget.GearPreference>
+ </com.android.settings.widget.WorkOnlyCategory>
+
+ <PreferenceCategory
+ android:key="accounts_category"
android:order="100"
- settings:allowDividerAbove="true"/>
+ android:title="@string/account_settings">
- <SwitchPreference
- android:key="auto_sync_work_account_data"
- android:title="@string/account_settings_menu_auto_sync_work"
- android:summary="@string/auto_sync_account_summary"
- android:order="110"/>
+ <PreferenceCategory
+ android:key="dashboard_tile_placeholder"
+ android:order="130"/>
+
+ <SwitchPreference
+ android:key="auto_sync_account_data"
+ android:title="@string/auto_sync_account_title"
+ android:summary="@string/auto_sync_account_summary"
+ android:order="200"
+ settings:allowDividerAbove="true"/>
+
+ <SwitchPreference
+ android:key="auto_sync_work_account_data"
+ android:title="@string/account_settings_menu_auto_sync_work"
+ android:summary="@string/auto_sync_account_summary"
+ android:order="210"/>
+ </PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/apps.xml b/res/xml/apps.xml
index cefb67a..68b5c9a 100644
--- a/res/xml/apps.xml
+++ b/res/xml/apps.xml
@@ -23,7 +23,7 @@
<Preference
android:key="all_app_infos"
- android:title="@string/applications_settings"
+ android:title="@string/all_apps"
android:summary="@string/summary_placeholder"
android:order="-999"
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
diff --git a/res/xml/default_autofill_picker_settings.xml b/res/xml/default_autofill_picker_settings.xml
deleted file mode 100644
index 392f733..0000000
--- a/res/xml/default_autofill_picker_settings.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:settings="http://schemas.android.com/apk/res-auto"
- android:key="default_autofill_picker"
- android:title="@string/autofill_app"
- settings:keywords="@string/autofill_keywords">
-
- <PreferenceCategory
- android:key="passwords_category"
- android:persistent="false"
- android:title="@string/autofill_passwords"
- settings:controller="com.android.settings.applications.autofill.PasswordsPreferenceController" >
- </PreferenceCategory>
-
- <PreferenceCategory
- android:key="default_service_category"
- android:title="@string/autofill_app">
-
- <!-- TODO(b/169455298): Fix the redundant title. -->
- <com.android.settings.widget.GearPreference
- android:key="default_autofill_main"
- android:title="@string/autofill_app"
- android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
- settings:searchable="false"
- settings:keywords="@string/autofill_keywords">
- <extra android:name="for_work" android:value="false" />
- </com.android.settings.widget.GearPreference>
- </PreferenceCategory>
-
-
- <com.android.settings.widget.WorkOnlyCategory
- android:key="autofill_work_app_defaults"
- android:title="@string/default_for_work">
-
- <com.android.settings.widget.GearPreference
- android:key="default_autofill_work"
- android:title="@string/autofill_app"
- android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
- settings:searchable="false"
- settings:keywords="@string/autofill_keywords">
- <extra android:name="for_work" android:value="true" />
- </com.android.settings.widget.GearPreference>
- </com.android.settings.widget.WorkOnlyCategory>
-</PreferenceScreen>
diff --git a/res/xml/display_settings_v2.xml b/res/xml/display_settings_v2.xml
index 0b43914..50879da 100644
--- a/res/xml/display_settings_v2.xml
+++ b/res/xml/display_settings_v2.xml
@@ -59,7 +59,7 @@
</PreferenceCategory>
<PreferenceCategory
- android:title="@string/category_name_visibility">
+ android:title="@string/category_name_appearance">
<com.android.settings.display.darkmode.DarkModePreference
android:key="dark_ui_mode"
@@ -102,7 +102,7 @@
</PreferenceCategory>
<PreferenceCategory
- android:title="@string/category_name_general">
+ android:title="@string/category_name_display_controls">
<SwitchPreference
android:key="auto_rotate"
diff --git a/res/xml/emergency_settings.xml b/res/xml/emergency_settings.xml
index 28ae8b1..80d6ac0 100644
--- a/res/xml/emergency_settings.xml
+++ b/res/xml/emergency_settings.xml
@@ -32,6 +32,13 @@
android:order="100"
android:fragment="com.android.settings.emergency.EmergencyGestureSettings"
settings:controller="com.android.settings.emergency.EmergencyGestureEntrypointPreferenceController" />
+ <com.android.settingslib.widget.LayoutPreference
+ android:key="more_settings"
+ android:layout="@layout/more_settings_button"
+ android:order="180"
+ android:selectable="false"
+ settings:allowDividerBelow="true"
+ settings:controller="com.android.settings.emergency.MoreSettingsPreferenceController" />
<com.android.settingslib.RestrictedPreference
android:key="app_and_notif_cell_broadcast_settings"
android:title="@string/cell_broadcast_settings"
diff --git a/res/xml/financed_privacy_settings.xml b/res/xml/financed_privacy_settings.xml
new file mode 100644
index 0000000..742d7e1
--- /dev/null
+++ b/res/xml/financed_privacy_settings.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/financed_privacy_settings">
+
+ <PreferenceCategory android:key="exposure_category"
+ android:order="200"
+ android:title="@string/financed_privacy_exposure_category"
+ android:contentDescription="@string/financed_privacy_exposure_category">
+ <Preference android:key="enterprise_privacy_enterprise_data"
+ android:order="210"
+ android:layout_height="wrap_content"
+ android:title="@string/financed_privacy_data"
+ android:selectable="false"/>
+ <Preference android:key="enterprise_privacy_installed_packages"
+ android:order="220"
+ android:title="@string/enterprise_privacy_installed_packages"
+ android:selectable="false"/>
+ <Preference android:key="enterprise_privacy_usage_stats"
+ android:order="230"
+ android:title="@string/enterprise_privacy_usage_stats"
+ android:selectable="false"/>
+ <Preference android:key="network_logs"
+ android:order="240"
+ android:title="@string/enterprise_privacy_network_logs"
+ android:selectable="false"/>
+ <Preference android:key="bug_reports"
+ android:order="250"
+ android:title="@string/enterprise_privacy_bug_reports"
+ android:selectable="false"/>
+ <Preference android:key="security_logs"
+ android:order="260"
+ android:title="@string/enterprise_privacy_security_logs"
+ android:selectable="false"/>
+ </PreferenceCategory>
+
+ <PreferenceCategory android:title="@string/financed_privacy_exposure_changes_category"
+ android:order="300"
+ android:key="exposure_changes_category">
+ <Preference android:fragment="com.android.settings.enterprise.ApplicationListFragment$EnterpriseInstalledPackages"
+ android:order="310"
+ android:key="number_enterprise_installed_packages"
+ android:title="@string/enterprise_privacy_enterprise_installed_packages"/>
+ </PreferenceCategory>
+
+ <PreferenceCategory android:key="device_access_category"
+ android:order="500"
+ android:title="@string/enterprise_privacy_device_access_category">
+ <Preference android:key="enterprise_privacy_lock_device"
+ android:order="510"
+ android:title="@string/financed_privacy_lock_device"
+ android:selectable="false"/>
+ <Preference android:key="enterprise_privacy_wipe_device"
+ android:order="520"
+ android:title="@string/financed_privacy_wipe_device"
+ android:selectable="false"/>
+ <Preference android:key="failed_password_wipe_current_user"
+ android:order="530"
+ android:title="@string/financed_privacy_failed_password_wipe_device"
+ android:selectable="false"/>
+ </PreferenceCategory>
+
+ <com.android.settingslib.widget.FooterPreference
+ android:key="financed_privacy_footer"
+ android:title="@string/financed_privacy_header"
+ android:selectable="false"
+ settings:searchable="false"/>
+</PreferenceScreen>
diff --git a/res/xml/installed_app_launch_settings.xml b/res/xml/installed_app_launch_settings.xml
index b777949..d631e56 100644
--- a/res/xml/installed_app_launch_settings.xml
+++ b/res/xml/installed_app_launch_settings.xml
@@ -16,31 +16,59 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/launch_by_default">
- <PreferenceCategory android:key="app_launch_domain_links"
- android:title="@string/app_launch_domain_links_title">
+ <com.android.settingslib.widget.MainSwitchPreference
+ android:key="open_by_default_supported_links"
+ android:title="@string/app_launch_open_domain_urls_title"/>
- <Preference
- android:key="app_link_state"
- android:summary="@string/summary_placeholder"
- android:title="@string/app_launch_open_domain_urls_title"/>
+ <com.android.settingslib.widget.TopIntroPreference
+ android:key="open_by_default_top_intro"
+ android:title="@string/app_launch_top_intro_message"/>
- <com.android.settings.applications.AppDomainsPreference
- android:key="app_launch_supported_domain_urls"
- android:title="@string/app_launch_supported_domain_urls_title"
- android:dependency="app_link_state"
- />
+ <PreferenceCategory
+ android:layout="@layout/preference_category_no_label"
+ android:key="open_by_default_main_category"
+ settings:searchable="false">
+
+ <PreferenceCategory
+ android:title="@string/app_launch_links_category">
+
+ <com.android.settings.applications.intentpicker.VerifiedLinksPreference
+ android:key="open_by_default_verified_links"
+ android:title="@string/summary_placeholder"
+ android:order="-100"
+ settings:searchable="false"/>
+
+ <PreferenceCategory
+ android:layout="@layout/preference_category_no_label"
+ android:key="open_by_default_selected_links_category"
+ android:order="100"
+ settings:searchable="false"/>
+
+ <Preference
+ android:key="open_by_default_add_link"
+ android:title="@string/app_launch_add_link"
+ android:order="300"
+ android:icon="@drawable/ic_add_24dp"/>
+
+ </PreferenceCategory>
+
+ <PreferenceCategory android:key="app_launch_other_defaults"
+ android:title="@string/app_launch_other_defaults_title">
+
+ <com.android.settings.applications.ClearDefaultsPreference
+ android:key="app_launch_clear_defaults"
+ android:selectable="false"/>
+
+ </PreferenceCategory>
+
+ <com.android.settingslib.widget.FooterPreference
+ android:key="open_by_default_footer"
+ android:selectable="false"
+ settings:allowDividerAbove="true"
+ settings:searchable="false"/>
</PreferenceCategory>
-
- <PreferenceCategory android:key="app_launch_other_defaults"
- android:title="@string/app_launch_other_defaults_title">
-
- <com.android.settings.applications.ClearDefaultsPreference
- android:key="app_launch_clear_defaults"
- android:selectable="false"/>
-
- </PreferenceCategory>
-
</PreferenceScreen>
diff --git a/res/xml/language_and_input.xml b/res/xml/language_and_input.xml
index 50968d9..d7b8364 100644
--- a/res/xml/language_and_input.xml
+++ b/res/xml/language_and_input.xml
@@ -54,12 +54,6 @@
android:persistent="false"
android:fragment="com.android.settings.inputmethod.SpellCheckersSettings" />
- <Preference
- android:key="default_autofill"
- android:title="@string/autofill_app"
- android:fragment="com.android.settings.applications.defaultapps.AutofillPicker"
- settings:keywords="@string/autofill_keywords" />
-
<!-- User dictionary preference title and fragment will be set programmatically. -->
<Preference
android:key="key_user_dictionary_settings"
diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml
index bb7117d..4c760aa 100644
--- a/res/xml/network_provider_internet.xml
+++ b/res/xml/network_provider_internet.xml
@@ -98,7 +98,7 @@
android:order="10"
android:fragment="com.android.settings.datausage.DataSaverSummary"/>
- <com.android.settingslib.RestrictedPreference
+ <com.android.settings.vpn2.VpnInfoPreference
android:fragment="com.android.settings.vpn2.VpnSettings"
android:key="vpn_settings"
android:title="@string/vpn_settings_title"
diff --git a/res/xml/storage_dashboard_fragment.xml b/res/xml/storage_dashboard_fragment.xml
index b49228e..076405f 100644
--- a/res/xml/storage_dashboard_fragment.xml
+++ b/res/xml/storage_dashboard_fragment.xml
@@ -21,68 +21,64 @@
android:orderingFromXml="false">
<com.android.settingslib.widget.SettingsSpinnerPreference
android:key="storage_spinner"
- android:order="-2"
+ android:order="1"
settings:searchable="false"
settings:controller="com.android.settings.deviceinfo.storage.StorageSelectionPreferenceController"/>
<com.android.settingslib.widget.UsageProgressBarPreference
android:key="storage_summary"
- android:order="-1"
+ android:order="2"
settings:searchable="false"
- settings:controller="com.android.settings.deviceinfo.storage.StorageUsageProgressBarPreferenceController"/>
- <Preference
- android:key="free_up_space"
- android:order="0"
- android:title="@string/storage_free_up_space_title"
- android:summary="@string/storage_free_up_space_summary"
- settings:allowDividerAbove="true"/>
+ settings:controller="com.android.settings.deviceinfo.storage.StorageUsageProgressBarPreferenceController"
+ settings:allowDividerBelow="true"/>
<com.android.settings.widget.PrimarySwitchPreference
android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings"
android:key="toggle_asm"
android:title="@string/automatic_storage_manager_preference_title"
android:icon="@drawable/ic_storage"
- android:order="1"
+ android:order="3"
settings:allowDividerAbove="true"
- settings:allowDividerBelow="true"
- settings:controller="com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchPreferenceController" />
+ settings:controller="com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchPreferenceController"/>
+ <Preference
+ android:key="free_up_space"
+ android:order="4"
+ android:title="@string/storage_free_up_space_title"
+ android:summary="@string/storage_free_up_space_summary"/>
+ <!-- Preference order 100~200 are 'ONLY' for storage category preferences below. -->
<com.android.settings.deviceinfo.StorageItemPreference
- android:key="pref_photos_videos"
- android:title="@string/storage_photos_videos"
- android:icon="@drawable/ic_photo_library"
- settings:allowDividerAbove="true"
- android:order="2" />
+ android:key="pref_images"
+ android:title="@string/storage_images"
+ android:icon="@drawable/ic_photo_library"/>
<com.android.settings.deviceinfo.StorageItemPreference
- android:key="pref_music_audio"
- android:title="@string/storage_music_audio"
- android:icon="@drawable/ic_media_stream"
- android:order="3" />
+ android:key="pref_videos"
+ android:title="@string/storage_videos"
+ android:icon="@drawable/ic_local_movies"/>
+ <com.android.settings.deviceinfo.StorageItemPreference
+ android:key="pref_audios"
+ android:title="@string/storage_audios"
+ android:icon="@drawable/ic_media_stream"/>
+ <com.android.settings.deviceinfo.StorageItemPreference
+ android:key="pref_apps"
+ android:title="@string/storage_apps"
+ android:icon="@drawable/ic_storage_apps"/>
<com.android.settings.deviceinfo.StorageItemPreference
android:key="pref_games"
android:title="@string/storage_games"
- android:icon="@drawable/ic_videogame_vd_theme_24"
- android:order="4" />
+ android:icon="@drawable/ic_videogame_vd_theme_24"/>
<com.android.settings.deviceinfo.StorageItemPreference
- android:key="pref_movies"
- android:title="@string/storage_movies_tv"
- android:icon="@drawable/ic_local_movies"
- android:order="5" />
- <com.android.settings.deviceinfo.StorageItemPreference
- android:key="pref_other_apps"
- android:title="@string/storage_other_apps"
- android:icon="@drawable/ic_storage_apps"
- android:order="6" />
- <com.android.settings.deviceinfo.StorageItemPreference
- android:key="pref_files"
- android:title="@string/storage_files"
- android:icon="@drawable/ic_folder_vd_theme_24"
- android:order="7"
- settings:keywords="@string/keywords_storage_files"/>
+ android:key="pref_documents_and_other"
+ android:title="@string/storage_documents_and_other"
+ android:icon="@drawable/ic_folder_vd_theme_24"/>
<com.android.settings.deviceinfo.StorageItemPreference
android:key="pref_system"
- android:title="@string/storage_detail_system"
- android:icon="@drawable/ic_system_update"
- android:order="100" />
+ android:title="@string/storage_system"
+ android:icon="@drawable/ic_system_update"/>
+ <com.android.settings.deviceinfo.StorageItemPreference
+ android:key="pref_trash"
+ android:title="@string/storage_trash"
+ android:icon="@drawable/ic_trash_can"/>
+ <!-- Preference order 100~200 are 'ONLY' for storage category preferences above. -->
<PreferenceCategory
android:key="pref_secondary_users"
android:title="@string/storage_other_users"
- android:order="200" />
+ android:order="201" />
</PreferenceScreen>
diff --git a/res/xml/swipe_bottom_to_notification_settings.xml b/res/xml/swipe_bottom_to_notification_settings.xml
index bec774b..2a75c14 100644
--- a/res/xml/swipe_bottom_to_notification_settings.xml
+++ b/res/xml/swipe_bottom_to_notification_settings.xml
@@ -20,11 +20,13 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/swipe_bottom_to_notifications_title">
- <com.android.settings.widget.VideoPreference
- android:title="@string/swipe_bottom_to_notifications_title"
- settings:animation="@raw/gesture_fingerprint_swipe"
- settings:preview="@drawable/gesture_fingerprint_swipe"
- settings:controller="com.android.settings.widget.VideoPreferenceController"/>
+ <com.android.settingslib.widget.LayoutPreference
+ android:key="one_handed_header"
+ android:layout="@layout/one_handed_header"
+ android:persistent="false"
+ android:selectable="false"
+ settings:allowDividerBelow="false"
+ settings:searchable="false"/>
<SwitchPreference
android:key="gesture_swipe_bottom_to_notification"
diff --git a/res/xml/wifi_network_details_fragment2.xml b/res/xml/wifi_network_details_fragment2.xml
index 181b799..cb24a8f 100644
--- a/res/xml/wifi_network_details_fragment2.xml
+++ b/res/xml/wifi_network_details_fragment2.xml
@@ -101,6 +101,11 @@
android:key="ip_details_category"
android:title="@string/wifi_setup_detail">
<Preference
+ android:key="type"
+ android:title="@string/wifi_type_title"
+ android:selectable="false"
+ settings:enableCopying="true"/>
+ <Preference
android:key="ssid"
android:title="@string/wifi_advanced_ssid_title"
android:selectable="false"
diff --git a/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java b/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java
index 82b3a64..bfe61b7 100644
--- a/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java
+++ b/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceController.java
@@ -18,8 +18,8 @@
import android.content.Context;
import android.hardware.display.ColorDisplayManager;
-import android.provider.Settings;
+import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
/** PreferenceController that shows the Reduce Bright Colors summary */
@@ -32,8 +32,8 @@
@Override
public CharSequence getSummary() {
- return AccessibilityUtil.getSummary(mContext,
- Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED);
+ return mContext.getText(
+ R.string.reduce_bright_colors_preference_summary);
}
@Override
diff --git a/src/com/android/settings/accessibility/ShortcutPreference.java b/src/com/android/settings/accessibility/ShortcutPreference.java
index a9b542a..cff9117 100644
--- a/src/com/android/settings/accessibility/ShortcutPreference.java
+++ b/src/com/android/settings/accessibility/ShortcutPreference.java
@@ -63,7 +63,7 @@
super(context, attrs);
setLayoutResource(R.layout.accessibility_shortcut_secondary_action);
setWidgetLayoutResource(R.layout.preference_widget_primary_switch);
- setIconSpaceReserved(true);
+ setIconSpaceReserved(false);
}
@Override
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index cf9c08b..be6b141 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -488,7 +488,7 @@
// Show the "Settings" menu as if it were a preference screen.
mSettingsPreference = new Preference(getPrefContext());
mSettingsPreference.setTitle(mSettingsTitle);
- mSettingsPreference.setIconSpaceReserved(true);
+ mSettingsPreference.setIconSpaceReserved(false);
mSettingsPreference.setIntent(mSettingsIntent);
final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY);
diff --git a/src/com/android/settings/accessibility/TurnScreenDarkerFragment.java b/src/com/android/settings/accessibility/TurnScreenDarkerFragment.java
index ad4bd56..0e0a600 100644
--- a/src/com/android/settings/accessibility/TurnScreenDarkerFragment.java
+++ b/src/com/android/settings/accessibility/TurnScreenDarkerFragment.java
@@ -94,8 +94,6 @@
if (ColorDisplayManager.isColorTransformAccelerated(getContext())) {
mToggleInversionPreference.setSummary(AccessibilityUtil.getSummary(
getContext(), Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED));
- mReduceBrightColorsPreference.setSummary(AccessibilityUtil.getSummary(
- getContext(), Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED));
getPreferenceScreen().removePreference(experimentalCategory);
} else {
// Move following preferences to experimental category if device don't supports HWC
diff --git a/src/com/android/settings/accounts/AccountDashboardFragment.java b/src/com/android/settings/accounts/AccountDashboardFragment.java
index 7b50b46..9e232f4 100644
--- a/src/com/android/settings/accounts/AccountDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDashboardFragment.java
@@ -27,6 +27,8 @@
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.applications.defaultapps.DefaultAutofillPreferenceController;
+import com.android.settings.applications.defaultapps.DefaultWorkAutofillPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -68,14 +70,22 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ buildAutofillPreferenceControllers(context, controllers);
final String[] authorities = getIntent().getStringArrayExtra(EXTRA_AUTHORITIES);
- return buildPreferenceControllers(context, this /* parent */, authorities);
+ buildAccountPreferenceControllers(context, this /* parent */, authorities, controllers);
+ return controllers;
}
- private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
- SettingsPreferenceFragment parent, String[] authorities) {
- final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ static void buildAutofillPreferenceControllers(
+ Context context, List<AbstractPreferenceController> controllers) {
+ controllers.add(new DefaultAutofillPreferenceController(context));
+ controllers.add(new DefaultWorkAutofillPreferenceController(context));
+ }
+ private static void buildAccountPreferenceControllers(
+ Context context, SettingsPreferenceFragment parent, String[] authorities,
+ List<AbstractPreferenceController> controllers) {
final AccountPreferenceController accountPrefController =
new AccountPreferenceController(context, parent, authorities,
ProfileSelectFragment.ProfileType.ALL);
@@ -86,7 +96,6 @@
controllers.add(new AutoSyncDataPreferenceController(context, parent));
controllers.add(new AutoSyncPersonalDataPreferenceController(context, parent));
controllers.add(new AutoSyncWorkDataPreferenceController(context, parent));
- return controllers;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
@@ -95,8 +104,11 @@
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
- return buildPreferenceControllers(
- context, null /* parent */, null /* authorities*/);
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ buildAccountPreferenceControllers(
+ context, null /* parent */, null /* authorities*/, controllers);
+ buildAutofillPreferenceControllers(context, controllers);
+ return controllers;
}
@Override
diff --git a/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java b/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
index f29326e..c97c886 100644
--- a/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
@@ -18,6 +18,8 @@
import static android.provider.Settings.EXTRA_AUTHORITIES;
+import static com.android.settings.accounts.AccountDashboardFragment.buildAutofillPreferenceControllers;
+
import android.app.settings.SettingsEnums;
import android.content.Context;
@@ -61,14 +63,16 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ buildAutofillPreferenceControllers(context, controllers);
final String[] authorities = getIntent().getStringArrayExtra(EXTRA_AUTHORITIES);
- return buildPreferenceControllers(context, this /* parent */, authorities);
+ buildAccountPreferenceControllers(context, this /* parent */, authorities, controllers);
+ return controllers;
}
- private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
- SettingsPreferenceFragment parent, String[] authorities) {
- final List<AbstractPreferenceController> controllers = new ArrayList<>();
-
+ private static void buildAccountPreferenceControllers(
+ Context context, SettingsPreferenceFragment parent, String[] authorities,
+ List<AbstractPreferenceController> controllers) {
final AccountPreferenceController accountPrefController =
new AccountPreferenceController(context, parent, authorities,
ProfileSelectFragment.ProfileType.PERSONAL);
@@ -78,7 +82,6 @@
controllers.add(accountPrefController);
controllers.add(new AutoSyncDataPreferenceController(context, parent));
controllers.add(new AutoSyncPersonalDataPreferenceController(context, parent));
- return controllers;
}
// TODO: b/141601408. After featureFlag settings_work_profile is launched, unmark this
@@ -88,6 +91,7 @@
// @Override
// public List<AbstractPreferenceController> createPreferenceControllers(
// Context context) {
+// ..Add autofill here too..
// return buildPreferenceControllers(
// context, null /* parent */, null /* authorities*/);
// }
diff --git a/src/com/android/settings/accounts/AccountPreferenceController.java b/src/com/android/settings/accounts/AccountPreferenceController.java
index ff5bc78..64c2d13 100644
--- a/src/com/android/settings/accounts/AccountPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountPreferenceController.java
@@ -75,11 +75,12 @@
private static final String TAG = "AccountPrefController";
- private static final int ORDER_ACCOUNT_PROFILES = 1;
+ private static final int ORDER_ACCOUNT_PROFILES = 101;
private static final int ORDER_LAST = 1002;
private static final int ORDER_NEXT_TO_LAST = 1001;
private static final int ORDER_NEXT_TO_NEXT_TO_LAST = 1000;
+ private static final String PREF_KEY_ACCOUNTS = "accounts_category";
private static final String PREF_KEY_ADD_ACCOUNT = "add_account";
private static final String PREF_KEY_REMOVE_PROFILE = "remove_profile";
private static final String PREF_KEY_WORK_PROFILE_SETTING = "work_profile_setting";
@@ -348,8 +349,10 @@
}
}
final PreferenceScreen screen = mFragment.getPreferenceScreen();
- if (screen != null) {
- screen.addPreference(preferenceGroup);
+ final PreferenceGroup accounts =
+ screen == null ? null : screen.findPreference(PREF_KEY_ACCOUNTS);
+ if (accounts != null) {
+ accounts.addPreference(preferenceGroup);
}
profileData.preferenceGroup = preferenceGroup;
if (userInfo.isEnabled()) {
diff --git a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
index 853c66b..4e6515b 100644
--- a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
@@ -18,6 +18,8 @@
import static android.provider.Settings.EXTRA_AUTHORITIES;
+import static com.android.settings.accounts.AccountDashboardFragment.buildAutofillPreferenceControllers;
+
import android.app.settings.SettingsEnums;
import android.content.Context;
@@ -61,14 +63,16 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ buildAutofillPreferenceControllers(context, controllers);
final String[] authorities = getIntent().getStringArrayExtra(EXTRA_AUTHORITIES);
- return buildPreferenceControllers(context, this /* parent */, authorities);
+ buildAccountPreferenceControllers(context, this /* parent */, authorities, controllers);
+ return controllers;
}
- private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
- SettingsPreferenceFragment parent, String[] authorities) {
- final List<AbstractPreferenceController> controllers = new ArrayList<>();
-
+ private static void buildAccountPreferenceControllers(
+ Context context, SettingsPreferenceFragment parent, String[] authorities,
+ List<AbstractPreferenceController> controllers) {
final AccountPreferenceController accountPrefController =
new AccountPreferenceController(context, parent, authorities,
ProfileSelectFragment.ProfileType.WORK);
@@ -78,7 +82,6 @@
controllers.add(accountPrefController);
controllers.add(new AutoSyncDataPreferenceController(context, parent));
controllers.add(new AutoSyncWorkDataPreferenceController(context, parent));
- return controllers;
}
// TODO: b/141601408. After featureFlag settings_work_profile is launched, unmark this
@@ -88,6 +91,7 @@
// @Override
// public List<AbstractPreferenceController> createPreferenceControllers(
// Context context) {
+// ..Add autofill here too..
// return buildPreferenceControllers(
// context, null /* parent */, null /* authorities*/);
// }
diff --git a/src/com/android/settings/accounts/AvatarViewMixin.java b/src/com/android/settings/accounts/AvatarViewMixin.java
index 7eb8cab..c4ab55a 100644
--- a/src/com/android/settings/accounts/AvatarViewMixin.java
+++ b/src/com/android/settings/accounts/AvatarViewMixin.java
@@ -17,7 +17,6 @@
package com.android.settings.accounts;
import android.accounts.Account;
-import android.app.ActivityManager;
import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.Context;
@@ -65,14 +64,23 @@
private final Context mContext;
private final ImageView mAvatarView;
private final MutableLiveData<Bitmap> mAvatarImage;
- private final ActivityManager mActivityManager;
@VisibleForTesting
String mAccountName;
+ /**
+ * @return true if the avatar icon is supported.
+ */
+ public static boolean isAvatarSupported(Context context) {
+ if (!context.getResources().getBoolean(R.bool.config_show_avatar_in_homepage)) {
+ Log.d(TAG, "Feature disabled by config. Skipping");
+ return false;
+ }
+ return true;
+ }
+
public AvatarViewMixin(SettingsHomepageActivity activity, ImageView avatarView) {
mContext = activity.getApplicationContext();
- mActivityManager = mContext.getSystemService(ActivityManager.class);
mAvatarView = avatarView;
mAvatarView.setOnClickListener(v -> {
Intent intent;
@@ -117,14 +125,6 @@
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
- if (!mContext.getResources().getBoolean(R.bool.config_show_avatar_in_homepage)) {
- Log.d(TAG, "Feature disabled by config. Skipping");
- return;
- }
- if (mActivityManager.isLowRamDevice()) {
- Log.d(TAG, "Feature disabled on low ram device. Skipping");
- return;
- }
if (hasAccount()) {
loadAccount();
} else {
diff --git a/src/com/android/settings/accounts/TopLevelAccountEntryPreferenceController.java b/src/com/android/settings/accounts/TopLevelAccountEntryPreferenceController.java
index 7cd746f..174ef0f 100644
--- a/src/com/android/settings/accounts/TopLevelAccountEntryPreferenceController.java
+++ b/src/com/android/settings/accounts/TopLevelAccountEntryPreferenceController.java
@@ -17,19 +17,11 @@
package com.android.settings.accounts;
import android.content.Context;
-import android.icu.text.ListFormatter;
-import android.os.UserHandle;
-import android.text.BidiFormatter;
-import android.text.TextUtils;
import android.util.FeatureFlagUtils;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.FeatureFlags;
-import com.android.settingslib.accounts.AuthenticatorHelper;
-
-import java.util.ArrayList;
-import java.util.List;
public class TopLevelAccountEntryPreferenceController extends BasePreferenceController {
public TopLevelAccountEntryPreferenceController(Context context, String preferenceKey) {
@@ -47,29 +39,6 @@
if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.SILKY_HOME)) {
return null;
}
-
- final AuthenticatorHelper authHelper = new AuthenticatorHelper(mContext,
- UserHandle.of(UserHandle.myUserId()), null /* OnAccountsUpdateListener */);
- final String[] types = authHelper.getEnabledAccountTypes();
- final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
- final List<CharSequence> summaries = new ArrayList<>();
-
- if (types == null || types.length == 0) {
- summaries.add(mContext.getString(R.string.account_dashboard_default_summary));
- } else {
- // Show up to 3 account types, ignore any null value
- int accountToAdd = Math.min(3, types.length);
-
- for (int i = 0; i < types.length && accountToAdd > 0; i++) {
- final CharSequence label = authHelper.getLabelForType(mContext, types[i]);
- if (TextUtils.isEmpty(label)) {
- continue;
- }
-
- summaries.add(bidiFormatter.unicodeWrap(label));
- accountToAdd--;
- }
- }
- return ListFormatter.getInstance().format(summaries);
+ return mContext.getString(R.string.account_dashboard_default_summary);
}
}
diff --git a/src/com/android/settings/applications/AppLaunchSettings.java b/src/com/android/settings/applications/AppLaunchSettings.java
deleted file mode 100644
index 86bc7ed..0000000
--- a/src/com/android/settings/applications/AppLaunchSettings.java
+++ /dev/null
@@ -1,152 +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.
- */
-
-package com.android.settings.applications;
-
-import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
-import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
-
-import android.app.settings.SettingsEnums;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.util.ArraySet;
-import android.view.View;
-import android.view.View.OnClickListener;
-
-import androidx.appcompat.app.AlertDialog;
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-import com.android.settings.Utils;
-import com.android.settings.core.SubSettingLauncher;
-import com.android.settingslib.applications.AppUtils;
-
-public class AppLaunchSettings extends AppInfoWithHeader implements OnClickListener,
- Preference.OnPreferenceChangeListener {
- private static final String TAG = "AppLaunchSettings";
- private static final String KEY_APP_LINK_STATE = "app_link_state";
- private static final String KEY_SUPPORTED_DOMAIN_URLS = "app_launch_supported_domain_urls";
- private static final String KEY_CLEAR_DEFAULTS = "app_launch_clear_defaults";
- private static final String FRAGMENT_OPEN_SUPPORTED_LINKS =
- "com.android.settings.applications.OpenSupportedLinks";
-
- private PackageManager mPm;
-
- private boolean mIsBrowser;
- private boolean mHasDomainUrls;
- private Preference mAppLinkState;
- private AppDomainsPreference mAppDomainUrls;
- private ClearDefaultsPreference mClearDefaultsPreference;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.installed_app_launch_settings);
- mAppDomainUrls = (AppDomainsPreference) findPreference(KEY_SUPPORTED_DOMAIN_URLS);
- mClearDefaultsPreference = (ClearDefaultsPreference) findPreference(KEY_CLEAR_DEFAULTS);
- mAppLinkState = findPreference(KEY_APP_LINK_STATE);
- mAppLinkState.setOnPreferenceClickListener(preference -> {
- final Bundle args = new Bundle();
- args.putString(ARG_PACKAGE_NAME, mPackageName);
- args.putInt(ARG_PACKAGE_UID, mUserId);
-
- new SubSettingLauncher(this.getContext())
- .setDestination(FRAGMENT_OPEN_SUPPORTED_LINKS)
- .setArguments(args)
- .setSourceMetricsCategory(SettingsEnums.APPLICATIONS_APP_LAUNCH)
- .setTitleRes(-1)
- .launch();
- return true;
- });
-
- mPm = getActivity().getPackageManager();
-
- mIsBrowser = AppUtils.isBrowserApp(this.getContext(), mPackageName, UserHandle.myUserId());
- mHasDomainUrls =
- (mAppEntry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
-
- if (!mIsBrowser) {
- CharSequence[] entries = getEntries(mPackageName);
- mAppDomainUrls.setTitles(entries);
- mAppDomainUrls.setValues(new int[entries.length]);
- mAppLinkState.setEnabled(mHasDomainUrls);
- } else {
- // Browsers don't show the app-link prefs
- mAppLinkState.setShouldDisableView(true);
- mAppLinkState.setEnabled(false);
- mAppDomainUrls.setShouldDisableView(true);
- mAppDomainUrls.setEnabled(false);
- }
- }
-
- private int linkStateToResourceId(int state) {
- switch (state) {
- case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
- return R.string.app_link_open_always; // Always
- case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER:
- return R.string.app_link_open_never; // Never
- default:
- return R.string.app_link_open_ask; // Ask
- }
- }
-
- private CharSequence[] getEntries(String packageName) {
- ArraySet<String> result = Utils.getHandledDomains(mPm, packageName);
- return result.toArray(new CharSequence[result.size()]);
- }
-
- private void setAppLinkStateSummary() {
- final int state = mPm.getIntentVerificationStatusAsUser(mPackageName,
- UserHandle.myUserId());
- mAppLinkState.setSummary(linkStateToResourceId(state));
- }
-
- @Override
- protected boolean refreshUi() {
- if (mHasDomainUrls) {
- //Update the summary after return from the OpenSupportedLinks
- setAppLinkStateSummary();
- }
- mClearDefaultsPreference.setPackageName(mPackageName);
- mClearDefaultsPreference.setAppEntry(mAppEntry);
- return true;
- }
-
- @Override
- protected AlertDialog createDialog(int id, int errorCode) {
- // No dialogs for preferred launch settings.
- return null;
- }
-
- @Override
- public void onClick(View v) {
- // Nothing to do
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- // actual updates are handled by the app link dropdown callback
- return true;
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.APPLICATIONS_APP_LAUNCH;
- }
-}
diff --git a/src/com/android/settings/applications/ClearDefaultsPreference.java b/src/com/android/settings/applications/ClearDefaultsPreference.java
index f946636..0952b9c 100644
--- a/src/com/android/settings/applications/ClearDefaultsPreference.java
+++ b/src/com/android/settings/applications/ClearDefaultsPreference.java
@@ -117,7 +117,7 @@
if (mUsbManager != null) {
final int userId = UserHandle.myUserId();
mPm.clearPackagePreferredActivities(mPackageName);
- if (isDefaultBrowser(mPackageName)) {
+ if (AppUtils.isDefaultBrowser(getContext(), mPackageName)) {
mPm.setDefaultBrowserPackageNameAsUser(null, userId);
}
try {
@@ -141,7 +141,7 @@
TextView autoLaunchView = (TextView) view.findViewById(R.id.auto_launch);
boolean autoLaunchEnabled = AppUtils.hasPreferredActivities(mPm, mPackageName)
- || isDefaultBrowser(mPackageName)
+ || AppUtils.isDefaultBrowser(getContext(), mPackageName)
|| AppUtils.hasUsbDefaults(mUsbManager, mPackageName);
if (!autoLaunchEnabled && !hasBindAppWidgetPermission) {
resetLaunchDefaultsUi(autoLaunchView);
@@ -185,11 +185,6 @@
return true;
}
- private boolean isDefaultBrowser(String packageName) {
- final String defaultBrowser = mPm.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId());
- return packageName.equals(defaultBrowser);
- }
-
private void resetLaunchDefaultsUi(TextView autoLaunchView) {
autoLaunchView.setText(R.string.auto_launch_disable_text);
// Disable clear activities button
diff --git a/src/com/android/settings/applications/HibernatedAppsPreferenceController.java b/src/com/android/settings/applications/HibernatedAppsPreferenceController.java
index 40cbb2e..4088d3a 100644
--- a/src/com/android/settings/applications/HibernatedAppsPreferenceController.java
+++ b/src/com/android/settings/applications/HibernatedAppsPreferenceController.java
@@ -20,15 +20,19 @@
import static com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED;
+import android.apphibernation.AppHibernationManager;
import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.provider.DeviceConfig;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
+import java.util.List;
+
/**
* A preference controller handling the logic for updating summary of hibernated apps.
- * TODO(b/181172051): add intent to launch Auto Revoke UI in app_and_notification.xml
*/
public final class HibernatedAppsPreferenceController extends BasePreferenceController {
private static final String TAG = "HibernatedAppsPrefController";
@@ -39,7 +43,8 @@
@Override
public int getAvailabilityStatus() {
- return isHibernationEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ return isHibernationEnabled() && getNumHibernated() > 0
+ ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
@@ -50,8 +55,27 @@
}
private int getNumHibernated() {
- //TODO(b/181172051): hook into hibernation service to get the number of hibernated apps.
- return 0;
+ final PackageManager pm = mContext.getPackageManager();
+ final AppHibernationManager ahm = mContext.getSystemService(AppHibernationManager.class);
+ final List<String> hibernatedPackages = ahm.getHibernatingPackagesForUser();
+ int numHibernated = hibernatedPackages.size();
+
+ // Also need to count packages that are auto revoked but not hibernated.
+ final List<PackageInfo> packages = pm.getInstalledPackages(
+ PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_PERMISSIONS);
+ for (PackageInfo pi : packages) {
+ final String packageName = pi.packageName;
+ if (!hibernatedPackages.contains(packageName) && pi.requestedPermissions != null) {
+ for (String perm : pi.requestedPermissions) {
+ if ((pm.getPermissionFlags(perm, packageName, mContext.getUser())
+ & PackageManager.FLAG_PERMISSION_AUTO_REVOKED) != 0) {
+ numHibernated++;
+ break;
+ }
+ }
+ }
+ }
+ return numHibernated;
}
private static boolean isHibernationEnabled() {
diff --git a/src/com/android/settings/applications/InstalledAppOpenByDefaultActivity.java b/src/com/android/settings/applications/InstalledAppOpenByDefaultActivity.java
index cd30d79..799389e 100644
--- a/src/com/android/settings/applications/InstalledAppOpenByDefaultActivity.java
+++ b/src/com/android/settings/applications/InstalledAppOpenByDefaultActivity.java
@@ -19,6 +19,7 @@
import android.content.Intent;
import com.android.settings.SettingsActivity;
+import com.android.settings.applications.intentpicker.AppLaunchSettings;
public class InstalledAppOpenByDefaultActivity extends SettingsActivity {
diff --git a/src/com/android/settings/applications/appinfo/AppOpenByDefaultPreferenceController.java b/src/com/android/settings/applications/appinfo/AppOpenByDefaultPreferenceController.java
index f9c88fc..d8c190f 100644
--- a/src/com/android/settings/applications/appinfo/AppOpenByDefaultPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppOpenByDefaultPreferenceController.java
@@ -28,7 +28,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.applications.AppLaunchSettings;
+import com.android.settings.applications.intentpicker.AppLaunchSettings;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
diff --git a/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java b/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java
index 8ab2c9d..40be629 100644
--- a/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceController.java
@@ -80,7 +80,8 @@
/**
* Set the package. And also retrieve details from package manager. Some packages may be
- * exempted from hibernation by default.
+ * exempted from hibernation by default. This method should only be called to initialize the
+ * controller.
* @param packageName The name of the package whose hibernation state to be managed.
*/
void setPackage(@NonNull String packageName) {
@@ -93,8 +94,7 @@
? android.os.Build.VERSION_CODES.R
: android.os.Build.VERSION_CODES.Q;
try {
- mPackageUid = packageManager.getPackageUidAsUser(
- packageName, mContext.getUserId());
+ mPackageUid = packageManager.getPackageUid(packageName, /* flags */ 0);
mIsPackageExemptByDefault = packageManager.getTargetSdkVersion(packageName)
<= maxTargetSdkVersionForExemptApps;
mIsPackageSet = true;
diff --git a/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java b/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java
index f27530e..47882de 100644
--- a/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java
+++ b/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java
@@ -16,37 +16,64 @@
package com.android.settings.applications.autofill;
+import static android.service.autofill.AutofillService.EXTRA_RESULT;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_CREATE;
+import static androidx.lifecycle.Lifecycle.Event.ON_DESTROY;
+
import android.annotation.UserIdInt;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
import android.os.UserHandle;
+import android.service.autofill.AutofillService;
import android.service.autofill.AutofillServiceInfo;
+import android.service.autofill.IAutoFillService;
import android.text.TextUtils;
import android.util.IconDrawableFactory;
+import android.util.Log;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.IResultReceiver;
+import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
+import java.lang.ref.WeakReference;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Queries available autofill services and adds preferences for those that declare passwords
* settings.
+ * <p>
+ * The controller binds to each service to fetch the number of saved passwords in each.
*/
-public class PasswordsPreferenceController extends BasePreferenceController {
+public class PasswordsPreferenceController extends BasePreferenceController
+ implements LifecycleObserver {
+ private static final String TAG = "AutofillSettings";
private final PackageManager mPm;
private final IconDrawableFactory mIconFactory;
private final List<AutofillServiceInfo> mServices;
+ private LifecycleOwner mLifecycleOwner;
+
public PasswordsPreferenceController(Context context, String preferenceKey) {
this(context, preferenceKey,
AutofillServiceInfo.getAvailableServices(context, UserHandle.myUserId()));
@@ -67,6 +94,11 @@
mServices = availableServices;
}
+ @OnLifecycleEvent(ON_CREATE)
+ void onCreate(LifecycleOwner lifecycleOwner) {
+ mLifecycleOwner = lifecycleOwner;
+ }
+
@Override
public int getAvailabilityStatus() {
return mServices.isEmpty() ? CONDITIONALLY_UNAVAILABLE : AVAILABLE;
@@ -96,7 +128,83 @@
pref.setIntent(
new Intent(Intent.ACTION_MAIN)
.setClassName(serviceInfo.packageName, service.getPasswordsActivity()));
+
+ final MutableLiveData<Integer> passwordCount = new MutableLiveData<>();
+ passwordCount.observe(
+ mLifecycleOwner, count -> {
+ // TODO(b/169455298): Validate the result.
+ final CharSequence summary =
+ mContext.getResources().getQuantityString(
+ R.plurals.autofill_passwords_count, count, count);
+ pref.setSummary(summary);
+ });
+ // TODO(b/169455298): Limit the number of concurrent queries.
+ // TODO(b/169455298): Cache the results for some time.
+ requestSavedPasswordCount(service, user, passwordCount);
+
group.addPreference(pref);
}
}
+
+ private void requestSavedPasswordCount(
+ AutofillServiceInfo service, @UserIdInt int user, MutableLiveData<Integer> data) {
+ final Intent intent =
+ new Intent(AutofillService.SERVICE_INTERFACE)
+ .setComponent(service.getServiceInfo().getComponentName());
+ final AutofillServiceConnection connection = new AutofillServiceConnection(mContext, data);
+ if (mContext.bindServiceAsUser(
+ intent, connection, Context.BIND_AUTO_CREATE, UserHandle.of(user))) {
+ connection.mBound.set(true);
+ mLifecycleOwner.getLifecycle().addObserver(connection);
+ }
+ }
+
+ private static class AutofillServiceConnection implements ServiceConnection, LifecycleObserver {
+ final WeakReference<Context> mContext;
+ final MutableLiveData<Integer> mData;
+ final AtomicBoolean mBound = new AtomicBoolean();
+
+ AutofillServiceConnection(Context context, MutableLiveData<Integer> data) {
+ mContext = new WeakReference<>(context);
+ mData = data;
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ final IAutoFillService autofillService = IAutoFillService.Stub.asInterface(service);
+ // TODO check if debug is logged on user build.
+ Log.d(TAG, "Fetching password count from " + name);
+ try {
+ autofillService.onSavedPasswordCountRequest(
+ new IResultReceiver.Stub() {
+ @Override
+ public void send(int resultCode, Bundle resultData) {
+ Log.d(TAG, "Received password count result " + resultCode
+ + " from " + name);
+ if (resultCode == 0 && resultData != null) {
+ mData.postValue(resultData.getInt(EXTRA_RESULT));
+ }
+ unbind();
+ }
+ });
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to fetch password count: " + e);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ }
+
+ @OnLifecycleEvent(ON_DESTROY)
+ void unbind() {
+ if (!mBound.getAndSet(false)) {
+ return;
+ }
+ final Context context = mContext.get();
+ if (context != null) {
+ context.unbindService(this);
+ }
+ }
+ }
}
diff --git a/src/com/android/settings/applications/defaultapps/AutofillPicker.java b/src/com/android/settings/applications/defaultapps/AutofillPicker.java
deleted file mode 100644
index 62a478f..0000000
--- a/src/com/android/settings/applications/defaultapps/AutofillPicker.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications.defaultapps;
-
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.provider.SearchIndexableResource;
-
-import com.android.settings.R;
-import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.search.Indexable;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.search.SearchIndexable;
-
-import java.util.Arrays;
-import java.util.List;
-
-@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
-public class AutofillPicker extends DashboardFragment {
- private static final String TAG = "AutofillPicker";
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DEFAULT_AUTOFILL_PICKER;
- }
-
- @Override
- protected String getLogTag() {
- return TAG;
- }
-
- @Override
- protected int getPreferenceScreenResId() {
- return R.xml.default_autofill_picker_settings;
- }
-
- @Override
- protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
- return buildPreferenceControllers(context);
- }
-
- public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider(R.xml.default_autofill_picker_settings) {
-
- @Override
- public List<AbstractPreferenceController> getPreferenceControllers(Context
- context) {
- return buildPreferenceControllers(context);
- }
- };
-
- private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
- return Arrays.asList(
- new DefaultAutofillPreferenceController(context),
- new DefaultWorkAutofillPreferenceController(context));
- }
-}
diff --git a/src/com/android/settings/applications/intentpicker/AppLaunchSettings.java b/src/com/android/settings/applications/intentpicker/AppLaunchSettings.java
new file mode 100644
index 0000000..7d6abe7
--- /dev/null
+++ b/src/com/android/settings/applications/intentpicker/AppLaunchSettings.java
@@ -0,0 +1,404 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.applications.intentpicker;
+
+import static android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_NONE;
+import static android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_SELECTED;
+import static android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_VERIFIED;
+
+import android.app.Activity;
+import android.app.settings.SettingsEnums;
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.verify.domain.DomainVerificationManager;
+import android.content.pm.verify.domain.DomainVerificationUserState;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.ArraySet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settings.applications.ClearDefaultsPreference;
+import com.android.settings.utils.AnnotationSpan;
+import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.widget.FooterPreference;
+import com.android.settingslib.widget.MainSwitchPreference;
+import com.android.settingslib.widget.OnMainSwitchChangeListener;
+
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+/** The page of the Open by default */
+public class AppLaunchSettings extends AppInfoBase implements
+ Preference.OnPreferenceChangeListener, OnMainSwitchChangeListener {
+ private static final String TAG = "AppLaunchSettings";
+ // Preference keys
+ private static final String MAIN_SWITCH_PREF_KEY = "open_by_default_supported_links";
+ private static final String VERIFIED_LINKS_PREF_KEY = "open_by_default_verified_links";
+ private static final String ADD_LINK_PREF_KEY = "open_by_default_add_link";
+ private static final String CLEAR_DEFAULTS_PREF_KEY = "app_launch_clear_defaults";
+ private static final String FOOTER_PREF_KEY = "open_by_default_footer";
+
+ private static final String MAIN_PREF_CATEGORY_KEY = "open_by_default_main_category";
+ private static final String SELECTED_LINKS_CATEGORY_KEY =
+ "open_by_default_selected_links_category";
+ private static final String OTHER_DETAILS_PREF_CATEGORY_KEY = "app_launch_other_defaults";
+
+ // Url and Uri
+ private static final String ANNOTATION_URL = "url";
+ private static final String LEARN_MORE_URI =
+ "https://developer.android.com/training/app-links/verify-site-associations";
+
+ // Dialogs id
+ private static final int DLG_VERIFIED_LINKS = DLG_BASE + 1;
+
+ // Arguments key
+ public static final String APP_PACKAGE_KEY = "app_package";
+
+ private ClearDefaultsPreference mClearDefaultsPreference;
+ private MainSwitchPreference mMainSwitchPreference;
+ private PreferenceCategory mMainPreferenceCategory;
+ private PreferenceCategory mSelectedLinksPreferenceCategory;
+ private PreferenceCategory mOtherDefaultsPreferenceCategory;
+
+ private boolean mActivityCreated;
+
+ @VisibleForTesting
+ Context mContext;
+ @VisibleForTesting
+ DomainVerificationManager mDomainVerificationManager;
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ mContext = context;
+ mActivityCreated = false;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.installed_app_launch_settings);
+ mDomainVerificationManager = mContext.getSystemService(DomainVerificationManager.class);
+ initUIComponents();
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ createHeaderPreference();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.APPLICATIONS_APP_LAUNCH;
+ }
+
+ @Override
+ protected AlertDialog createDialog(int id, int errorCode) {
+ if (id == DLG_VERIFIED_LINKS) {
+ return createVerifiedLinksDialog();
+ }
+ return null;
+ }
+
+ @Override
+ protected boolean refreshUi() {
+ mClearDefaultsPreference.setPackageName(mPackageName);
+ mClearDefaultsPreference.setAppEntry(mAppEntry);
+ return true;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean isChecked = (boolean) newValue;
+ IntentPickerUtils.logd(
+ "onPreferenceChange: " + preference.getTitle() + " isChecked: " + isChecked);
+ if ((preference instanceof LeftSideCheckBoxPreference) && !isChecked) {
+ final Set<String> domainSet = new ArraySet<>();
+ domainSet.add(preference.getTitle().toString());
+ removePreference(preference.getKey());
+ final DomainVerificationUserState userState =
+ IntentPickerUtils.getDomainVerificationUserState(mDomainVerificationManager,
+ mPackageName);
+ if (userState == null) {
+ return false;
+ }
+ setDomainVerificationUserSelection(userState.getIdentifier(), domainSet, /* enabled= */
+ false);
+ }
+ return true;
+ }
+
+ @Override
+ public void onSwitchChanged(Switch switchView, boolean isChecked) {
+ IntentPickerUtils.logd("onSwitchChanged: isChecked=" + isChecked);
+ if (mMainSwitchPreference != null) { //mMainSwitchPreference synced with Switch
+ mMainSwitchPreference.setChecked(isChecked);
+ }
+ if (mMainPreferenceCategory != null) {
+ mMainPreferenceCategory.setVisible(isChecked);
+ }
+ if (mDomainVerificationManager != null) {
+ try {
+ mDomainVerificationManager.setDomainVerificationLinkHandlingAllowed(mPackageName,
+ isChecked);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "onSwitchChanged: " + e.getMessage());
+ }
+ }
+ }
+
+ private void createHeaderPreference() {
+ if (mActivityCreated) {
+ Log.w(TAG, "onParentActivityCreated: ignoring duplicate call.");
+ return;
+ }
+ mActivityCreated = true;
+ if (mPackageInfo == null) {
+ Log.w(TAG, "onParentActivityCreated: PakcageInfo is null.");
+ return;
+ }
+ final Activity activity = getActivity();
+ final Preference pref = EntityHeaderController
+ .newInstance(activity, this, null /* header */)
+ .setRecyclerView(getListView(), getSettingsLifecycle())
+ .setIcon(Utils.getBadgedIcon(mContext, mPackageInfo.applicationInfo))
+ .setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))
+ .setSummary("" /* summary */) // no version number
+ .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
+ .setPackageName(mPackageName)
+ .setUid(mPackageInfo.applicationInfo.uid)
+ .setHasAppInfoLink(true)
+ .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
+ EntityHeaderController.ActionType.ACTION_NONE)
+ .done(activity, getPrefContext());
+ getPreferenceScreen().addPreference(pref);
+ }
+
+ private void initUIComponents() {
+ initMainSwitchAndCategories();
+ if (canUpdateMainSwitchAndCategories()) {
+ initVerifiedLinksPreference();
+ addSelectedLinksPreference();
+ initAddLinkPreference();
+ initFooter();
+ }
+ }
+
+ private void initMainSwitchAndCategories() {
+ mMainSwitchPreference = (MainSwitchPreference) findPreference(MAIN_SWITCH_PREF_KEY);
+ mMainPreferenceCategory = findPreference(MAIN_PREF_CATEGORY_KEY);
+ mSelectedLinksPreferenceCategory = findPreference(SELECTED_LINKS_CATEGORY_KEY);
+ // Initialize the "Other Default Category" section
+ initOtherDefaultsSection();
+ }
+
+ private boolean canUpdateMainSwitchAndCategories() {
+ final DomainVerificationUserState userState =
+ IntentPickerUtils.getDomainVerificationUserState(mDomainVerificationManager,
+ mPackageName);
+ if (userState == null) {
+ disabledPreference();
+ return false;
+ }
+
+ IntentPickerUtils.logd("isLinkHandlingAllowed() : " + userState.isLinkHandlingAllowed());
+ mMainSwitchPreference.updateStatus(userState.isLinkHandlingAllowed());
+ mMainSwitchPreference.addOnSwitchChangeListener(this);
+ mMainPreferenceCategory.setVisible(userState.isLinkHandlingAllowed());
+ return true;
+ }
+
+ /** Initialize verified links preference */
+ private void initVerifiedLinksPreference() {
+ final VerifiedLinksPreference verifiedLinksPreference =
+ (VerifiedLinksPreference) mMainPreferenceCategory.findPreference(
+ VERIFIED_LINKS_PREF_KEY);
+ verifiedLinksPreference.setWidgetFrameClickListener(l -> {
+ showVerifiedLinksDialog();
+ });
+ final int verifiedLinksNo = getLinksNumber(DOMAIN_STATE_VERIFIED);
+ verifiedLinksPreference.setTitle(getVerifiedLinksTitle(verifiedLinksNo));
+ verifiedLinksPreference.setCheckBoxVisible(verifiedLinksNo > 0);
+ verifiedLinksPreference.setEnabled(verifiedLinksNo > 0);
+ }
+
+ private void showVerifiedLinksDialog() {
+ final int linksNo = getLinksNumber(DOMAIN_STATE_VERIFIED);
+ if (linksNo == 0) {
+ return;
+ }
+ showDialogInner(DLG_VERIFIED_LINKS, /* moveErrorCode= */ 0);
+ }
+
+ private AlertDialog createVerifiedLinksDialog() {
+ final int linksNo = getLinksNumber(DOMAIN_STATE_VERIFIED);
+
+ final View titleView = LayoutInflater.from(mContext).inflate(
+ R.layout.app_launch_verified_links_title, /* root= */ null);
+ ((TextView) titleView.findViewById(R.id.dialog_title)).setText(
+ getVerifiedLinksTitle(linksNo));
+ ((TextView) titleView.findViewById(R.id.dialog_message)).setText(
+ getVerifiedLinksMessage(linksNo));
+
+ final List<String> verifiedLinksList = IntentPickerUtils.getLinksList(
+ mDomainVerificationManager, mPackageName, DOMAIN_STATE_VERIFIED);
+ return new AlertDialog.Builder(mContext)
+ .setCustomTitle(titleView)
+ .setCancelable(true)
+ .setItems(verifiedLinksList.toArray(new String[0]), /* listener= */ null)
+ .setPositiveButton(R.string.app_launch_dialog_ok, /* listener= */ null)
+ .create();
+ }
+
+ @VisibleForTesting
+ String getVerifiedLinksTitle(int linksNo) {
+ return getResources().getQuantityString(
+ R.plurals.app_launch_verified_links_title, linksNo, linksNo);
+ }
+
+ private String getVerifiedLinksMessage(int linksNo) {
+ return getResources().getQuantityString(
+ R.plurals.app_launch_verified_links_message, linksNo, linksNo);
+ }
+
+ /** Add selected links items */
+ public void addSelectedLinksPreference() {
+ if (getLinksNumber(DOMAIN_STATE_SELECTED) == 0) {
+ return;
+ }
+ mSelectedLinksPreferenceCategory.removeAll();
+ final List<String> selectedLinks = IntentPickerUtils.getLinksList(
+ mDomainVerificationManager, mPackageName, DOMAIN_STATE_SELECTED);
+ for (String host : selectedLinks) {
+ generateCheckBoxPreference(mSelectedLinksPreferenceCategory, host);
+ }
+ }
+
+ /** Initialize add link preference */
+ private void initAddLinkPreference() {
+ final Preference addLinkPreference = findPreference(ADD_LINK_PREF_KEY);
+ if (addLinkPreference != null) {
+ addLinkPreference.setEnabled(getLinksNumber(DOMAIN_STATE_NONE) > 0);
+ addLinkPreference.setOnPreferenceClickListener(preference -> {
+ final int stateNoneLinksNo = getLinksNumber(DOMAIN_STATE_NONE);
+ IntentPickerUtils.logd("The number of the state none links: " + stateNoneLinksNo);
+ if (stateNoneLinksNo > 0) {
+ showProgressDialogFragment();
+ }
+ return true;
+ });
+ }
+ }
+
+ private void showProgressDialogFragment() {
+ final Bundle args = new Bundle();
+ args.putString(APP_PACKAGE_KEY, mPackageName);
+ final ProgressDialogFragment dialogFragment = new ProgressDialogFragment();
+ dialogFragment.setArguments(args);
+ dialogFragment.showDialog(getActivity().getSupportFragmentManager());
+ }
+
+ private void disabledPreference() {
+ mMainSwitchPreference.updateStatus(false);
+ mMainSwitchPreference.setSelectable(false);
+ mMainSwitchPreference.setEnabled(false);
+ mMainPreferenceCategory.setVisible(false);
+ }
+
+ /** Init OTHER DEFAULTS category */
+ private void initOtherDefaultsSection() {
+ mOtherDefaultsPreferenceCategory = findPreference(OTHER_DETAILS_PREF_CATEGORY_KEY);
+ mOtherDefaultsPreferenceCategory.setVisible(isClearDefaultsEnabled());
+ mClearDefaultsPreference = (ClearDefaultsPreference) findPreference(
+ CLEAR_DEFAULTS_PREF_KEY);
+ }
+
+ private void initFooter() {
+ // learn more
+ final AnnotationSpan.LinkInfo linkInfo =
+ new AnnotationSpan.LinkInfo(ANNOTATION_URL, v -> {
+ final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(LEARN_MORE_URI));
+ mContext.startActivity(intent);
+ });
+ final CharSequence footerText = mContext.getText(R.string.app_launch_footer);
+ final FooterPreference footerPreference = (FooterPreference) findPreference(
+ FOOTER_PREF_KEY);
+ footerPreference.setTitle(AnnotationSpan.linkify(footerText, linkInfo));
+ }
+
+ private boolean isClearDefaultsEnabled() {
+ final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+ final boolean hasBindAppWidgetPermission =
+ appWidgetManager.hasBindAppWidgetPermission(mAppEntry.info.packageName);
+
+ final boolean isAutoLaunchEnabled = AppUtils.hasPreferredActivities(mPm, mPackageName)
+ || AppUtils.isDefaultBrowser(mContext, mPackageName)
+ || AppUtils.hasUsbDefaults(mUsbManager, mPackageName);
+
+ IntentPickerUtils.logd("isClearDefaultsEnabled hasBindAppWidgetPermission : "
+ + hasBindAppWidgetPermission);
+ IntentPickerUtils.logd(
+ "isClearDefaultsEnabled isAutoLaunchEnabled : " + isAutoLaunchEnabled);
+ return (isAutoLaunchEnabled || hasBindAppWidgetPermission);
+ }
+
+ private void setDomainVerificationUserSelection(UUID identifier, Set<String> domainSet,
+ boolean isEnabled) {
+ try {
+ mDomainVerificationManager.setDomainVerificationUserSelection(identifier, domainSet,
+ isEnabled);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "addSelectedItems : " + e.getMessage());
+ }
+ }
+
+ private void generateCheckBoxPreference(PreferenceCategory parent, String title) {
+ final LeftSideCheckBoxPreference checkBoxPreference = new LeftSideCheckBoxPreference(
+ parent.getContext(), /* isChecked= */ true);
+ checkBoxPreference.setTitle(title);
+ checkBoxPreference.setOnPreferenceChangeListener(this);
+ checkBoxPreference.setKey(UUID.randomUUID().toString());
+ parent.addPreference(checkBoxPreference);
+ }
+
+ /** get the number of the specify links */
+ private int getLinksNumber(@DomainVerificationUserState.DomainState int state) {
+ final List<String> linkList = IntentPickerUtils.getLinksList(
+ mDomainVerificationManager, mPackageName, state);
+ if (linkList == null) {
+ return 0;
+ }
+ return linkList.size();
+ }
+}
diff --git a/src/com/android/settings/applications/intentpicker/IntentPickerUtils.java b/src/com/android/settings/applications/intentpicker/IntentPickerUtils.java
new file mode 100644
index 0000000..5b14bc7
--- /dev/null
+++ b/src/com/android/settings/applications/intentpicker/IntentPickerUtils.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.applications.intentpicker;
+
+import android.content.pm.PackageManager;
+import android.content.pm.verify.domain.DomainVerificationManager;
+import android.content.pm.verify.domain.DomainVerificationUserState;
+import android.os.Build;
+import android.text.Layout;
+import android.text.SpannableString;
+import android.text.style.AlignmentSpan;
+import android.util.Log;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/** The common APIs for intent picker */
+public class IntentPickerUtils {
+ private static final String TAG = "IntentPickerUtils";
+ private static final boolean DEBUG = Build.IS_DEBUGGABLE;
+
+ private IntentPickerUtils() {
+ }
+
+ /**
+ * Gets the centralized title.
+ *
+ * @param title The title of the dialog box.
+ * @return The spannable string with centralized title.
+ */
+ public static SpannableString getCentralizedDialogTitle(String title) {
+ final SpannableString dialogTitle = new SpannableString(title);
+ dialogTitle.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER), /* start= */
+ 0, title.length(), /* flags= */ 0);
+ return dialogTitle;
+ }
+
+ /**
+ * Gets the {@link DomainVerificationUserState} for specific application.
+ *
+ * @param manager The {@link DomainVerificationManager}.
+ * @param pkgName The package name of the target application.
+ */
+ public static DomainVerificationUserState getDomainVerificationUserState(
+ DomainVerificationManager manager, String pkgName) {
+ try {
+ final DomainVerificationUserState domainVerificationUserState =
+ manager.getDomainVerificationUserState(pkgName);
+ return domainVerificationUserState;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * Gets the links list by {@link DomainVerificationUserState.DomainState}
+ *
+ * @param manager The {@link DomainVerificationManager}.
+ * @param pkgName The package name of the target application.
+ * @param state The user state you want to query.
+ * @return A links list.
+ */
+ public static List<String> getLinksList(DomainVerificationManager manager, String pkgName,
+ @DomainVerificationUserState.DomainState int state) {
+ final DomainVerificationUserState userStage = getDomainVerificationUserState(manager,
+ pkgName);
+ if (userStage == null) {
+ return null;
+ }
+ return userStage.getHostToStateMap()
+ .entrySet()
+ .stream()
+ .filter(it -> it.getValue() == state)
+ .map(it -> it.getKey())
+ .collect(Collectors.toList());
+ }
+
+ /** Logs the message in debug ROM. */
+ public static void logd(String msg) {
+ if (DEBUG) {
+ Log.d(TAG, msg);
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/intentpicker/LeftSideCheckBoxPreference.java b/src/com/android/settings/applications/intentpicker/LeftSideCheckBoxPreference.java
new file mode 100644
index 0000000..fdb6d25
--- /dev/null
+++ b/src/com/android/settings/applications/intentpicker/LeftSideCheckBoxPreference.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.intentpicker;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.CheckBox;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+import com.android.settingslib.widget.TwoTargetPreference;
+
+/** This preference has a check box in the left side. */
+public class LeftSideCheckBoxPreference extends TwoTargetPreference {
+ private boolean mChecked;
+ private CheckBox mCheckBox;
+
+ public LeftSideCheckBoxPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ setLayoutResource(R.layout.preference_checkable_two_target);
+ }
+
+ public LeftSideCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public LeftSideCheckBoxPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public LeftSideCheckBoxPreference(Context context) {
+ this(context, /* attrs= */ null);
+ }
+
+ public LeftSideCheckBoxPreference(Context context, boolean isChecked) {
+ super(context);
+ mChecked = isChecked;
+ setLayoutResource(R.layout.preference_checkable_two_target);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder view) {
+ super.onBindViewHolder(view);
+ mCheckBox = (CheckBox) view.findViewById(com.android.internal.R.id.checkbox);
+ if (mCheckBox != null) {
+ mCheckBox.setChecked(mChecked);
+ }
+ }
+
+ @Override
+ protected void onClick() {
+ if (mCheckBox != null) {
+ mChecked = !mChecked;
+ mCheckBox.setChecked(mChecked);
+ callChangeListener(mChecked);
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java b/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java
new file mode 100644
index 0000000..53a6b04
--- /dev/null
+++ b/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.intentpicker;
+
+import static android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_NONE;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.pm.verify.domain.DomainOwner;
+import android.content.pm.verify.domain.DomainVerificationManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ProgressBar;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.lifecycle.ViewModelProviders;
+
+import com.android.settings.R;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/** A customized {@link DialogFragment} with a progress bar. */
+public class ProgressDialogFragment extends DialogFragment {
+ private static final String TAG = "ProgressDialogFragment";
+ private static final String DLG_ID = "ProgressDialog";
+ private static final int PROGRESS_BAR_STEPPING_TIME = 20;
+
+ private ProgressAlertDialog mProgressAlertDialog;
+ private DomainVerificationManager mDomainVerificationManager;
+ private List<SupportedLinkWrapper> mSupportedLinkWrapperList;
+ private SupportedLinkViewModel mViewModel;
+ private Handler mHandle;
+ private String mPackage;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mViewModel = ViewModelProviders.of(this.getActivity()).get(SupportedLinkViewModel.class);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ mPackage = getArguments().getString(AppLaunchSettings.APP_PACKAGE_KEY);
+ mDomainVerificationManager = getActivity().getSystemService(
+ DomainVerificationManager.class);
+ mHandle = new Handler(Looper.getMainLooper());
+ mProgressAlertDialog = createProgressAlertDialog();
+ return mProgressAlertDialog;
+ }
+
+ private ProgressAlertDialog createProgressAlertDialog() {
+ final Context context = getActivity();
+ final ProgressAlertDialog progressDialog = new ProgressAlertDialog(context);
+ final String title = context.getResources().getString(
+ R.string.app_launch_checking_links_title);
+ progressDialog.setTitle(IntentPickerUtils.getCentralizedDialogTitle(title));
+ progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
+ context.getText(R.string.app_launch_dialog_cancel),
+ (dialog, which) -> {
+ if (which == DialogInterface.BUTTON_NEGATIVE) {
+ dialog.cancel();
+ }
+ });
+ progressDialog.setCanceledOnTouchOutside(true);
+ return progressDialog;
+ }
+
+ /** Display the {@link ProgressAlertDialog}. */
+ public void showDialog(FragmentManager manager) {
+ show(manager, DLG_ID);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ generateProgressAlertDialog();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mProgressAlertDialog != null && mProgressAlertDialog.isShowing()) {
+ mProgressAlertDialog.cancel();
+ }
+ }
+
+ /**
+ * To generate a progress alter dialog and invoke the supported links dialog.
+ */
+ private void generateProgressAlertDialog() {
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final long start = SystemClock.elapsedRealtime();
+ queryLinksInBackground();
+ IntentPickerUtils.logd(
+ "queryLinksInBackground take time: " + (SystemClock.elapsedRealtime() - start));
+ if (mProgressAlertDialog.isShowing()) {
+ mHandle.post(() -> {
+ synchronized (mHandle) {
+ if (mProgressAlertDialog.isShowing()) {
+ mProgressAlertDialog.dismiss();
+ IntentPickerUtils.logd("mProgressAlertDialog.dismiss() and isShowing: "
+ + mProgressAlertDialog.isShowing());
+ launchSupportedLinksDialogFragment();
+ }
+ }
+ });
+ }
+ });
+ }
+
+ private void queryLinksInBackground() {
+ final List<String> links = IntentPickerUtils.getLinksList(mDomainVerificationManager,
+ mPackage, DOMAIN_STATE_NONE);
+ final int linksNo = links.size();
+ int index = 0;
+ mSupportedLinkWrapperList = new ArrayList<>();
+ for (String host : links) {
+ final List<DomainOwner> ownerList =
+ mDomainVerificationManager.getOwnersForDomain(host);
+ mSupportedLinkWrapperList.add(new SupportedLinkWrapper(getActivity(), host, ownerList));
+ index++;
+ // The cancel was clicked while progressing to collect data.
+ if (!mProgressAlertDialog.isShowing()) {
+ Log.w(TAG, "Exit the background thread!!!");
+ // clear buffer
+ mSupportedLinkWrapperList.clear();
+ break;
+ }
+ int progress = (int) (index * 100) / linksNo;
+ mHandle.post(() -> {
+ synchronized (mHandle) {
+ if (!mProgressAlertDialog.isShowing()) {
+ Log.w(TAG, "Exit the UI thread");
+ return;
+ }
+ mProgressAlertDialog.getProgressBar().setProgress(progress);
+ }
+ });
+ if (ownerList.size() == 0) {
+ SystemClock.sleep(PROGRESS_BAR_STEPPING_TIME);
+ }
+ }
+ IntentPickerUtils.logd("queryLinksInBackground : SupportedLinkWrapperList size="
+ + mSupportedLinkWrapperList.size());
+ Collections.sort(mSupportedLinkWrapperList);
+ }
+
+ private void launchSupportedLinksDialogFragment() {
+ if (mSupportedLinkWrapperList.size() > 0) {
+ mViewModel.setSupportedLinkWrapperList(mSupportedLinkWrapperList);
+ final Bundle args = new Bundle();
+ args.putString(AppLaunchSettings.APP_PACKAGE_KEY, mPackage);
+ final SupportedLinksDialogFragment dialogFragment = new SupportedLinksDialogFragment();
+ dialogFragment.setArguments(args);
+ dialogFragment.showDialog(getActivity().getSupportFragmentManager());
+ }
+ }
+
+ /** Create a custom {@link AlertDialog} with a {@link ProgressBar}. */
+ static class ProgressAlertDialog extends AlertDialog {
+ private ProgressBar mProgressBar;
+
+ protected ProgressAlertDialog(@NonNull Context context) {
+ this(context, 0);
+ }
+
+ protected ProgressAlertDialog(@NonNull Context context, int themeResId) {
+ super(context, themeResId);
+ init(context);
+ }
+
+ private void init(Context context) {
+ final View view = LayoutInflater.from(context).inflate(
+ R.layout.app_launch_progress, /* root= */ null);
+ mProgressBar = view.findViewById(R.id.scan_links_progressbar);
+ mProgressBar.setProgress(0);
+ mProgressBar.setMax(100);
+ setView(view);
+ }
+
+ ProgressBar getProgressBar() {
+ return mProgressBar;
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/intentpicker/SupportedLinkViewModel.java b/src/com/android/settings/applications/intentpicker/SupportedLinkViewModel.java
new file mode 100644
index 0000000..c374b8c
--- /dev/null
+++ b/src/com/android/settings/applications/intentpicker/SupportedLinkViewModel.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.applications.intentpicker;
+
+import android.app.Application;
+
+import androidx.lifecycle.AndroidViewModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This {@link AndroidViewModel} provides supported link wrapper data
+ * between multiple fragments.
+ */
+public class SupportedLinkViewModel extends AndroidViewModel {
+ private List<SupportedLinkWrapper> mSupportedLinkWrapperList;
+
+ public SupportedLinkViewModel(Application application) {
+ super(application);
+ }
+
+ /** Clear the list buffer of the {@link SupportedLinkWrapper}. */
+ public void clearSupportedLinkWrapperList() {
+ mSupportedLinkWrapperList = new ArrayList<>();
+ }
+
+ /** Set the list buffer of the {@link SupportedLinkWrapper}. */
+ public void setSupportedLinkWrapperList(List<SupportedLinkWrapper> wrapperList) {
+ mSupportedLinkWrapperList = wrapperList;
+ }
+
+ /** Get the list buffer of the {@link SupportedLinkWrapper}. */
+ public List<SupportedLinkWrapper> getSupportedLinkWrapperList() {
+ return mSupportedLinkWrapperList;
+ }
+}
diff --git a/src/com/android/settings/applications/intentpicker/SupportedLinkWrapper.java b/src/com/android/settings/applications/intentpicker/SupportedLinkWrapper.java
new file mode 100644
index 0000000..0acc2bc
--- /dev/null
+++ b/src/com/android/settings/applications/intentpicker/SupportedLinkWrapper.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.applications.intentpicker;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.verify.domain.DomainOwner;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.R;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * A buffer of the supported link data. This {@link SupportedLinkWrapper} wraps the host, enabled
+ * and a list of {@link DomainOwner}.
+ */
+public class SupportedLinkWrapper implements Comparable {
+ private static final String TAG = "SupportedLinkWrapper";
+
+ private String mHost;
+ private List<DomainOwner> mOwnerList;
+ private boolean mIsEnabled;
+ private String mLastOwnerName;
+ private boolean mIsChecked;
+
+ public SupportedLinkWrapper(Context context, String host, List<DomainOwner> ownerList) {
+ mHost = host;
+ mOwnerList = ownerList;
+ mIsEnabled = true;
+ mLastOwnerName = "";
+ mIsChecked = false;
+ init(context);
+ }
+
+ private void init(Context context) {
+ if (mOwnerList.size() > 0) {
+ final long nonOverirideableNo = mOwnerList.stream()
+ .filter(it -> !it.isOverrideable())
+ .count();
+ mIsEnabled = (nonOverirideableNo == 0L);
+ if (nonOverirideableNo > 0L) {
+ mLastOwnerName = getLastPackageLabel(context, false);
+ } else {
+ mLastOwnerName = getLastPackageLabel(context, true);
+ }
+ }
+ }
+
+ private String getLastPackageLabel(Context context, boolean isOverrideable) {
+ final List<String> labelList = mOwnerList.stream()
+ .filter(it -> it.isOverrideable() == isOverrideable)
+ .map(it -> getLabel(context, it.getPackageName()))
+ .filter(label -> label != null)
+ .collect(Collectors.toList());
+ return labelList.get(labelList.size() - 1);
+ }
+
+ private String getLabel(Context context, String pkg) {
+ try {
+ final PackageManager pm = context.getPackageManager();
+ return pm.getApplicationInfo(pkg, /* flags= */ 0).loadLabel(pm).toString();
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "getLabel error : " + e.getMessage());
+ return null;
+ }
+ }
+
+ /** Returns the enabled/disabled value for list item. */
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ /** Returns the display format of list item in the Supported Links dialog */
+ public String getDisplayTitle(Context context) {
+ if (TextUtils.isEmpty(mLastOwnerName) || context == null) {
+ return mHost;
+ }
+ return mHost + System.lineSeparator() + context.getString(
+ R.string.app_launch_supported_links_subtext, mLastOwnerName);
+ }
+
+ /** Returns the host name. */
+ public String getHost() {
+ return mHost;
+ }
+
+ /** Returns the checked value for list item. */
+ public boolean isChecked() {
+ return mIsChecked;
+ }
+
+ /** Set the checked value. */
+ public void setChecked(boolean isChecked) {
+ mIsChecked = isChecked;
+ }
+
+ @Override
+ public int compareTo(Object o) {
+ final SupportedLinkWrapper that = (SupportedLinkWrapper) o;
+ if (this.mIsEnabled != that.mIsEnabled) {
+ return this.mIsEnabled ? -1 : 1;
+ }
+ if (TextUtils.isEmpty(this.mLastOwnerName) != TextUtils.isEmpty(that.mLastOwnerName)) {
+ return TextUtils.isEmpty(this.mLastOwnerName) ? -1 : 1;
+ }
+ return 0;
+ }
+}
diff --git a/src/com/android/settings/applications/intentpicker/SupportedLinksAdapter.java b/src/com/android/settings/applications/intentpicker/SupportedLinksAdapter.java
new file mode 100644
index 0000000..9288d52
--- /dev/null
+++ b/src/com/android/settings/applications/intentpicker/SupportedLinksAdapter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.intentpicker;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.CheckedTextView;
+
+import com.android.settings.R;
+
+import java.util.List;
+
+/** This adapter is for supported links dialog. */
+public class SupportedLinksAdapter extends BaseAdapter {
+ private final Context mContext;
+ private final List<SupportedLinkWrapper> mWrapperList;
+
+ public SupportedLinksAdapter(Context context, List<SupportedLinkWrapper> list) {
+ mContext = context;
+ mWrapperList = list;
+ }
+
+ @Override
+ public int getCount() {
+ return mWrapperList.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ if (position < mWrapperList.size()) {
+ return mWrapperList.get(position);
+ }
+ return null;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = LayoutInflater.from(mContext).inflate(
+ R.layout.supported_links_dialog_item, /* root= */ null);
+ }
+ final CheckedTextView textView = convertView.findViewById(android.R.id.text1);
+ textView.setText(mWrapperList.get(position).getDisplayTitle(mContext));
+ textView.setEnabled(mWrapperList.get(position).isEnabled());
+ textView.setChecked(mWrapperList.get(position).isChecked());
+ textView.setOnClickListener(l -> {
+ textView.toggle();
+ mWrapperList.get(position).setChecked(textView.isChecked());
+ });
+ return convertView;
+ }
+}
diff --git a/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java b/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java
new file mode 100644
index 0000000..52511c9
--- /dev/null
+++ b/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.intentpicker;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.verify.domain.DomainVerificationManager;
+import android.content.pm.verify.domain.DomainVerificationUserState;
+import android.os.Bundle;
+import android.util.ArraySet;
+import android.util.Log;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.lifecycle.ViewModelProviders;
+
+import com.android.settings.R;
+
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+/** A customized {@link DialogFragment} with multiple checkboxes. */
+public class SupportedLinksDialogFragment extends DialogFragment {
+ private static final String TAG = "SupportedLinksDialogFrg";
+ private static final String DLG_ID = "SupportedLinksDialog";
+
+ private SupportedLinkViewModel mViewModel;
+ private List<SupportedLinkWrapper> mSupportedLinkWrapperList;
+ private String mPackage;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mPackage = getArguments().getString(AppLaunchSettings.APP_PACKAGE_KEY);
+ mViewModel = ViewModelProviders.of(this.getActivity()).get(SupportedLinkViewModel.class);
+ mSupportedLinkWrapperList = mViewModel.getSupportedLinkWrapperList();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Context context = getActivity();
+ final SupportedLinksAdapter adapter = new SupportedLinksAdapter(context,
+ mSupportedLinkWrapperList);
+ final AlertDialog.Builder builder = new AlertDialog
+ .Builder(context)
+ .setTitle(IntentPickerUtils.getCentralizedDialogTitle(getSupportedLinksTitle()))
+ .setAdapter(adapter, /* listener= */ null)
+ .setCancelable(true)
+ .setPositiveButton(R.string.app_launch_supported_links_add, (dialog, id) -> {
+ // addSelectedItems(((AlertDialog) dialog).getListView());
+ doSelectedAction();
+ })
+ .setNegativeButton(R.string.app_launch_dialog_cancel, /* listener= */ null);
+ return builder.create();
+ }
+
+ /** Display the dialog. */
+ public void showDialog(FragmentManager manager) {
+ show(manager, DLG_ID);
+ }
+
+ private String getSupportedLinksTitle() {
+ final int supportedLinksNo = mSupportedLinkWrapperList.size();
+ return getResources().getQuantityString(
+ R.plurals.app_launch_supported_links_title, supportedLinksNo, supportedLinksNo);
+ }
+
+ private void doSelectedAction() {
+ final DomainVerificationManager manager = getActivity().getSystemService(
+ DomainVerificationManager.class);
+ final DomainVerificationUserState userState =
+ IntentPickerUtils.getDomainVerificationUserState(manager, mPackage);
+ if (userState == null || mSupportedLinkWrapperList == null) {
+ return;
+ }
+
+ updateUserSelection(manager, userState);
+ displaySelectedItem();
+ }
+
+ private void updateUserSelection(DomainVerificationManager manager,
+ DomainVerificationUserState userState) {
+ final Set<String> domainSet = new ArraySet<>();
+ for (SupportedLinkWrapper wrapper : mSupportedLinkWrapperList) {
+ if (wrapper.isChecked()) {
+ domainSet.add(wrapper.getHost());
+ }
+ }
+ if (domainSet.size() > 0) {
+ setDomainVerificationUserSelection(manager, userState.getIdentifier(),
+ domainSet, /* enabled= */true);
+ }
+ }
+
+ private void setDomainVerificationUserSelection(DomainVerificationManager manager,
+ UUID identifier, Set<String> domainSet, boolean isEnabled) {
+ try {
+ manager.setDomainVerificationUserSelection(identifier, domainSet, isEnabled);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "addSelectedItems : " + e.getMessage());
+ }
+ }
+
+ private void displaySelectedItem() {
+ final List<Fragment> fragments = getActivity().getSupportFragmentManager().getFragments();
+ for (Fragment fragment : fragments) {
+ if (fragment instanceof AppLaunchSettings) {
+ ((AppLaunchSettings) fragment).addSelectedLinksPreference();
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/intentpicker/VerifiedLinksPreference.java b/src/com/android/settings/applications/intentpicker/VerifiedLinksPreference.java
new file mode 100644
index 0000000..5452a2a
--- /dev/null
+++ b/src/com/android/settings/applications/intentpicker/VerifiedLinksPreference.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.intentpicker;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.CheckBox;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+import com.android.settingslib.widget.TwoTargetPreference;
+
+/** This customized VerifiedLinksPreference was belonged to Open by default page */
+public class VerifiedLinksPreference extends TwoTargetPreference {
+ private Context mContext;
+ private View.OnClickListener mOnWidgetClickListener;
+ private boolean mShowCheckBox;
+
+ public VerifiedLinksPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(context);
+ }
+
+ public VerifiedLinksPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, /* defStyleRes= */0);
+ }
+
+ public VerifiedLinksPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, /* defStyleAttr= */ 0);
+ }
+
+ public VerifiedLinksPreference(Context context) {
+ this(context, /* attrs= */ null);
+ }
+
+ private void init(Context context) {
+ mContext = context;
+ mOnWidgetClickListener = null;
+ mShowCheckBox = true;
+ setLayoutResource(R.layout.preference_checkable_two_target);
+ setWidgetLayoutResource(R.layout.verified_links_widget);
+ }
+
+ /**
+ * Register a callback to be invoked when this widget is clicked.
+ *
+ * @param listener The callback that will run.
+ */
+ public void setWidgetFrameClickListener(View.OnClickListener listener) {
+ mOnWidgetClickListener = listener;
+ }
+
+ /** Determine the visibility of the {@link CheckBox}. */
+ public void setCheckBoxVisible(boolean isVisible) {
+ mShowCheckBox = isVisible;
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder view) {
+ super.onBindViewHolder(view);
+ final View settingsWidget = view.findViewById(android.R.id.widget_frame);
+ final View divider = view.findViewById(R.id.two_target_divider);
+ divider.setVisibility(View.VISIBLE);
+ settingsWidget.setVisibility(View.VISIBLE);
+ if (mOnWidgetClickListener != null) {
+ settingsWidget.setOnClickListener(mOnWidgetClickListener);
+ }
+ final View checkboxContainer = view.findViewById(R.id.checkbox_container);
+ final View parentView = (View) checkboxContainer.getParent();
+ parentView.setEnabled(false);
+ parentView.setClickable(false);
+ CheckBox checkBox = (CheckBox) view.findViewById(com.android.internal.R.id.checkbox);
+ if (checkBox != null) {
+ checkBox.setChecked(true);
+ checkBox.setVisibility(mShowCheckBox ? View.VISIBLE : View.INVISIBLE);
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index e98555b..a92f539 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -277,7 +277,7 @@
Intent intent = activity.getIntent();
Bundle args = getArguments();
int screenTitle = intent.getIntExtra(
- SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.application_info_label);
+ SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.all_apps);
String className = args != null ? args.getString(EXTRA_CLASSNAME) : null;
if (className == null) {
className = intent.getComponent().getClassName();
@@ -342,7 +342,7 @@
screenTitle = R.string.app_notifications_title;
} else {
if (screenTitle == -1) {
- screenTitle = R.string.application_info_label;
+ screenTitle = R.string.all_apps;
}
mListType = LIST_TYPE_MAIN;
}
diff --git a/src/com/android/settings/applications/managedomainurls/DomainAppPreferenceController.java b/src/com/android/settings/applications/managedomainurls/DomainAppPreferenceController.java
index c859db2..07c4858 100644
--- a/src/com/android/settings/applications/managedomainurls/DomainAppPreferenceController.java
+++ b/src/com/android/settings/applications/managedomainurls/DomainAppPreferenceController.java
@@ -28,7 +28,7 @@
import com.android.settings.R;
import com.android.settings.applications.AppInfoBase;
-import com.android.settings.applications.AppLaunchSettings;
+import com.android.settings.applications.intentpicker.AppLaunchSettings;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
diff --git a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
index 096c2c5..bc5aa47 100644
--- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
@@ -192,6 +192,7 @@
updateSubLayout(mLayoutPreference.findViewById(R.id.layout_middle),
BluetoothDevice.METADATA_MAIN_ICON,
BluetoothDevice.METADATA_MAIN_BATTERY,
+ BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD,
BluetoothDevice.METADATA_MAIN_CHARGING,
/* titleResId */ 0,
MAIN_DEVICE_ID);
@@ -202,6 +203,7 @@
updateSubLayout(mLayoutPreference.findViewById(R.id.layout_left),
BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON,
BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY,
+ BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD,
BluetoothDevice.METADATA_UNTETHERED_LEFT_CHARGING,
R.string.bluetooth_left_name,
LEFT_DEVICE_ID);
@@ -209,6 +211,7 @@
updateSubLayout(mLayoutPreference.findViewById(R.id.layout_middle),
BluetoothDevice.METADATA_UNTETHERED_CASE_ICON,
BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY,
+ BluetoothDevice.METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD,
BluetoothDevice.METADATA_UNTETHERED_CASE_CHARGING,
R.string.bluetooth_middle_name,
CASE_DEVICE_ID);
@@ -216,6 +219,7 @@
updateSubLayout(mLayoutPreference.findViewById(R.id.layout_right),
BluetoothDevice.METADATA_UNTETHERED_RIGHT_ICON,
BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY,
+ BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD,
BluetoothDevice.METADATA_UNTETHERED_RIGHT_CHARGING,
R.string.bluetooth_right_name,
RIGHT_DEVICE_ID);
@@ -243,7 +247,7 @@
}
private void updateSubLayout(LinearLayout linearLayout, int iconMetaKey, int batteryMetaKey,
- int chargeMetaKey, int titleResId, int deviceId) {
+ int lowBatteryMetaKey, int chargeMetaKey, int titleResId, int deviceId) {
if (linearLayout == null) {
return;
}
@@ -273,7 +277,15 @@
linearLayout.setVisibility(View.VISIBLE);
batterySummaryView.setText(com.android.settings.Utils.formatPercentage(batteryLevel));
batterySummaryView.setVisibility(View.VISIBLE);
- showBatteryIcon(linearLayout, batteryLevel, charging, batteryMetaKey);
+ int lowBatteryLevel = BluetoothUtils.getIntMetaData(bluetoothDevice, lowBatteryMetaKey);
+ if (lowBatteryLevel == BluetoothUtils.META_INT_ERROR) {
+ if (batteryMetaKey == BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY) {
+ lowBatteryLevel = CASE_LOW_BATTERY_LEVEL;
+ } else {
+ lowBatteryLevel = LOW_BATTERY_LEVEL;
+ }
+ }
+ showBatteryIcon(linearLayout, batteryLevel, lowBatteryLevel, charging);
} else {
if (deviceId == MAIN_DEVICE_ID) {
linearLayout.setVisibility(View.VISIBLE);
@@ -354,11 +366,8 @@
});
}
- private void showBatteryIcon(LinearLayout linearLayout, int level, boolean charging,
- int batteryMetaKey) {
- final int lowBatteryLevel =
- batteryMetaKey == BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY
- ? CASE_LOW_BATTERY_LEVEL : LOW_BATTERY_LEVEL;
+ private void showBatteryIcon(LinearLayout linearLayout, int level, int lowBatteryLevel,
+ boolean charging) {
final boolean enableLowBattery = level <= lowBatteryLevel && !charging;
final ImageView imageView = linearLayout.findViewById(R.id.bt_battery_icon);
if (enableLowBattery) {
diff --git a/src/com/android/settings/datetime/DateTimeSettings.java b/src/com/android/settings/datetime/DateTimeSettings.java
index 469a4c7..d74847f 100644
--- a/src/com/android/settings/datetime/DateTimeSettings.java
+++ b/src/com/android/settings/datetime/DateTimeSettings.java
@@ -59,6 +59,7 @@
public void onAttach(Context context) {
super.onAttach(context);
getSettingsLifecycle().addObserver(new TimeChangeListenerMixin(context, this));
+ use(LocationTimeZoneDetectionPreferenceController.class).setFragment(this);
}
@Override
@@ -77,6 +78,7 @@
final AutoTimeFormatPreferenceController autoTimeFormatPreferenceController =
new AutoTimeFormatPreferenceController(
activity, this /* UpdateTimeAndDateCallback */);
+
controllers.add(autoTimeZonePreferenceController);
controllers.add(autoTimePreferenceController);
controllers.add(autoTimeFormatPreferenceController);
diff --git a/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java b/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java
index 0b0fa27..cb39635 100644
--- a/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java
+++ b/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java
@@ -31,6 +31,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
+import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
@@ -46,17 +47,24 @@
extends TogglePreferenceController
implements LifecycleObserver, OnStart, OnStop, TimeManager.TimeZoneDetectorListener {
+ private static final String TAG = "location_time_zone_detection";
+
private final TimeManager mTimeManager;
private final LocationManager mLocationManager;
private TimeZoneCapabilitiesAndConfig mTimeZoneCapabilitiesAndConfig;
+ private InstrumentedPreferenceFragment mFragment;
private Preference mPreference;
- public LocationTimeZoneDetectionPreferenceController(Context context, String key) {
- super(context, key);
+ public LocationTimeZoneDetectionPreferenceController(Context context) {
+ super(context, TAG);
mTimeManager = context.getSystemService(TimeManager.class);
mLocationManager = context.getSystemService(LocationManager.class);
}
+ void setFragment(InstrumentedPreferenceFragment fragment) {
+ mFragment = fragment;
+ }
+
@Override
public boolean isChecked() {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
@@ -67,10 +75,17 @@
@Override
public boolean setChecked(boolean isChecked) {
- TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
- .setGeoDetectionEnabled(isChecked)
- .build();
- return mTimeManager.updateTimeZoneConfiguration(configuration);
+ if (isChecked && !mLocationManager.isLocationEnabled()) {
+ new LocationToggleDisabledDialogFragment(mContext)
+ .show(mFragment.getFragmentManager(), TAG);
+ // Toggle status is not updated.
+ return false;
+ } else {
+ TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
+ .setGeoDetectionEnabled(isChecked)
+ .build();
+ return mTimeManager.updateTimeZoneConfiguration(configuration);
+ }
}
@Override
diff --git a/src/com/android/settings/datetime/LocationToggleDisabledDialogFragment.java b/src/com/android/settings/datetime/LocationToggleDisabledDialogFragment.java
new file mode 100644
index 0000000..61d46c6
--- /dev/null
+++ b/src/com/android/settings/datetime/LocationToggleDisabledDialogFragment.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 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.datetime;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/**
+ * Dialog shown when user tries to enable GeoTZ with Location toggle disabled.
+ */
+public class LocationToggleDisabledDialogFragment extends InstrumentedDialogFragment {
+
+ private final Context mContext;
+
+ public LocationToggleDisabledDialogFragment(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.location_time_zone_detection_location_is_off_dialog_title)
+ .setIcon(R.drawable.ic_warning_24dp)
+ .setMessage(R.string.location_time_zone_detection_location_is_off_dialog_message)
+ .setPositiveButton(
+ R.string.location_time_zone_detection_location_is_off_dialog_ok_button,
+ (dialog, which) -> {
+ Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+ mContext.startActivity(intent);
+ })
+ .setNegativeButton(
+ R.string.location_time_zone_detection_location_is_off_dialog_cancel_button,
+ (dialog, which) -> {})
+ .create();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DIALOG_DATE_TIME_ENABLE_GEOTZ_WITH_DISABLED_LOCATION;
+ }
+}
diff --git a/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java b/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java
index 905c552..be7704f 100644
--- a/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java
+++ b/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java
@@ -54,4 +54,11 @@
mPreference.setDisabledByAdmin(
checkIfUsbDataSignalingIsDisabled(mContext, UserHandle.myUserId()));
}
+
+ @Override
+ protected void onDeveloperOptionsSwitchEnabled() {
+ super.onDeveloperOptionsSwitchEnabled();
+ mPreference.setDisabledByAdmin(
+ checkIfUsbDataSignalingIsDisabled(mContext, UserHandle.myUserId()));
+ }
}
diff --git a/src/com/android/settings/development/UsbAudioRoutingPreferenceController.java b/src/com/android/settings/development/UsbAudioRoutingPreferenceController.java
index 8aa4f3c..e130b2b 100644
--- a/src/com/android/settings/development/UsbAudioRoutingPreferenceController.java
+++ b/src/com/android/settings/development/UsbAudioRoutingPreferenceController.java
@@ -83,4 +83,11 @@
Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, SETTING_VALUE_OFF);
((SwitchPreference) mPreference).setChecked(false);
}
+
+ @Override
+ protected void onDeveloperOptionsSwitchEnabled() {
+ super.onDeveloperOptionsSwitchEnabled();
+ mPreference.setDisabledByAdmin(
+ checkIfUsbDataSignalingIsDisabled(mContext, UserHandle.myUserId()));
+ }
}
diff --git a/src/com/android/settings/deviceinfo/DeviceNamePreferenceController.java b/src/com/android/settings/deviceinfo/DeviceNamePreferenceController.java
index e6d9dfd..536f699 100644
--- a/src/com/android/settings/deviceinfo/DeviceNamePreferenceController.java
+++ b/src/com/android/settings/deviceinfo/DeviceNamePreferenceController.java
@@ -58,7 +58,7 @@
public DeviceNamePreferenceController(Context context, String key) {
super(context, key);
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mWifiManager = context.getSystemService(WifiManager.class);
mWifiDeviceNameTextValidator = new WifiDeviceNameTextValidator();
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
diff --git a/src/com/android/settings/deviceinfo/StorageItemPreference.java b/src/com/android/settings/deviceinfo/StorageItemPreference.java
index 0766a74..65ef6f4 100644
--- a/src/com/android/settings/deviceinfo/StorageItemPreference.java
+++ b/src/com/android/settings/deviceinfo/StorageItemPreference.java
@@ -35,6 +35,7 @@
private ProgressBar mProgressBar;
private static final int PROGRESS_MAX = 100;
private int mProgressPercent = UNINITIALIZED;
+ private long mStorageSize;
public StorageItemPreference(Context context) {
this(context, null);
@@ -47,6 +48,7 @@
}
public void setStorageSize(long size, long total) {
+ mStorageSize = size;
setSummary(
FileSizeFormatter.formatFileSize(
getContext(),
@@ -61,6 +63,10 @@
updateProgressBar();
}
+ public long getStorageSize() {
+ return mStorageSize;
+ }
+
protected void updateProgressBar() {
if (mProgressBar == null || mProgressPercent == UNINITIALIZED)
return;
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java b/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java
index 7d20aa7..9e969a8 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java
@@ -121,7 +121,7 @@
try {
moveId = getPackageManager().movePrimaryStorage(mVolume);
} catch (IllegalArgumentException e) {
- StorageManager sm = (StorageManager) getSystemService(STORAGE_SERVICE);
+ StorageManager sm = getSystemService(StorageManager.class);
if (Objects.equals(mVolume.getFsUuid(), sm.getPrimaryStorageVolume().getUuid())) {
final Intent intent = new Intent(this, StorageWizardReady.class);
diff --git a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
index 4af5d79..fcbd5d3 100644
--- a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
+++ b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
@@ -146,8 +146,8 @@
// TODO: There may be an avatar setting action we can use here.
final int iconId = bundle.getInt("icon_id", 0);
if (iconId == 0) {
- final UserManager userManager = (UserManager) getActivity().getSystemService(
- Context.USER_SERVICE);
+ final UserManager userManager = getActivity().getSystemService(
+ UserManager.class);
final UserInfo info = Utils.getExistingUser(userManager,
android.os.Process.myUserHandle());
controller.setLabel(info.name);
diff --git a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDetailPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDetailPreferenceController.java
index d6cf442..14e86b4 100644
--- a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDetailPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDetailPreferenceController.java
@@ -49,7 +49,7 @@
public FirmwareVersionDetailPreferenceController(Context context, String key) {
super(context, key);
- mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mUserManager = mContext.getSystemService(UserManager.class);
initializeAdminPermissions();
}
diff --git a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
index 967eea6..fbb29a7 100644
--- a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
@@ -49,7 +49,7 @@
public ImeiInfoPreferenceController(Context context, String key) {
super(context, key);
- mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ mTelephonyManager = context.getSystemService(TelephonyManager.class);
mIsMultiSim = mTelephonyManager.getPhoneCount() > 1;
}
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
index 02c1916..c391750 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
@@ -46,9 +46,9 @@
public SimStatusPreferenceController(Context context, Fragment fragment) {
super(context);
- mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- mSubscriptionManager = (SubscriptionManager) context.getSystemService(
- Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ mTelephonyManager = context.getSystemService(TelephonyManager.class);
+ mSubscriptionManager = context.getSystemService(
+ SubscriptionManager.class);
mFragment = fragment;
}
diff --git a/src/com/android/settings/deviceinfo/storage/EmptyTrashFragment.java b/src/com/android/settings/deviceinfo/storage/EmptyTrashFragment.java
new file mode 100644
index 0000000..da7b9ba
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/storage/EmptyTrashFragment.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 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.deviceinfo.storage;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/**
+ * Dialog asks if users want to empty trash files.
+ */
+public class EmptyTrashFragment extends InstrumentedDialogFragment {
+ private static final String TAG_EMPTY_TRASH = "empty_trash";
+
+ /** Shows the empty trash dialog. */
+ public static void show(Fragment parent) {
+ final EmptyTrashFragment dialog = new EmptyTrashFragment();
+ dialog.setTargetFragment(parent, 0 /* requestCode */);
+ dialog.show(parent.getFragmentManager(), TAG_EMPTY_TRASH);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DIALOG_EMPTY_TRASH;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ return builder.setTitle(R.string.storage_trash_dialog_title)
+ .setMessage(R.string.storage_trash_dialog_ask_message)
+ .setPositiveButton(R.string.storage_trash_dialog_confirm, (dialog, which) -> {
+ // TODO(170918505): Implement the logic in worker thread.
+ }).setNegativeButton(android.R.string.cancel, null)
+ .create();
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index e007090..7d77687 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -19,12 +19,13 @@
import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PERSONAL_TAB;
import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.WORK_TAB;
-import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.net.TrafficStats;
+import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -53,6 +54,8 @@
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -67,20 +70,31 @@
private static final String SYSTEM_FRAGMENT_TAG = "SystemInfo";
@VisibleForTesting
- static final String PHOTO_KEY = "pref_photos_videos";
+ static final String IMAGES_KEY = "pref_images";
@VisibleForTesting
- static final String AUDIO_KEY = "pref_music_audio";
+ static final String VIDEOS_KEY = "pref_videos";
@VisibleForTesting
- static final String GAME_KEY = "pref_games";
+ static final String AUDIOS_KEY = "pref_audios";
@VisibleForTesting
- static final String MOVIES_KEY = "pref_movies";
+ static final String APPS_KEY = "pref_apps";
@VisibleForTesting
- static final String OTHER_APPS_KEY = "pref_other_apps";
+ static final String GAMES_KEY = "pref_games";
+ @VisibleForTesting
+ static final String DOCUMENTS_AND_OTHER_KEY = "pref_documents_and_other";
@VisibleForTesting
static final String SYSTEM_KEY = "pref_system";
@VisibleForTesting
- static final String FILES_KEY = "pref_files";
+ static final String TRASH_KEY = "pref_trash";
+ private final Uri mImagesUri;
+ private final Uri mVideosUri;
+ private final Uri mAudiosUri;
+ private final Uri mDocumentsAndOtherUri;
+
+ // This value should align with the design of storage_dashboard_fragment.xml
+ private static final int LAST_STORAGE_CATEGORY_PREFERENCE_ORDER = 200;
+
+ private PackageManager mPackageManager;
private final Fragment mFragment;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final StorageVolumeProvider mSvp;
@@ -89,14 +103,25 @@
private long mUsedBytes;
private long mTotalSize;
+ private List<StorageItemPreference> mStorageItemPreferences;
private PreferenceScreen mScreen;
- private StorageItemPreference mPhotoPreference;
- private StorageItemPreference mAudioPreference;
- private StorageItemPreference mGamePreference;
- private StorageItemPreference mMoviesPreference;
- private StorageItemPreference mAppPreference;
- private StorageItemPreference mFilePreference;
- private StorageItemPreference mSystemPreference;
+ @VisibleForTesting
+ StorageItemPreference mImagesPreference;
+ @VisibleForTesting
+ StorageItemPreference mVideosPreference;
+ @VisibleForTesting
+ StorageItemPreference mAudiosPreference;
+ @VisibleForTesting
+ StorageItemPreference mAppsPreference;
+ @VisibleForTesting
+ StorageItemPreference mGamesPreference;
+ @VisibleForTesting
+ StorageItemPreference mDocumentsAndOtherPreference;
+ @VisibleForTesting
+ StorageItemPreference mSystemPreference;
+ @VisibleForTesting
+ StorageItemPreference mTrashPreference;
+
private boolean mIsWorkProfile;
private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
@@ -104,11 +129,21 @@
public StorageItemPreferenceController(
Context context, Fragment hostFragment, VolumeInfo volume, StorageVolumeProvider svp) {
super(context);
+ mPackageManager = context.getPackageManager();
mFragment = hostFragment;
mVolume = volume;
mSvp = svp;
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mUserId = UserHandle.myUserId();
+
+ mImagesUri = Uri.parse(context.getResources()
+ .getString(R.string.config_images_storage_category_uri));
+ mVideosUri = Uri.parse(context.getResources()
+ .getString(R.string.config_videos_storage_category_uri));
+ mAudiosUri = Uri.parse(context.getResources()
+ .getString(R.string.config_audios_storage_category_uri));
+ mDocumentsAndOtherUri = Uri.parse(context.getResources()
+ .getString(R.string.config_documents_and_other_storage_category_uri));
}
public StorageItemPreferenceController(
@@ -128,57 +163,39 @@
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
- if (preference == null) {
- return false;
- }
-
- Intent intent = null;
if (preference.getKey() == null) {
return false;
}
switch (preference.getKey()) {
- case PHOTO_KEY:
- intent = getPhotosIntent();
- break;
- case AUDIO_KEY:
- intent = getAudioIntent();
- break;
- case GAME_KEY:
- intent = getGamesIntent();
- break;
- case MOVIES_KEY:
- intent = getMoviesIntent();
- break;
- case OTHER_APPS_KEY:
- // Because we are likely constructed with a null volume, this is theoretically
- // possible.
- if (mVolume == null) {
- break;
- }
- intent = getAppsIntent();
- break;
- case FILES_KEY:
- if (mVolume == null) {
- break;
- }
- intent = getFilesIntent();
- FeatureFactory.getFactory(mContext).getMetricsFeatureProvider().action(
- mContext, SettingsEnums.STORAGE_FILES);
- break;
+ case IMAGES_KEY:
+ launchImagesIntent();
+ return true;
+ case VIDEOS_KEY:
+ launchVideosIntent();
+ return true;
+ case AUDIOS_KEY:
+ launchAudiosIntent();
+ return true;
+ case APPS_KEY:
+ launchAppsIntent();
+ return true;
+ case GAMES_KEY:
+ launchGamesIntent();
+ return true;
+ case DOCUMENTS_AND_OTHER_KEY:
+ launchDocumentsAndOtherIntent();
+ return true;
case SYSTEM_KEY:
final SystemInfoFragment dialog = new SystemInfoFragment();
dialog.setTargetFragment(mFragment, 0);
dialog.show(mFragment.getFragmentManager(), SYSTEM_FRAGMENT_TAG);
return true;
+ case TRASH_KEY:
+ launchTrashIntent();
+ return true;
+ default:
+ // Do nothing.
}
-
- if (intent != null) {
- intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
-
- Utils.launchIntent(mFragment, intent);
- return true;
- }
-
return super.handlePreferenceTreeClick(preference);
}
@@ -192,57 +209,97 @@
*/
public void setVolume(VolumeInfo volume) {
mVolume = volume;
- updateCategoryPreferencesVisibility();
- }
- private void updateCategoryPreferencesVisibility() {
- // Stats data is only available on private volumes.
- final boolean isValidVolume = mVolume != null
- && mVolume.getType() == VolumeInfo.TYPE_PRIVATE
- && (mVolume.getState() == VolumeInfo.STATE_MOUNTED
- || mVolume.getState() == VolumeInfo.STATE_MOUNTED_READ_ONLY);
-
- mPhotoPreference.setVisible(isValidVolume);
- mAudioPreference.setVisible(isValidVolume);
- mGamePreference.setVisible(isValidVolume);
- mMoviesPreference.setVisible(isValidVolume);
- mAppPreference.setVisible(isValidVolume);
- mFilePreference.setVisible(isValidVolume);
- mSystemPreference.setVisible(isValidVolume);
-
+ final boolean isValidVolume = isValidVolume();
+ setCategoryPreferencesVisibility(isValidVolume);
if (isValidVolume) {
- setFilesPreferenceVisibility();
+ updateCategoryPreferencesOrder();
}
}
- private void setFilesPreferenceVisibility() {
- if (mScreen != null) {
+ // Stats data is only available on private volumes.
+ private boolean isValidVolume() {
+ return mVolume != null
+ && mVolume.getType() == VolumeInfo.TYPE_PRIVATE
+ && (mVolume.getState() == VolumeInfo.STATE_MOUNTED
+ || mVolume.getState() == VolumeInfo.STATE_MOUNTED_READ_ONLY);
+ }
+
+ private void setCategoryPreferencesVisibility(boolean visible) {
+ if (mScreen == null) {
+ return;
+ }
+
+ mImagesPreference.setVisible(visible);
+ mVideosPreference.setVisible(visible);
+ mAudiosPreference.setVisible(visible);
+ mAppsPreference.setVisible(visible);
+ mGamesPreference.setVisible(visible);
+ mDocumentsAndOtherPreference.setVisible(visible);
+ mSystemPreference.setVisible(visible);
+ // TODO(b/170918505): Shows trash category after trash category feature complete.
+ mTrashPreference.setVisible(false);
+
+ if (visible) {
final VolumeInfo sharedVolume = mSvp.findEmulatedForPrivate(mVolume);
// If we don't have a shared volume for our internal storage (or the shared volume isn't
// mounted as readable for whatever reason), we should hide the File preference.
- final boolean hideFilePreference =
- (sharedVolume == null) || !sharedVolume.isMountedReadable();
- if (hideFilePreference) {
- mScreen.removePreference(mFilePreference);
- } else {
- mScreen.addPreference(mFilePreference);
+ if (sharedVolume == null || !sharedVolume.isMountedReadable()) {
+ mDocumentsAndOtherPreference.setVisible(false);
}
}
}
+ private void updateCategoryPreferencesOrder() {
+ if (mScreen == null) {
+ return;
+ }
+
+ if (mStorageItemPreferences == null) {
+ mStorageItemPreferences = new ArrayList<>();
+
+ mStorageItemPreferences.add(mImagesPreference);
+ mStorageItemPreferences.add(mVideosPreference);
+ mStorageItemPreferences.add(mAudiosPreference);
+ mStorageItemPreferences.add(mAppsPreference);
+ mStorageItemPreferences.add(mGamesPreference);
+ mStorageItemPreferences.add(mDocumentsAndOtherPreference);
+ mStorageItemPreferences.add(mSystemPreference);
+ mStorageItemPreferences.add(mTrashPreference);
+ }
+ mScreen.removePreference(mImagesPreference);
+ mScreen.removePreference(mVideosPreference);
+ mScreen.removePreference(mAudiosPreference);
+ mScreen.removePreference(mAppsPreference);
+ mScreen.removePreference(mGamesPreference);
+ mScreen.removePreference(mDocumentsAndOtherPreference);
+ mScreen.removePreference(mSystemPreference);
+ mScreen.removePreference(mTrashPreference);
+
+ // Sort display order by size.
+ Collections.sort(mStorageItemPreferences,
+ Comparator.comparingLong(StorageItemPreference::getStorageSize));
+ int orderIndex = LAST_STORAGE_CATEGORY_PREFERENCE_ORDER;
+ for (StorageItemPreference preference : mStorageItemPreferences) {
+ preference.setOrder(orderIndex--);
+ mScreen.addPreference(preference);
+ }
+ }
+
/**
* Sets the user id for which this preference controller is handling.
*/
public void setUserId(UserHandle userHandle) {
mUserId = userHandle.getIdentifier();
- tintPreference(mPhotoPreference);
- tintPreference(mMoviesPreference);
- tintPreference(mAudioPreference);
- tintPreference(mGamePreference);
- tintPreference(mAppPreference);
+ tintPreference(mImagesPreference);
+ tintPreference(mVideosPreference);
+ tintPreference(mAudiosPreference);
+ tintPreference(mAppsPreference);
+ tintPreference(mGamesPreference);
+ tintPreference(mDocumentsAndOtherPreference);
tintPreference(mSystemPreference);
- tintPreference(mFilePreference);
+ tintPreference(mTrashPreference);
}
private void tintPreference(Preference preference) {
@@ -263,15 +320,20 @@
@Override
public void displayPreference(PreferenceScreen screen) {
mScreen = screen;
- mPhotoPreference = screen.findPreference(PHOTO_KEY);
- mAudioPreference = screen.findPreference(AUDIO_KEY);
- mGamePreference = screen.findPreference(GAME_KEY);
- mMoviesPreference = screen.findPreference(MOVIES_KEY);
- mAppPreference = screen.findPreference(OTHER_APPS_KEY);
+ mImagesPreference = screen.findPreference(IMAGES_KEY);
+ mVideosPreference = screen.findPreference(VIDEOS_KEY);
+ mAudiosPreference = screen.findPreference(AUDIOS_KEY);
+ mAppsPreference = screen.findPreference(APPS_KEY);
+ mGamesPreference = screen.findPreference(GAMES_KEY);
+ mDocumentsAndOtherPreference = screen.findPreference(DOCUMENTS_AND_OTHER_KEY);
mSystemPreference = screen.findPreference(SYSTEM_KEY);
- mFilePreference = screen.findPreference(FILES_KEY);
+ mTrashPreference = screen.findPreference(TRASH_KEY);
- updateCategoryPreferencesVisibility();
+ final boolean isValidVolume = isValidVolume();
+ setCategoryPreferencesVisibility(isValidVolume);
+ if (isValidVolume) {
+ updateCategoryPreferencesOrder();
+ }
}
public void onLoadFinished(SparseArray<StorageAsyncLoader.AppsStorageResult> result,
@@ -280,12 +342,14 @@
final StorageAsyncLoader.AppsStorageResult profileData = result.get(
Utils.getManagedProfileId(mContext.getSystemService(UserManager.class), userId));
- mPhotoPreference.setStorageSize(getPhotosSize(data, profileData), mTotalSize);
- mAudioPreference.setStorageSize(getAudioSize(data, profileData), mTotalSize);
- mGamePreference.setStorageSize(getGamesSize(data, profileData), mTotalSize);
- mMoviesPreference.setStorageSize(getMoviesSize(data, profileData), mTotalSize);
- mAppPreference.setStorageSize(getAppsSize(data, profileData), mTotalSize);
- mFilePreference.setStorageSize(getFilesSize(data, profileData), mTotalSize);
+ mImagesPreference.setStorageSize(getImagesSize(data, profileData), mTotalSize);
+ mVideosPreference.setStorageSize(getVideosSize(data, profileData), mTotalSize);
+ mAudiosPreference.setStorageSize(getAudiosSize(data, profileData), mTotalSize);
+ mAppsPreference.setStorageSize(getAppsSize(data, profileData), mTotalSize);
+ mGamesPreference.setStorageSize(getGamesSize(data, profileData), mTotalSize);
+ mDocumentsAndOtherPreference.setStorageSize(getDocumentsAndOtherSize(data, profileData),
+ mTotalSize);
+ mTrashPreference.setStorageSize(getTrashSize(data, profileData), mTotalSize);
if (mSystemPreference != null) {
// Everything else that hasn't already been attributed is tracked as
@@ -306,6 +370,8 @@
final long systemSize = Math.max(TrafficStats.GB_IN_BYTES, mUsedBytes - attributedSize);
mSystemPreference.setStorageSize(systemSize, mTotalSize);
}
+
+ updateCategoryPreferencesOrder();
}
public void setUsedSize(long usedSizeBytes) {
@@ -316,37 +382,32 @@
mTotalSize = totalSizeBytes;
}
- /**
- * Returns a list of keys used by this preference controller.
- */
- public static List<String> getUsedKeys() {
- List<String> list = new ArrayList<>();
- list.add(PHOTO_KEY);
- list.add(AUDIO_KEY);
- list.add(GAME_KEY);
- list.add(MOVIES_KEY);
- list.add(OTHER_APPS_KEY);
- list.add(SYSTEM_KEY);
- list.add(FILES_KEY);
- return list;
+ // TODO(b/183078080): To simplify StorageItemPreferenceController, move launchxxxIntent to a
+ // utility object.
+ private void launchImagesIntent() {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(mImagesUri);
+
+ if (intent.resolveActivity(mPackageManager) == null) {
+ final Bundle args = getWorkAnnotatedBundle(2);
+ args.putString(ManageApplications.EXTRA_CLASSNAME,
+ Settings.PhotosStorageActivity.class.getName());
+ args.putInt(ManageApplications.EXTRA_STORAGE_TYPE,
+ ManageApplications.STORAGE_TYPE_PHOTOS_VIDEOS);
+ intent = new SubSettingLauncher(mContext)
+ .setDestination(ManageApplications.class.getName())
+ .setTitleRes(R.string.storage_photos_videos)
+ .setArguments(args)
+ .setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
+ .toIntent();
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ Utils.launchIntent(mFragment, intent);
+ } else {
+ mContext.startActivity(intent);
+ }
}
- private Intent getPhotosIntent() {
- Bundle args = getWorkAnnotatedBundle(2);
- args.putString(
- ManageApplications.EXTRA_CLASSNAME, Settings.PhotosStorageActivity.class.getName());
- args.putInt(
- ManageApplications.EXTRA_STORAGE_TYPE,
- ManageApplications.STORAGE_TYPE_PHOTOS_VIDEOS);
- return new SubSettingLauncher(mContext)
- .setDestination(ManageApplications.class.getName())
- .setTitleRes(R.string.storage_photos_videos)
- .setArguments(args)
- .setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
- .toIntent();
- }
-
- private long getPhotosSize(StorageAsyncLoader.AppsStorageResult data,
+ private long getImagesSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
return data.photosAppsSize + data.externalStats.imageBytes
@@ -359,26 +420,62 @@
}
}
- private Intent getAudioIntent() {
- if (mVolume == null) {
- return null;
- }
+ private void launchVideosIntent() {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(mVideosUri);
- Bundle args = getWorkAnnotatedBundle(4);
- args.putString(ManageApplications.EXTRA_CLASSNAME,
- Settings.StorageUseActivity.class.getName());
- args.putString(ManageApplications.EXTRA_VOLUME_UUID, mVolume.getFsUuid());
- args.putString(ManageApplications.EXTRA_VOLUME_NAME, mVolume.getDescription());
- args.putInt(ManageApplications.EXTRA_STORAGE_TYPE, ManageApplications.STORAGE_TYPE_MUSIC);
- return new SubSettingLauncher(mContext)
- .setDestination(ManageApplications.class.getName())
- .setTitleRes(R.string.storage_music_audio)
- .setArguments(args)
- .setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
- .toIntent();
+ if (intent.resolveActivity(mPackageManager) == null) {
+ final Bundle args = getWorkAnnotatedBundle(1);
+ args.putString(ManageApplications.EXTRA_CLASSNAME,
+ Settings.MoviesStorageActivity.class.getName());
+ intent = new SubSettingLauncher(mContext)
+ .setDestination(ManageApplications.class.getName())
+ .setTitleRes(R.string.storage_movies_tv)
+ .setArguments(args)
+ .setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
+ .toIntent();
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ Utils.launchIntent(mFragment, intent);
+ } else {
+ mContext.startActivity(intent);
+ }
}
- private long getAudioSize(StorageAsyncLoader.AppsStorageResult data,
+ private long getVideosSize(StorageAsyncLoader.AppsStorageResult data,
+ StorageAsyncLoader.AppsStorageResult profileData) {
+ if (profileData != null) {
+ return data.videoAppsSize + profileData.videoAppsSize;
+ } else {
+ return data.videoAppsSize;
+ }
+ }
+
+ private void launchAudiosIntent() {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(mAudiosUri);
+
+ if (intent.resolveActivity(mPackageManager) == null) {
+ final Bundle args = getWorkAnnotatedBundle(4);
+ args.putString(ManageApplications.EXTRA_CLASSNAME,
+ Settings.StorageUseActivity.class.getName());
+ args.putString(ManageApplications.EXTRA_VOLUME_UUID, mVolume.getFsUuid());
+ args.putString(ManageApplications.EXTRA_VOLUME_NAME, mVolume.getDescription());
+ args.putInt(ManageApplications.EXTRA_STORAGE_TYPE,
+ ManageApplications.STORAGE_TYPE_MUSIC);
+ intent = new SubSettingLauncher(mContext)
+ .setDestination(ManageApplications.class.getName())
+ .setTitleRes(R.string.storage_music_audio)
+ .setArguments(args)
+ .setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
+ .toIntent();
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ Utils.launchIntent(mFragment, intent);
+ } else {
+ mContext.startActivity(intent);
+ }
+ }
+
+ private long getAudiosSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
return data.musicAppsSize + data.externalStats.audioBytes
@@ -388,21 +485,20 @@
}
}
- private Intent getAppsIntent() {
- if (mVolume == null) {
- return null;
- }
+ private void launchAppsIntent() {
final Bundle args = getWorkAnnotatedBundle(3);
args.putString(ManageApplications.EXTRA_CLASSNAME,
Settings.StorageUseActivity.class.getName());
args.putString(ManageApplications.EXTRA_VOLUME_UUID, mVolume.getFsUuid());
args.putString(ManageApplications.EXTRA_VOLUME_NAME, mVolume.getDescription());
- return new SubSettingLauncher(mContext)
+ final Intent intent = new SubSettingLauncher(mContext)
.setDestination(ManageApplications.class.getName())
.setTitleRes(R.string.apps_storage)
.setArguments(args)
.setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
.toIntent();
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ Utils.launchIntent(mFragment, intent);
}
private long getAppsSize(StorageAsyncLoader.AppsStorageResult data,
@@ -414,16 +510,18 @@
}
}
- private Intent getGamesIntent() {
+ private void launchGamesIntent() {
final Bundle args = getWorkAnnotatedBundle(1);
args.putString(ManageApplications.EXTRA_CLASSNAME,
Settings.GamesStorageActivity.class.getName());
- return new SubSettingLauncher(mContext)
+ final Intent intent = new SubSettingLauncher(mContext)
.setDestination(ManageApplications.class.getName())
.setTitleRes(R.string.game_storage_settings)
.setArguments(args)
.setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
.toIntent();
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ Utils.launchIntent(mFragment, intent);
}
private long getGamesSize(StorageAsyncLoader.AppsStorageResult data,
@@ -435,27 +533,6 @@
}
}
- private Intent getMoviesIntent() {
- final Bundle args = getWorkAnnotatedBundle(1);
- args.putString(ManageApplications.EXTRA_CLASSNAME,
- Settings.MoviesStorageActivity.class.getName());
- return new SubSettingLauncher(mContext)
- .setDestination(ManageApplications.class.getName())
- .setTitleRes(R.string.storage_movies_tv)
- .setArguments(args)
- .setSourceMetricsCategory(mMetricsFeatureProvider.getMetricsCategory(mFragment))
- .toIntent();
- }
-
- private long getMoviesSize(StorageAsyncLoader.AppsStorageResult data,
- StorageAsyncLoader.AppsStorageResult profileData) {
- if (profileData != null) {
- return data.videoAppsSize + profileData.videoAppsSize;
- } else {
- return data.videoAppsSize;
- }
- }
-
private Bundle getWorkAnnotatedBundle(int additionalCapacity) {
final Bundle args = new Bundle(1 + additionalCapacity);
args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB,
@@ -463,11 +540,20 @@
return args;
}
- private Intent getFilesIntent() {
- return mSvp.findEmulatedForPrivate(mVolume).buildBrowseIntent();
+ private void launchDocumentsAndOtherIntent() {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(mDocumentsAndOtherUri);
+
+ if (intent.resolveActivity(mPackageManager) == null) {
+ intent = mSvp.findEmulatedForPrivate(mVolume).buildBrowseIntent();
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ Utils.launchIntent(mFragment, intent);
+ } else {
+ mContext.startActivity(intent);
+ }
}
- private long getFilesSize(StorageAsyncLoader.AppsStorageResult data,
+ private long getDocumentsAndOtherSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
return data.externalStats.totalBytes
@@ -489,6 +575,22 @@
}
}
+ private void launchTrashIntent() {
+ final Intent intent = new Intent("android.settings.VIEW_TRASH");
+
+ if (intent.resolveActivity(mPackageManager) == null) {
+ EmptyTrashFragment.show(mFragment);
+ } else {
+ mContext.startActivity(intent);
+ }
+ }
+
+ private long getTrashSize(StorageAsyncLoader.AppsStorageResult data,
+ StorageAsyncLoader.AppsStorageResult profileData) {
+ // TODO(170918505): Implement it.
+ return 0L;
+ }
+
private static long totalValues(StorageMeasurement.MeasurementDetails details, int userId,
String... keys) {
long total = 0;
diff --git a/src/com/android/settings/emergency/MoreSettingsPreferenceController.java b/src/com/android/settings/emergency/MoreSettingsPreferenceController.java
new file mode 100644
index 0000000..34c11c7
--- /dev/null
+++ b/src/com/android/settings/emergency/MoreSettingsPreferenceController.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2021 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.emergency;
+
+import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.widget.LayoutPreference;
+
+import java.util.List;
+
+/**
+ * Preference controller for More settings button
+ */
+public class MoreSettingsPreferenceController extends BasePreferenceController implements
+ View.OnClickListener {
+
+ private static final String EXTRA_KEY_ATTRIBUTION = "attribution";
+ private static final String TAG = "MoreSettingsPrefCtrl";
+ @VisibleForTesting
+ Intent mIntent;
+
+ public MoreSettingsPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ final String packageName = mContext.getResources().getString(
+ R.string.config_emergency_package_name);
+
+ if (TextUtils.isEmpty(packageName)) {
+ return;
+ }
+ mIntent = new Intent(Intent.ACTION_MAIN)
+ .setPackage(packageName);
+
+ final List<ResolveInfo> info = mContext.getPackageManager()
+ .queryIntentActivities(mIntent, MATCH_SYSTEM_ONLY);
+
+ if (info != null && !info.isEmpty()) {
+ mIntent.setClassName(packageName, info.get(0).activityInfo.name);
+ } else {
+ mIntent = null;
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ final LayoutPreference pref = screen.findPreference(getPreferenceKey());
+ final Button button = pref.findViewById(R.id.button);
+ button.setText(getButtonText());
+ button.setOnClickListener(this);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mIntent == null) {
+ return UNSUPPORTED_ON_DEVICE;
+ } else {
+ return AVAILABLE;
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ final Intent intent = new Intent(mIntent)
+ .addCategory(Intent.CATEGORY_LAUNCHER)
+ .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ Bundle bundle = new Bundle();
+ bundle.putString(EXTRA_KEY_ATTRIBUTION, mContext.getPackageName());
+ mContext.startActivity(intent, bundle);
+ }
+
+ private CharSequence getButtonText() {
+ final String packageName = mContext.getResources().getString(
+ R.string.config_emergency_package_name);
+ try {
+ final PackageManager pm = mContext.getPackageManager();
+ final ApplicationInfo appInfo = pm.getApplicationInfo(
+ packageName, MATCH_DISABLED_COMPONENTS
+ | MATCH_DISABLED_UNTIL_USED_COMPONENTS);
+ return mContext.getString(R.string.open_app_button, appInfo.loadLabel(pm));
+ } catch (Exception e) {
+ Log.d(TAG, "Failed to get open app button text, falling back.");
+ return "";
+ }
+ }
+}
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceController.java b/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceController.java
index b07eb91..8353d20 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceController.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceController.java
@@ -13,6 +13,9 @@
*/
package com.android.settings.enterprise;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
+
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import androidx.preference.Preference;
@@ -39,6 +42,10 @@
if (preference == null) {
return;
}
+ if (isFinancedDevice()) {
+ preference.setTitle(R.string.financed_privacy_settings);
+ }
+
final String organizationName = mFeatureProvider.getDeviceOwnerOrganizationName();
if (organizationName == null) {
preference.setSummary(R.string.enterprise_privacy_settings_summary_generic);
@@ -57,4 +64,10 @@
public String getPreferenceKey() {
return KEY_ENTERPRISE_PRIVACY;
}
+
+ private boolean isFinancedDevice() {
+ final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+ return dpm.isDeviceManaged() && dpm.getDeviceOwnerType(
+ dpm.getDeviceOwnerComponentOnAnyUser()) == DEVICE_OWNER_TYPE_FINANCED;
+ }
}
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
index dd0a9ce..1aad544 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
@@ -20,16 +20,13 @@
import android.content.Context;
import android.provider.SearchIndexableResource;
-import com.android.settings.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.widget.PreferenceCategoryController;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
@SearchIndexable
@@ -37,6 +34,23 @@
static final String TAG = "EnterprisePrivacySettings";
+ @VisibleForTesting
+ PrivacySettingsPreference mPrivacySettingsPreference;
+
+ @Override
+ public void onAttach(Context context) {
+ mPrivacySettingsPreference =
+ PrivacySettingsPreferenceFactory.createPrivacySettingsPreference(context);
+
+ super.onAttach(context);
+ }
+
+ @Override
+ public void onDetach() {
+ mPrivacySettingsPreference = null;
+ super.onDetach();
+ }
+
@Override
public int getMetricsCategory() {
return SettingsEnums.ENTERPRISE_PRIVACY_SETTINGS;
@@ -49,47 +63,12 @@
@Override
protected int getPreferenceScreenResId() {
- return R.xml.enterprise_privacy_settings;
+ return mPrivacySettingsPreference.getPreferenceScreenResId();
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
- return buildPreferenceControllers(context, true /* async */);
- }
-
- private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
- boolean async) {
- final List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new NetworkLogsPreferenceController(context));
- controllers.add(new BugReportsPreferenceController(context));
- controllers.add(new SecurityLogsPreferenceController(context));
- final List<AbstractPreferenceController> exposureChangesCategoryControllers =
- new ArrayList<>();
- exposureChangesCategoryControllers.add(new EnterpriseInstalledPackagesPreferenceController(
- context, async));
- exposureChangesCategoryControllers.add(
- new AdminGrantedLocationPermissionsPreferenceController(context, async));
- exposureChangesCategoryControllers.add(
- new AdminGrantedMicrophonePermissionPreferenceController(context, async));
- exposureChangesCategoryControllers.add(new AdminGrantedCameraPermissionPreferenceController(
- context, async));
- exposureChangesCategoryControllers.add(new EnterpriseSetDefaultAppsPreferenceController(
- context));
- exposureChangesCategoryControllers.add(new AlwaysOnVpnCurrentUserPreferenceController(
- context));
- exposureChangesCategoryControllers.add(new AlwaysOnVpnManagedProfilePreferenceController(
- context));
- exposureChangesCategoryControllers.add(new ImePreferenceController(context));
- exposureChangesCategoryControllers.add(new GlobalHttpProxyPreferenceController(context));
- exposureChangesCategoryControllers.add(new CaCertsCurrentUserPreferenceController(context));
- exposureChangesCategoryControllers.add(new CaCertsManagedProfilePreferenceController(
- context));
- controllers.addAll(exposureChangesCategoryControllers);
- controllers.add(new PreferenceCategoryController(context, "exposure_changes_category")
- .setChildren(exposureChangesCategoryControllers));
- controllers.add(new FailedPasswordWipeCurrentUserPreferenceController(context));
- controllers.add(new FailedPasswordWipeManagedProfilePreferenceController(context));
- return controllers;
+ return mPrivacySettingsPreference.createPreferenceControllers(true /* async */);
}
public static boolean isPageEnabled(Context context) {
@@ -99,17 +78,32 @@
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider(R.xml.enterprise_privacy_settings) {
+ new BaseSearchIndexProvider() {
+
+ private PrivacySettingsPreference mPrivacySettingsPreference;
+
@Override
protected boolean isPageSearchEnabled(Context context) {
return isPageEnabled(context);
}
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ mPrivacySettingsPreference =
+ PrivacySettingsPreferenceFactory.createPrivacySettingsPreference(
+ context);
+ return mPrivacySettingsPreference.getXmlResourcesToIndex();
+ }
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
- return buildPreferenceControllers(context, false /* async */);
+ mPrivacySettingsPreference =
+ PrivacySettingsPreferenceFactory.createPrivacySettingsPreference(
+ context);
+ return mPrivacySettingsPreference.createPreferenceControllers(
+ false /* async */);
}
};
}
diff --git a/src/com/android/settings/enterprise/PrivacySettingsEnterprisePreference.java b/src/com/android/settings/enterprise/PrivacySettingsEnterprisePreference.java
new file mode 100644
index 0000000..19556a1
--- /dev/null
+++ b/src/com/android/settings/enterprise/PrivacySettingsEnterprisePreference.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2021 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.enterprise;
+
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settings.widget.PreferenceCategoryController;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/** Privacy Settings preferences for an Enterprise device. */
+public class PrivacySettingsEnterprisePreference implements PrivacySettingsPreference {
+ private static final String KEY_EXPOSURE_CHANGES_CATEGORY = "exposure_changes_category";
+
+ private final Context mContext;
+
+ public PrivacySettingsEnterprisePreference(Context context) {
+ mContext = context.getApplicationContext();
+ }
+
+ /**
+ * Returns the XML Res Id that is used for an Enterprise device in the Privacy Settings screen.
+ */
+ @Override
+ public int getPreferenceScreenResId() {
+ return R.xml.enterprise_privacy_settings;
+ }
+
+ /**
+ * Returns the Enterprise XML resources to index for an Enterprise device.
+ */
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex() {
+ final SearchIndexableResource sir = new SearchIndexableResource(mContext);
+ sir.xmlResId = getPreferenceScreenResId();
+ return Collections.singletonList(sir);
+ }
+
+ /**
+ * Returns the preference controllers used to populate the privacy preferences in the Privacy
+ * Settings screen for Enterprise devices.
+ */
+ @Override
+ public List<AbstractPreferenceController> createPreferenceControllers(boolean async) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new NetworkLogsPreferenceController(mContext));
+ controllers.add(new BugReportsPreferenceController(mContext));
+ controllers.add(new SecurityLogsPreferenceController(mContext));
+ final List<AbstractPreferenceController> exposureChangesCategoryControllers =
+ new ArrayList<>();
+ exposureChangesCategoryControllers.add(new EnterpriseInstalledPackagesPreferenceController(
+ mContext, async));
+ exposureChangesCategoryControllers.add(
+ new AdminGrantedLocationPermissionsPreferenceController(mContext, async));
+ exposureChangesCategoryControllers.add(
+ new AdminGrantedMicrophonePermissionPreferenceController(mContext, async));
+ exposureChangesCategoryControllers.add(new AdminGrantedCameraPermissionPreferenceController(
+ mContext, async));
+ exposureChangesCategoryControllers.add(new EnterpriseSetDefaultAppsPreferenceController(
+ mContext));
+ exposureChangesCategoryControllers.add(new AlwaysOnVpnCurrentUserPreferenceController(
+ mContext));
+ exposureChangesCategoryControllers.add(new AlwaysOnVpnManagedProfilePreferenceController(
+ mContext));
+ exposureChangesCategoryControllers.add(new ImePreferenceController(mContext));
+ exposureChangesCategoryControllers.add(new GlobalHttpProxyPreferenceController(mContext));
+ exposureChangesCategoryControllers.add(new CaCertsCurrentUserPreferenceController(
+ mContext));
+ exposureChangesCategoryControllers.add(new CaCertsManagedProfilePreferenceController(
+ mContext));
+ controllers.addAll(exposureChangesCategoryControllers);
+ controllers.add(new PreferenceCategoryController(mContext, KEY_EXPOSURE_CHANGES_CATEGORY)
+ .setChildren(exposureChangesCategoryControllers));
+ controllers.add(new FailedPasswordWipeCurrentUserPreferenceController(mContext));
+ controllers.add(new FailedPasswordWipeManagedProfilePreferenceController(mContext));
+ return controllers;
+ }
+}
diff --git a/src/com/android/settings/enterprise/PrivacySettingsFinancedPreference.java b/src/com/android/settings/enterprise/PrivacySettingsFinancedPreference.java
new file mode 100644
index 0000000..12901a6
--- /dev/null
+++ b/src/com/android/settings/enterprise/PrivacySettingsFinancedPreference.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 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.enterprise;
+
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settings.widget.PreferenceCategoryController;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/** Privacy Settings preferences for a financed device. */
+public class PrivacySettingsFinancedPreference implements PrivacySettingsPreference {
+ private static final String KEY_EXPOSURE_CHANGES_CATEGORY = "exposure_changes_category";
+
+ private final Context mContext;
+
+ public PrivacySettingsFinancedPreference(Context context) {
+ mContext = context.getApplicationContext();
+ }
+
+ /**
+ * Returns the XML Res Id that is used for financed devices in the Privacy Settings screen.
+ */
+ @Override
+ public int getPreferenceScreenResId() {
+ return R.xml.financed_privacy_settings;
+ }
+
+ /**
+ * Returns the XML resources to index for a financed device.
+ */
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex() {
+ final SearchIndexableResource sir = new SearchIndexableResource(mContext);
+ sir.xmlResId = getPreferenceScreenResId();
+ return Collections.singletonList(sir);
+ }
+
+ /**
+ * Returns the preference controllers used to populate the privacy preferences in the Privacy
+ * Settings screen for a financed device.
+ */
+ @Override
+ public List<AbstractPreferenceController> createPreferenceControllers(boolean async) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new NetworkLogsPreferenceController(mContext));
+ controllers.add(new BugReportsPreferenceController(mContext));
+ controllers.add(new SecurityLogsPreferenceController(mContext));
+ final List<AbstractPreferenceController> exposureChangesCategoryControllers =
+ new ArrayList<>();
+ exposureChangesCategoryControllers.add(new EnterpriseInstalledPackagesPreferenceController(
+ mContext, async));
+ controllers.addAll(exposureChangesCategoryControllers);
+ controllers.add(new PreferenceCategoryController(mContext, KEY_EXPOSURE_CHANGES_CATEGORY)
+ .setChildren(exposureChangesCategoryControllers));
+ controllers.add(new FailedPasswordWipeCurrentUserPreferenceController(mContext));
+ return controllers;
+ }
+}
diff --git a/src/com/android/settings/enterprise/PrivacySettingsPreference.java b/src/com/android/settings/enterprise/PrivacySettingsPreference.java
new file mode 100644
index 0000000..4310f5e
--- /dev/null
+++ b/src/com/android/settings/enterprise/PrivacySettingsPreference.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.enterprise;
+
+import android.provider.SearchIndexableResource;
+
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.List;
+
+/** Interface for configuring what is displayed on the Privacy Settings. */
+public interface PrivacySettingsPreference {
+
+ /**
+ * Returns the XML Res Id that is used in the Privacy Settings screen.
+ */
+ int getPreferenceScreenResId();
+
+ /**
+ * Returns the XML resources to index.
+ */
+ List<SearchIndexableResource> getXmlResourcesToIndex();
+
+ /**
+ * Returns the preference controllers used to populate the privacy preferences.
+ */
+ List<AbstractPreferenceController> createPreferenceControllers(boolean async);
+}
diff --git a/src/com/android/settings/enterprise/PrivacySettingsPreferenceFactory.java b/src/com/android/settings/enterprise/PrivacySettingsPreferenceFactory.java
new file mode 100644
index 0000000..0ec2498
--- /dev/null
+++ b/src/com/android/settings/enterprise/PrivacySettingsPreferenceFactory.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 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.enterprise;
+
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+
+/** Factory for creating the privacy settings preference for a managed device. */
+public class PrivacySettingsPreferenceFactory {
+
+ /**
+ * Determines which preference to use in the Privacy Settings based off of the type of managed
+ * device.
+ */
+ public static PrivacySettingsPreference createPrivacySettingsPreference(Context context) {
+ if (isFinancedDevice(context)) {
+ return createPrivacySettingsFinancedPreference(context);
+ } else {
+ return createPrivacySettingsEnterprisePreference(context);
+ }
+ }
+
+ private static PrivacySettingsEnterprisePreference createPrivacySettingsEnterprisePreference(
+ Context context) {
+ return new PrivacySettingsEnterprisePreference(context);
+ }
+
+ private static PrivacySettingsFinancedPreference createPrivacySettingsFinancedPreference(
+ Context context) {
+ return new PrivacySettingsFinancedPreference(context);
+ }
+
+ private static boolean isFinancedDevice(Context context) {
+ final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ return dpm.isDeviceManaged() && dpm.getDeviceOwnerType(
+ dpm.getDeviceOwnerComponentOnAnyUser()) == DEVICE_OWNER_TYPE_FINANCED;
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
index 47b2a0a..a55d0d3 100644
--- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
@@ -257,6 +257,27 @@
BatteryEntry.startRequestQueue();
}
+ /**
+ * Gets the BatteryEntry list by using the supplied BatteryUsageStats.
+ */
+ public List<BatteryEntry> getBatteryEntryList(
+ BatteryUsageStats batteryUsageStats, boolean showAllApps) {
+ mBatteryUsageStats = USE_FAKE_DATA ? getFakeStats() : batteryUsageStats;
+ if (!sConfig.shouldShowBatteryAttributionList(mContext)) {
+ return null;
+ }
+ final int dischargePercentage = getDischargePercentage(batteryUsageStats);
+ final List<BatteryEntry> usageList = getCoalescedUsageList(showAllApps);
+ final double totalPower = batteryUsageStats.getConsumedPower();
+ for (int i = 0; i < usageList.size(); i++) {
+ final BatteryEntry entry = usageList.get(i);
+ final double percentOfTotal = mBatteryUtils.calculateBatteryPercent(
+ entry.getConsumedPower(), totalPower, dischargePercentage);
+ entry.percent = percentOfTotal;
+ }
+ return usageList;
+ }
+
private int getDischargePercentage(BatteryUsageStats batteryUsageStats) {
int dischargePercentage = batteryUsageStats.getDischargePercentage();
if (dischargePercentage < 0) {
@@ -311,7 +332,7 @@
final int index = batteryEntryList.indexOfKey(realUid);
if (index < 0) {
// New entry.
- batteryEntryList.put(realUid, new BatteryEntry(mActivity, mHandler, mUserManager,
+ batteryEntryList.put(realUid, new BatteryEntry(mContext, mHandler, mUserManager,
consumer, isHidden, packages, null));
} else {
// Combine BatterySippers if we already have one with this UID.
@@ -328,7 +349,7 @@
continue;
}
- results.add(new BatteryEntry(mActivity, mHandler, mUserManager,
+ results.add(new BatteryEntry(mContext, mHandler, mUserManager,
consumer, /* isHidden */ true, null, null));
}
@@ -337,7 +358,7 @@
mBatteryUsageStats.getUserBatteryConsumers();
for (int i = 0, size = userBatteryConsumers.size(); i < size; i++) {
final UserBatteryConsumer consumer = userBatteryConsumers.get(i);
- results.add(new BatteryEntry(mActivity, mHandler, mUserManager,
+ results.add(new BatteryEntry(mContext, mHandler, mUserManager,
consumer, /* isHidden */ true, null, null));
}
}
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index 9fafefd..6c3add3 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -35,6 +35,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
+import android.util.Pair;
import androidx.annotation.NonNull;
@@ -182,49 +183,10 @@
getQuickNameIconForUid(uid, packages);
return;
} else if (batteryConsumer instanceof SystemBatteryConsumer) {
- switch(((SystemBatteryConsumer) batteryConsumer).getDrainType()) {
- case SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY:
- name = context.getResources().getString(R.string.ambient_display_screen_title);
- iconId = R.drawable.ic_settings_aod;
- break;
- case SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH:
- name = context.getResources().getString(R.string.power_bluetooth);
- iconId = com.android.internal.R.drawable.ic_settings_bluetooth;
- break;
- case SystemBatteryConsumer.DRAIN_TYPE_CAMERA:
- name = context.getResources().getString(R.string.power_camera);
- iconId = R.drawable.ic_settings_camera;
- break;
- case SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO:
- name = context.getResources().getString(R.string.power_cell);
- iconId = R.drawable.ic_cellular_1_bar;
- break;
- case SystemBatteryConsumer.DRAIN_TYPE_FLASHLIGHT:
- name = context.getResources().getString(R.string.power_flashlight);
- iconId = R.drawable.ic_settings_display;
- break;
- case SystemBatteryConsumer.DRAIN_TYPE_PHONE:
- name = context.getResources().getString(R.string.power_phone);
- iconId = R.drawable.ic_settings_voice_calls;
- break;
- case SystemBatteryConsumer.DRAIN_TYPE_SCREEN:
- name = context.getResources().getString(R.string.power_screen);
- iconId = R.drawable.ic_settings_display;
- break;
- case SystemBatteryConsumer.DRAIN_TYPE_WIFI:
- name = context.getResources().getString(R.string.power_wifi);
- iconId = R.drawable.ic_settings_wireless;
- break;
- case SystemBatteryConsumer.DRAIN_TYPE_IDLE:
- case SystemBatteryConsumer.DRAIN_TYPE_MEMORY:
- name = context.getResources().getString(R.string.power_idle);
- iconId = R.drawable.ic_settings_phone_idle;
- break;
- case SystemBatteryConsumer.DRAIN_TYPE_CUSTOM:
- name = null;
- iconId = R.drawable.ic_power_system;
- break;
- }
+ final Pair<Integer, String> resourcePair = getResourcePairFromDrainType(
+ context, ((SystemBatteryConsumer) batteryConsumer).getDrainType());
+ iconId = resourcePair.first;
+ name = resourcePair.second;
} else if (batteryConsumer instanceof UserBatteryConsumer) {
UserInfo info = um.getUserInfo(((UserBatteryConsumer) batteryConsumer).getUserId());
if (info != null) {
@@ -493,4 +455,57 @@
((UidBatteryConsumer) batteryConsumer).getPackageWithHighestDrain();
}
}
+
+ /**
+ * Gets icon ID and name from system battery consumer drain type.
+ */
+ public static Pair<Integer, String> getResourcePairFromDrainType(
+ Context context, int drainType) {
+ String name = null;
+ int iconId = 0;
+ switch (drainType) {
+ case SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY:
+ name = context.getResources().getString(R.string.ambient_display_screen_title);
+ iconId = R.drawable.ic_settings_aod;
+ break;
+ case SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH:
+ name = context.getResources().getString(R.string.power_bluetooth);
+ iconId = com.android.internal.R.drawable.ic_settings_bluetooth;
+ break;
+ case SystemBatteryConsumer.DRAIN_TYPE_CAMERA:
+ name = context.getResources().getString(R.string.power_camera);
+ iconId = R.drawable.ic_settings_camera;
+ break;
+ case SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO:
+ name = context.getResources().getString(R.string.power_cell);
+ iconId = R.drawable.ic_cellular_1_bar;
+ break;
+ case SystemBatteryConsumer.DRAIN_TYPE_FLASHLIGHT:
+ name = context.getResources().getString(R.string.power_flashlight);
+ iconId = R.drawable.ic_settings_display;
+ break;
+ case SystemBatteryConsumer.DRAIN_TYPE_PHONE:
+ name = context.getResources().getString(R.string.power_phone);
+ iconId = R.drawable.ic_settings_voice_calls;
+ break;
+ case SystemBatteryConsumer.DRAIN_TYPE_SCREEN:
+ name = context.getResources().getString(R.string.power_screen);
+ iconId = R.drawable.ic_settings_display;
+ break;
+ case SystemBatteryConsumer.DRAIN_TYPE_WIFI:
+ name = context.getResources().getString(R.string.power_wifi);
+ iconId = R.drawable.ic_settings_wireless;
+ break;
+ case SystemBatteryConsumer.DRAIN_TYPE_IDLE:
+ case SystemBatteryConsumer.DRAIN_TYPE_MEMORY:
+ name = context.getResources().getString(R.string.power_idle);
+ iconId = R.drawable.ic_settings_phone_idle;
+ break;
+ case SystemBatteryConsumer.DRAIN_TYPE_CUSTOM:
+ name = null;
+ iconId = R.drawable.ic_power_system;
+ break;
+ }
+ return new Pair<>(Integer.valueOf(iconId), name);
+ }
}
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 1645590..68a0b03 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -298,7 +298,7 @@
*/
public long calculateLastFullChargeTime(BatteryUsageStats batteryUsageStats,
long currentTimeMs) {
- return currentTimeMs - batteryUsageStats.getStatsStartRealtime();
+ return currentTimeMs - batteryUsageStats.getStatsStartTimestamp();
}
public static void logRuntime(String tag, String message, long startTime) {
diff --git a/src/com/android/settings/fuelgauge/FakeUid.java b/src/com/android/settings/fuelgauge/FakeUid.java
index b49fb10..ee0d91f 100644
--- a/src/com/android/settings/fuelgauge/FakeUid.java
+++ b/src/com/android/settings/fuelgauge/FakeUid.java
@@ -366,6 +366,16 @@
}
@Override
+ public long getGnssMeasuredBatteryConsumptionUC() {
+ return 0;
+ }
+
+ @Override
+ public long getMobileRadioMeasuredBatteryConsumptionUC() {
+ return 0;
+ }
+
+ @Override
public long getScreenOnMeasuredBatteryConsumptionUC() {
return 0;
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
index 1052afe..623bd4f 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
@@ -69,7 +69,8 @@
tips.add(new LowBatteryDetector(context, policy, batteryInfo).detect());
tips.add(new HighUsageDetector(context, policy, mBatteryUsageStats, batteryInfo).detect());
- tips.add(new SmartBatteryDetector(policy, context.getContentResolver()).detect());
+ tips.add(new SmartBatteryDetector(
+ context, policy, batteryInfo, context.getContentResolver()).detect());
tips.add(new EarlyWarningDetector(policy, context).detect());
tips.add(new BatteryDefenderDetector(batteryInfo).detect());
// Disable this feature now since it introduces false positive cases. We will try to improve
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java
index e88a494..d12784f 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java
@@ -30,7 +30,6 @@
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.fuelgauge.batterytip.actions.BatteryDefenderAction;
-import com.android.settings.fuelgauge.batterytip.actions.BatterySaverAction;
import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction;
import com.android.settings.fuelgauge.batterytip.actions.OpenBatterySaverAction;
import com.android.settings.fuelgauge.batterytip.actions.OpenRestrictAppFragmentAction;
@@ -99,11 +98,7 @@
return new SmartBatteryAction(settingsActivity, fragment);
case BatteryTip.TipType.BATTERY_SAVER:
case BatteryTip.TipType.LOW_BATTERY:
- if (batteryTip.getState() == BatteryTip.StateType.HANDLED) {
- return new OpenBatterySaverAction(settingsActivity);
- } else {
- return new BatterySaverAction(settingsActivity);
- }
+ return new OpenBatterySaverAction(settingsActivity);
case BatteryTip.TipType.APP_RESTRICTION:
if (batteryTip.getState() == BatteryTip.StateType.HANDLED) {
return new OpenRestrictAppFragmentAction(fragment, (RestrictAppTip) batteryTip);
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetector.java
index 9b6b9b5..f7a4f8c 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetector.java
@@ -56,7 +56,7 @@
EarlyWarningDetector.class.getName()) || mPolicy.testBatterySaverTip;
final int state = powerSaveModeOn
- ? BatteryTip.StateType.HANDLED
+ ? BatteryTip.StateType.INVISIBLE
: mPolicy.batterySaverTipEnabled && discharging && earlyWarning
? BatteryTip.StateType.NEW
: BatteryTip.StateType.INVISIBLE;
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java
index ca9141d..75f47a7 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java
@@ -49,16 +49,16 @@
final boolean lowBattery = mBatteryInfo.batteryLevel <= mWarningLevel
|| (mBatteryInfo.discharging && mBatteryInfo.remainingTimeUs != 0
&& mBatteryInfo.remainingTimeUs < TimeUnit.HOURS.toMicros(mPolicy.lowBatteryHour));
+ final boolean lowBatteryEnabled = mPolicy.lowBatteryEnabled && !powerSaveModeOn;
+ final boolean dischargingLowBatteryState =
+ mPolicy.testLowBatteryTip || (mBatteryInfo.discharging && lowBattery);
int state = BatteryTip.StateType.INVISIBLE;
- if (mPolicy.lowBatteryEnabled) {
- if (powerSaveModeOn) {
- // Show it is handled if battery saver is on
- state = BatteryTip.StateType.HANDLED;
- } else if (mPolicy.testLowBatteryTip || (mBatteryInfo.discharging && lowBattery)) {
- // Show it is new if in test or in discharging low battery state
- state = BatteryTip.StateType.NEW;
- }
+
+ // Show it as new if in test or in discharging low battery state,
+ // dismiss it if battery saver is on or disabled by config.
+ if (lowBatteryEnabled && dischargingLowBatteryState) {
+ state = BatteryTip.StateType.NEW;
}
return new LowBatteryTip(
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetector.java
index a8d4981..23409a1 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetector.java
@@ -17,8 +17,11 @@
package com.android.settings.fuelgauge.batterytip.detectors;
import android.content.ContentResolver;
+import android.content.Context;
+import android.os.PowerManager;
import android.provider.Settings;
+import com.android.settings.fuelgauge.BatteryInfo;
import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.SmartBatteryTip;
@@ -27,22 +30,33 @@
* Detect whether to show smart battery tip.
*/
public class SmartBatteryDetector implements BatteryTipDetector {
+ private static final int EXPECTED_BATTERY_LEVEL = 30;
+
+ private BatteryInfo mBatteryInfo;
private BatteryTipPolicy mPolicy;
private ContentResolver mContentResolver;
+ private PowerManager mPowerManager;
- public SmartBatteryDetector(BatteryTipPolicy policy, ContentResolver contentResolver) {
+ public SmartBatteryDetector(Context context, BatteryTipPolicy policy, BatteryInfo batteryInfo,
+ ContentResolver contentResolver) {
mPolicy = policy;
+ mBatteryInfo = batteryInfo;
mContentResolver = contentResolver;
+ mPowerManager = context.getSystemService(PowerManager.class);
}
@Override
public BatteryTip detect() {
- // Show it if there is no other tips shown
final boolean smartBatteryOff = Settings.Global.getInt(mContentResolver,
- Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, 1) == 0
+ Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, 1) == 0;
+ final boolean isUnderExpectedBatteryLevel =
+ mBatteryInfo.batteryLevel <= EXPECTED_BATTERY_LEVEL;
+ // Show it if in test or smart battery is off.
+ final boolean enableSmartBatteryTip =
+ smartBatteryOff && !mPowerManager.isPowerSaveMode() && isUnderExpectedBatteryLevel
|| mPolicy.testSmartBatteryTip;
final int state =
- smartBatteryOff ? BatteryTip.StateType.NEW : BatteryTip.StateType.INVISIBLE;
+ enableSmartBatteryTip ? BatteryTip.StateType.NEW : BatteryTip.StateType.INVISIBLE;
return new SmartBatteryTip(state);
}
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
index 0c2bb03..6701314 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
@@ -18,7 +18,6 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.os.Parcel;
import com.android.settings.R;
@@ -43,31 +42,23 @@
@Override
public CharSequence getTitle(Context context) {
return context.getString(
- mState == StateType.HANDLED
- ? R.string.battery_tip_early_heads_up_done_title
- : R.string.battery_tip_early_heads_up_title);
+ mState = R.string.battery_tip_early_heads_up_title);
}
@Override
public CharSequence getSummary(Context context) {
return context.getString(
- mState == StateType.HANDLED
- ? R.string.battery_tip_early_heads_up_done_summary
- : R.string.battery_tip_early_heads_up_summary);
+ mState = R.string.battery_tip_early_heads_up_summary);
}
@Override
public int getIconId() {
- return mState == StateType.HANDLED
- ? R.drawable.ic_battery_status_maybe_24dp
- : R.drawable.ic_battery_status_bad_24dp;
+ return mState = R.drawable.ic_battery_status_bad_24dp;
}
@Override
public int getIconTintColorId() {
- return mState == StateType.HANDLED
- ? R.color.battery_maybe_color_light
- : R.color.battery_bad_color_light;
+ return mState = R.color.battery_bad_color_light;
}
@Override
@@ -76,9 +67,9 @@
if (earlyWarningTip.mState == StateType.NEW) {
// Display it if there is early warning
mState = StateType.NEW;
- } else if (mState == StateType.NEW && earlyWarningTip.mState == StateType.INVISIBLE) {
- // If powerSaveMode is really on, show it as handled, otherwise just dismiss it.
- mState = earlyWarningTip.mPowerSaveModeOn ? StateType.HANDLED : StateType.INVISIBLE;
+ } else if (earlyWarningTip.mPowerSaveModeOn) {
+ // If powerSaveMode is really on, dismiss it.
+ mState = StateType.INVISIBLE;
} else {
mState = earlyWarningTip.getState();
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
index d7acdd2..7790b10 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
@@ -21,7 +21,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.settings.R;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
@@ -43,8 +42,7 @@
@Override
public CharSequence getSummary(Context context) {
- return mState == StateType.HANDLED ? context.getString(
- R.string.battery_tip_early_heads_up_done_summary) : mSummary;
+ return mSummary;
}
@Override
diff --git a/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java b/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java
index c6db4ea..03bd195 100644
--- a/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java
+++ b/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java
@@ -17,7 +17,6 @@
package com.android.settings.gestures;
import android.content.Context;
-import android.os.SystemProperties;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
@@ -28,15 +27,13 @@
**/
public class OneHandedEnablePreferenceController extends TogglePreferenceController {
- static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
-
public OneHandedEnablePreferenceController(Context context, String key) {
super(context, key);
}
@Override
public int getAvailabilityStatus() {
- return SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)
+ return OneHandedSettingsUtils.isSupportOneHandedMode()
? BasePreferenceController.AVAILABLE
: BasePreferenceController.UNSUPPORTED_ON_DEVICE;
}
@@ -45,6 +42,7 @@
public boolean setChecked(boolean isChecked) {
OneHandedSettingsUtils.setSettingsOneHandedModeEnabled(mContext,
isChecked);
+ OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, !isChecked);
return true;
}
diff --git a/src/com/android/settings/gestures/OneHandedSettings.java b/src/com/android/settings/gestures/OneHandedSettings.java
index 2449cf2..6a07c85 100644
--- a/src/com/android/settings/gestures/OneHandedSettings.java
+++ b/src/com/android/settings/gestures/OneHandedSettings.java
@@ -18,7 +18,6 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
-import android.os.SystemProperties;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
@@ -52,8 +51,7 @@
new BaseSearchIndexProvider(R.xml.one_handed_settings) {
@Override
protected boolean isPageSearchEnabled(Context context) {
- return SystemProperties.getBoolean(
- OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, false);
+ return OneHandedSettingsUtils.isSupportOneHandedMode();
}
};
}
diff --git a/src/com/android/settings/gestures/OneHandedSettingsUtils.java b/src/com/android/settings/gestures/OneHandedSettingsUtils.java
index f3d7e33..ed0f62f 100644
--- a/src/com/android/settings/gestures/OneHandedSettingsUtils.java
+++ b/src/com/android/settings/gestures/OneHandedSettingsUtils.java
@@ -22,6 +22,7 @@
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
+import android.os.SystemProperties;
import android.provider.Settings;
/**
@@ -29,6 +30,8 @@
*/
public class OneHandedSettingsUtils {
+ static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
+
public enum OneHandedTimeout {
NEVER(0), SHORT(4), MEDIUM(8), LONG(12);
@@ -52,6 +55,13 @@
}
/**
+ * Get One-Handed mode support flag.
+ */
+ public static boolean isSupportOneHandedMode() {
+ return SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false);
+ }
+
+ /**
* Get one-handed mode enable or disable flag from Settings provider.
*
* @param context App context
@@ -119,6 +129,28 @@
}
/**
+ * Get Swipe-down-notification enable or disable flag from Settings provider.
+ *
+ * @param context App context
+ * @return enable or disable Swipe-down-notification flag.
+ */
+ public static boolean isSwipeDownNotificationEnabled(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0) == 1;
+ }
+
+ /**
+ * Set Swipe-down-notification enable or disable flag to Settings provider.
+ *
+ * @param context App context
+ * @param enable enable or disable Swipe-down-notification.
+ */
+ public static void setSwipeDownNotificationEnabled(Context context, boolean enable) {
+ Settings.Secure.putInt(context.getContentResolver(),
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, enable ? 1 : 0);
+ }
+
+ /**
* Register callback for observing Settings.Secure.ONE_HANDED_MODE_ENABLED state.
* @param callback for state changes
*/
diff --git a/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceController.java
index 5eba539..28441cd 100644
--- a/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceController.java
@@ -16,14 +16,8 @@
package com.android.settings.gestures;
-import static android.provider.Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED;
-
-import static com.android.settings.gestures.OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE;
import android.content.Context;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.text.TextUtils;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
@@ -33,32 +27,20 @@
**/
public class SwipeBottomToNotificationPreferenceController extends TogglePreferenceController {
- private static final int ON = 1;
- private static final int OFF = 0;
-
private static final String PREF_KEY = "gesture_swipe_bottom_to_notification";
public SwipeBottomToNotificationPreferenceController(Context context, String key) {
super(context, key);
}
- /** Indicates whether the gesture is available or not. */
- public static boolean isGestureAvailable(Context context) {
- // Disable the gesture once One-Handed mode gesture enabled.
- if (SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
- return !OneHandedSettingsUtils.isOneHandedModeEnabled(context);
- }
- return true;
- }
-
@Override
public int getAvailabilityStatus() {
- return isGestureAvailable(mContext) ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+ return OneHandedSettingsUtils.isSupportOneHandedMode() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isSliceable() {
- return TextUtils.equals(getPreferenceKey(), PREF_KEY);
+ return true;
}
@Override
@@ -68,15 +50,16 @@
@Override
public boolean setChecked(boolean isChecked) {
- Settings.Secure.putInt(mContext.getContentResolver(),
- SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, isChecked ? ON : OFF);
+ if (isChecked) {
+ OneHandedSettingsUtils.setSettingsOneHandedModeEnabled(mContext, false);
+ }
+ OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, isChecked);
return true;
}
@Override
public boolean isChecked() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
- SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, OFF) == ON;
+ return OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext);
}
@Override
diff --git a/src/com/android/settings/gestures/SwipeBottomToNotificationSettings.java b/src/com/android/settings/gestures/SwipeBottomToNotificationSettings.java
index d0441f3..9d85f11 100644
--- a/src/com/android/settings/gestures/SwipeBottomToNotificationSettings.java
+++ b/src/com/android/settings/gestures/SwipeBottomToNotificationSettings.java
@@ -50,8 +50,10 @@
@Override
protected boolean isPageSearchEnabled(Context context) {
- return SwipeBottomToNotificationPreferenceController
- .isGestureAvailable(context);
+ if (!OneHandedSettingsUtils.isSupportOneHandedMode()) {
+ return false;
+ }
+ return !OneHandedSettingsUtils.isOneHandedModeEnabled(context);
}
};
}
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index aa7b2d1..881e39c 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -43,6 +43,25 @@
private static final String TAG = "SettingsHomepageActivity";
+ private static final long HOMEPAGE_LOADING_TIMEOUT_MS = 300;
+
+ private View mHomepageView;
+ private View mSuggestionView;
+
+ /**
+ * Shows the homepage and shows/hides the suggestion together. Only allows to be executed once
+ * to avoid the flicker caused by the suggestion suddenly appearing/disappearing.
+ */
+ public void showHomepageWithSuggestion(boolean showSuggestion) {
+ if (mHomepageView == null) {
+ return;
+ }
+ Log.i(TAG, "showHomepageWithSuggestion: " + showSuggestion);
+ mSuggestionView.setVisibility(showSuggestion ? View.VISIBLE : View.GONE);
+ mHomepageView.setVisibility(View.VISIBLE);
+ mHomepageView = null;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -56,15 +75,23 @@
FeatureFactory.getFactory(this).getSearchFeatureProvider()
.initSearchToolbar(this /* activity */, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);
- final ImageView avatarView = findViewById(R.id.account_avatar);
- getLifecycle().addObserver(new AvatarViewMixin(this, avatarView));
getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
if (!getSystemService(ActivityManager.class).isLowRamDevice()) {
- // Only allow contextual features on high ram devices.
+ // Only allow features on high ram devices.
+ final ImageView avatarView = findViewById(R.id.account_avatar);
+ if (AvatarViewMixin.isAvatarSupported(this)) {
+ avatarView.setVisibility(View.VISIBLE);
+ getLifecycle().addObserver(new AvatarViewMixin(this, avatarView));
+ }
+
if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SILKY_HOME)) {
showSuggestionFragment();
+ } else {
+ findViewById(R.id.homepage_title).setVisibility(View.GONE);
+ avatarView.setVisibility(View.GONE);
}
+
if (FeatureFlagUtils.isEnabled(this, FeatureFlags.CONTEXTUAL_HOME)) {
showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
}
@@ -81,9 +108,16 @@
return;
}
+ mSuggestionView = findViewById(R.id.suggestion_content);
+ mHomepageView = findViewById(R.id.settings_homepage_container);
+ // Hide the homepage for preparing the suggestion.
+ mHomepageView.setVisibility(View.GONE);
+ // Schedule a timer to show the homepage and hide the suggestion on timeout.
+ mHomepageView.postDelayed(() -> showHomepageWithSuggestion(false),
+ HOMEPAGE_LOADING_TIMEOUT_MS);
try {
- showFragment(fragment.newInstance(), R.id.contextual_suggestion_content);
- } catch (IllegalAccessException | InstantiationException e) {
+ showFragment(fragment.getConstructor().newInstance(), R.id.suggestion_content);
+ } catch (Exception e) {
Log.w(TAG, "Cannot show fragment", e);
}
}
@@ -110,10 +144,7 @@
private int getSearchBoxHeight() {
final int searchBarHeight = getResources().getDimensionPixelSize(R.dimen.search_bar_height);
- final int searchBarMarginTop = getResources().getDimensionPixelSize(
- R.dimen.search_bar_margin);
- final int searchBarMarginBottom = getResources().getDimensionPixelSize(
- R.dimen.search_bar_margin_bottom);
- return searchBarHeight + searchBarMarginTop + searchBarMarginBottom;
+ final int searchBarMargin = getResources().getDimensionPixelSize(R.dimen.search_bar_margin);
+ return searchBarHeight + searchBarMargin * 2;
}
}
diff --git a/src/com/android/settings/network/EthernetTetherPreferenceController.java b/src/com/android/settings/network/EthernetTetherPreferenceController.java
index 06cd6a7..3559edb 100644
--- a/src/com/android/settings/network/EthernetTetherPreferenceController.java
+++ b/src/com/android/settings/network/EthernetTetherPreferenceController.java
@@ -43,7 +43,7 @@
super(context, preferenceKey);
mEthernetRegex = context.getString(
com.android.internal.R.string.config_ethernet_iface_regex);
- mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);
+ mEthernetManager = context.getSystemService(EthernetManager.class);
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
diff --git a/src/com/android/settings/network/MobilePlanPreferenceController.java b/src/com/android/settings/network/MobilePlanPreferenceController.java
index d8963ad..65439bc 100644
--- a/src/com/android/settings/network/MobilePlanPreferenceController.java
+++ b/src/com/android/settings/network/MobilePlanPreferenceController.java
@@ -73,9 +73,9 @@
MobilePlanPreferenceHost host) {
super(context);
mHost = host;
- mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- mTm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mCm = context.getSystemService(ConnectivityManager.class);
+ mTm = context.getSystemService(TelephonyManager.class);
+ mUserManager = context.getSystemService(UserManager.class);
mIsSecondaryUser = !mUserManager.isAdminUser();
}
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index 803b981..1d8ee7a 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -1129,7 +1129,7 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem item = menu.add(0, MENU_FIX_CONNECTIVITY, 0, R.string.fix_connectivity);
- item.setIcon(R.drawable.ic_refresh_24dp);
+ item.setIcon(R.drawable.ic_repair_24dp);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
super.onCreateOptionsMenu(menu, inflater);
}
diff --git a/src/com/android/settings/network/NetworkResetRestrictionChecker.java b/src/com/android/settings/network/NetworkResetRestrictionChecker.java
index 46227f9..c873f9d 100644
--- a/src/com/android/settings/network/NetworkResetRestrictionChecker.java
+++ b/src/com/android/settings/network/NetworkResetRestrictionChecker.java
@@ -31,7 +31,7 @@
public NetworkResetRestrictionChecker(Context context) {
mContext = context;
- mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mUserManager = context.getSystemService(UserManager.class);
}
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
diff --git a/src/com/android/settings/network/NetworkScorerPicker.java b/src/com/android/settings/network/NetworkScorerPicker.java
index 9ecab3b..011cf05 100644
--- a/src/com/android/settings/network/NetworkScorerPicker.java
+++ b/src/com/android/settings/network/NetworkScorerPicker.java
@@ -140,6 +140,6 @@
@VisibleForTesting
NetworkScoreManager createNetworkScorerManager(Context context) {
- return (NetworkScoreManager) context.getSystemService(Context.NETWORK_SCORE_SERVICE);
+ return context.getSystemService(NetworkScoreManager.class);
}
}
diff --git a/src/com/android/settings/network/NetworkScorerPickerPreferenceController.java b/src/com/android/settings/network/NetworkScorerPickerPreferenceController.java
index 4b452c0..2abe390 100644
--- a/src/com/android/settings/network/NetworkScorerPickerPreferenceController.java
+++ b/src/com/android/settings/network/NetworkScorerPickerPreferenceController.java
@@ -37,7 +37,7 @@
public NetworkScorerPickerPreferenceController(Context context, String key) {
super(context, key);
mNetworkScoreManager =
- (NetworkScoreManager) mContext.getSystemService(Context.NETWORK_SCORE_SERVICE);
+ mContext.getSystemService(NetworkScoreManager.class);
}
@Override
diff --git a/src/com/android/settings/network/TetherEnabler.java b/src/com/android/settings/network/TetherEnabler.java
index ef031f6..550d324 100644
--- a/src/com/android/settings/network/TetherEnabler.java
+++ b/src/com/android/settings/network/TetherEnabler.java
@@ -128,10 +128,10 @@
mSwitchWidgetController = switchWidgetController;
mDataSaverBackend = new DataSaverBackend(context);
mConnectivityManager =
- (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- mTetheringManager = (TetheringManager) context.getSystemService(Context.TETHERING_SERVICE);
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
- mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ context.getSystemService(ConnectivityManager.class);
+ mTetheringManager = context.getSystemService(TetheringManager.class);
+ mWifiManager = context.getSystemService(WifiManager.class);
+ mUserManager = context.getSystemService(UserManager.class);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothPan = bluetoothPan;
mEthernetRegex =
diff --git a/src/com/android/settings/network/VpnPreferenceController.java b/src/com/android/settings/network/VpnPreferenceController.java
index e815d49..0bec7ac 100644
--- a/src/com/android/settings/network/VpnPreferenceController.java
+++ b/src/com/android/settings/network/VpnPreferenceController.java
@@ -27,6 +27,8 @@
import android.os.UserManager;
import android.provider.Settings;
import android.provider.SettingsSlicesContract;
+import android.security.Credentials;
+import android.security.LegacyVpnProfileStore;
import android.util.Log;
import android.util.SparseArray;
@@ -36,8 +38,11 @@
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
+import com.android.internal.net.VpnProfile;
import com.android.settings.R;
+import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.vpn2.VpnInfoPreference;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -119,6 +124,7 @@
// Copied from SystemUI::SecurityControllerImpl
SparseArray<VpnConfig> vpns = new SparseArray<>();
final List<UserInfo> users = mUserManager.getUsers();
+ int connectedLegacyVpnCount = 0;
for (UserInfo user : users) {
VpnConfig cfg = mVpnManager.getVpnConfig(user.id);
if (cfg == null) {
@@ -129,6 +135,8 @@
final LegacyVpnInfo legacyVpn = mVpnManager.getLegacyVpnInfo(user.id);
if (legacyVpn == null || legacyVpn.state != LegacyVpnInfo.STATE_CONNECTED) {
continue;
+ } else {
+ connectedLegacyVpnCount++;
}
}
vpns.put(user.id, cfg);
@@ -141,13 +149,34 @@
uid = userInfo.id;
}
VpnConfig vpn = vpns.get(uid);
- final String summary;
+ String summary;
if (vpn == null) {
summary = mContext.getString(R.string.vpn_disconnected_summary);
} else {
summary = getNameForVpnConfig(vpn, UserHandle.of(uid));
}
- ThreadUtils.postOnMainThread(() -> mPreference.setSummary(summary));
+ // Optionally add warning icon if an insecure VPN is present.
+ if (Utils.isProviderModelEnabled(mContext) && mPreference instanceof VpnInfoPreference) {
+ final int insecureVpnCount = getInsecureVpnCount();
+ boolean isInsecureVPN = insecureVpnCount > 0;
+ ((VpnInfoPreference) mPreference).setInsecureVpn(isInsecureVPN);
+ // Set the summary based on the total number of VPNs and insecure VPNs.
+ if (isInsecureVPN) {
+ // Add the users and the number of legacy vpns to determine if there is more than
+ // one vpn, since there can be more than one VPN per user.
+ final int vpnCount = vpns.size()
+ + LegacyVpnProfileStore.list(Credentials.VPN).length
+ - connectedLegacyVpnCount;
+ if (vpnCount == 1) {
+ summary = mContext.getString(R.string.vpn_settings_insecure_single);
+ } else {
+ summary = mContext.getString(
+ R.string.vpn_settings_insecure_multiple, insecureVpnCount);
+ }
+ }
+ }
+ final String finalSummary = summary;
+ ThreadUtils.postOnMainThread(() -> mPreference.setSummary(finalSummary));
}
@VisibleForTesting
@@ -167,6 +196,21 @@
}
}
+ @VisibleForTesting
+ protected int getInsecureVpnCount() {
+ int count = 0;
+ for (String key : LegacyVpnProfileStore.list(Credentials.VPN)) {
+ final VpnProfile profile = VpnProfile.decode(key,
+ LegacyVpnProfileStore.get(Credentials.VPN + key));
+ // Return whether any profile is an insecure type.
+ if (VpnProfile.isLegacyType(profile.type)) {
+ count++;
+ }
+ }
+ // We did not find any insecure VPNs.
+ return count;
+ }
+
// Copied from SystemUI::SecurityControllerImpl
private final ConnectivityManager.NetworkCallback
mNetworkCallback = new ConnectivityManager.NetworkCallback() {
diff --git a/src/com/android/settings/network/apn/ApnEditor.java b/src/com/android/settings/network/apn/ApnEditor.java
index afc68d5..78b7ccc 100644
--- a/src/com/android/settings/network/apn/ApnEditor.java
+++ b/src/com/android/settings/network/apn/ApnEditor.java
@@ -1291,8 +1291,8 @@
mReadOnlyApnTypes = null;
mReadOnlyApnFields = null;
- final CarrierConfigManager configManager = (CarrierConfigManager)
- getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ final CarrierConfigManager configManager =
+ getSystemService(CarrierConfigManager.class);
if (configManager != null) {
final PersistableBundle b = configManager.getConfigForSubId(mSubId);
if (b != null) {
diff --git a/src/com/android/settings/network/apn/ApnSettings.java b/src/com/android/settings/network/apn/ApnSettings.java
index 02d9b3d..3ba667c 100755
--- a/src/com/android/settings/network/apn/ApnSettings.java
+++ b/src/com/android/settings/network/apn/ApnSettings.java
@@ -209,8 +209,8 @@
mSubscriptionInfo = getSubscriptionInfo(mSubId);
mTelephonyManager = activity.getSystemService(TelephonyManager.class);
- final CarrierConfigManager configManager = (CarrierConfigManager)
- getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ final CarrierConfigManager configManager =
+ getSystemService(CarrierConfigManager.class);
final PersistableBundle b = configManager.getConfigForSubId(mSubId);
mHideImsApn = b.getBoolean(CarrierConfigManager.KEY_HIDE_IMS_APN_BOOL);
mAllowAddingApns = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL);
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index 9a4cb40..7eb53b9 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -202,7 +202,7 @@
super.onCreate(icicle);
final Context context = getContext();
- mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mUserManager = context.getSystemService(UserManager.class);
mTelephonyManager = context.getSystemService(TelephonyManager.class)
.createForSubscriptionId(mSubId);
diff --git a/src/com/android/settings/network/telephony/NetworkOperatorPreference.java b/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
index cfd587a..a4cff33 100644
--- a/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
+++ b/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
@@ -19,6 +19,7 @@
import static android.telephony.SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
import android.content.Context;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
@@ -180,7 +181,7 @@
public OperatorInfo getOperatorInfo() {
return new OperatorInfo(Objects.toString(mCellId.getOperatorAlphaLong(), ""),
Objects.toString(mCellId.getOperatorAlphaShort(), ""),
- getOperatorNumeric());
+ getOperatorNumeric(), getAccessNetworkTypeFromCellInfo(mCellInfo));
}
private int getIconIdForCell(CellInfo ci) {
@@ -225,6 +226,25 @@
return null;
}
+ private int getAccessNetworkTypeFromCellInfo(CellInfo ci) {
+ if (ci instanceof CellInfoGsm) {
+ return AccessNetworkType.GERAN;
+ }
+ if (ci instanceof CellInfoCdma) {
+ return AccessNetworkType.CDMA2000;
+ }
+ if ((ci instanceof CellInfoWcdma) || (ci instanceof CellInfoTdscdma)) {
+ return AccessNetworkType.UTRAN;
+ }
+ if (ci instanceof CellInfoLte) {
+ return AccessNetworkType.EUTRAN;
+ }
+ if (ci instanceof CellInfoNr) {
+ return AccessNetworkType.NGRAN;
+ }
+ return AccessNetworkType.UNKNOWN;
+ }
+
private void updateIcon(int level) {
if (!mUseNewApi || level < 0 || level >= NUM_SIGNAL_STRENGTH_BINS) {
return;
diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
index c8121c4..588d828 100644
--- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java
+++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
@@ -106,8 +106,8 @@
.createForSubscriptionId(mSubId);
mNetworkScanHelper = new NetworkScanHelper(
mTelephonyManager, mCallback, mNetworkScanExecutor);
- PersistableBundle bundle = ((CarrierConfigManager) getContext().getSystemService(
- Context.CARRIER_CONFIG_SERVICE)).getConfigForSubId(mSubId);
+ PersistableBundle bundle = (getContext().getSystemService(
+ CarrierConfigManager.class)).getConfigForSubId(mSubId);
if (bundle != null) {
mShow4GForLTE = bundle.getBoolean(
CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
diff --git a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
index c782b66..6cb627b 100644
--- a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
+++ b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
@@ -212,8 +212,8 @@
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- final LayoutInflater inflater = (LayoutInflater)
- mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ final LayoutInflater inflater =
+ mContext.getSystemService(LayoutInflater.class);
if (convertView == null) {
convertView = inflater.inflate(mItemResId, null);
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 0e47556..e7b23b9 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -41,6 +41,7 @@
import com.android.settings.panel.PanelFeatureProvider;
import com.android.settings.search.SearchFeatureProvider;
import com.android.settings.security.SecurityFeatureProvider;
+import com.android.settings.security.SecuritySettingsFeatureProvider;
import com.android.settings.slices.SlicesFeatureProvider;
import com.android.settings.users.UserFeatureProvider;
import com.android.settings.wifi.WifiTrackerLibProvider;
@@ -162,6 +163,11 @@
*/
public abstract ExtraAppInfoFeatureProvider getExtraAppInfoFeatureProvider();
+ /**
+ * Retrieve implementation for SecuritySettings feature.
+ */
+ public abstract SecuritySettingsFeatureProvider getSecuritySettingsFeatureProvider();
+
public static final class FactoryNotFoundException extends RuntimeException {
public FactoryNotFoundException(Throwable throwable) {
super("Unable to create factory. Did you misconfigure Proguard?", throwable);
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index dc08547..9105c10 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -63,6 +63,8 @@
import com.android.settings.search.SearchFeatureProviderImpl;
import com.android.settings.security.SecurityFeatureProvider;
import com.android.settings.security.SecurityFeatureProviderImpl;
+import com.android.settings.security.SecuritySettingsFeatureProvider;
+import com.android.settings.security.SecuritySettingsFeatureProviderImpl;
import com.android.settings.slices.SlicesFeatureProvider;
import com.android.settings.slices.SlicesFeatureProviderImpl;
import com.android.settings.users.UserFeatureProvider;
@@ -100,6 +102,7 @@
private FaceFeatureProvider mFaceFeatureProvider;
private WifiTrackerLibProvider mWifiTrackerLibProvider;
private ExtraAppInfoFeatureProvider mExtraAppInfoFeatureProvider;
+ private SecuritySettingsFeatureProvider mSecuritySettingsFeatureProvider;
@Override
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -313,4 +316,12 @@
}
return mExtraAppInfoFeatureProvider;
}
+
+ @Override
+ public SecuritySettingsFeatureProvider getSecuritySettingsFeatureProvider() {
+ if (mSecuritySettingsFeatureProvider == null) {
+ mSecuritySettingsFeatureProvider = new SecuritySettingsFeatureProviderImpl();
+ }
+ return mSecuritySettingsFeatureProvider;
+ }
}
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index 6a97dcd..14b364c 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -228,7 +228,7 @@
launchedCDC = builder.setHeader(mTitle) // Show the title in the header location
.setDescription(mDetails)
.setAlternateButton(alternateButton)
- .setExternal(true)
+ .setExternal(false)
.setUserId(LockPatternUtils.USER_FRP)
.show();
} else if (isManagedProfile && isInternalActivity()
diff --git a/src/com/android/settings/security/SecuritySettingsFeatureProvider.java b/src/com/android/settings/security/SecuritySettingsFeatureProvider.java
new file mode 100644
index 0000000..78e4bc7
--- /dev/null
+++ b/src/com/android/settings/security/SecuritySettingsFeatureProvider.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 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.security;
+
+/** FeatureProvider for security settings. */
+public interface SecuritySettingsFeatureProvider {
+
+ /** Returns whether an alternative SecuritySettings fragment is available. */
+ boolean hasAlternativeSecuritySettingsFragment();
+
+ /** Returns the alternative SecuritySettings fragment name if available. */
+ String getAlternativeSecuritySettingsFragmentClassname();
+}
diff --git a/src/com/android/settings/security/SecuritySettingsFeatureProviderImpl.java b/src/com/android/settings/security/SecuritySettingsFeatureProviderImpl.java
new file mode 100644
index 0000000..8aba523
--- /dev/null
+++ b/src/com/android/settings/security/SecuritySettingsFeatureProviderImpl.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 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.security;
+
+/** Implementation for {@code SecuritySettingsFeatureProvider}. */
+public class SecuritySettingsFeatureProviderImpl implements SecuritySettingsFeatureProvider {
+
+ @Override
+ public boolean hasAlternativeSecuritySettingsFragment() {
+ return false;
+ }
+
+ @Override
+ public String getAlternativeSecuritySettingsFragmentClassname() {
+ return null;
+ }
+}
diff --git a/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java b/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java
index 4efc620..349a91d 100644
--- a/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java
+++ b/src/com/android/settings/security/TopLevelSecurityEntryPreferenceController.java
@@ -19,12 +19,17 @@
import android.content.Context;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
+import android.text.TextUtils;
import android.util.FeatureFlagUtils;
+import androidx.preference.Preference;
+
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.FeatureFlags;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.overlay.FeatureFactory;
public class TopLevelSecurityEntryPreferenceController extends BasePreferenceController {
@@ -56,4 +61,28 @@
return mContext.getText(R.string.security_dashboard_summary_no_fingerprint);
}
}
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+ return super.handlePreferenceTreeClick(preference);
+ }
+
+ SecuritySettingsFeatureProvider securitySettingsFeatureProvider =
+ FeatureFactory.getFactory(mContext).getSecuritySettingsFeatureProvider();
+ if (securitySettingsFeatureProvider.hasAlternativeSecuritySettingsFragment()) {
+ String alternativeFragmentClassname =
+ securitySettingsFeatureProvider
+ .getAlternativeSecuritySettingsFragmentClassname();
+ if (alternativeFragmentClassname != null) {
+ new SubSettingLauncher(mContext)
+ .setDestination(alternativeFragmentClassname)
+ .setSourceMetricsCategory(getMetricsCategory())
+ .launch();
+ return true;
+ }
+ }
+
+ return super.handlePreferenceTreeClick(preference);
+ }
}
diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java
index 7dab4c0..3051b92 100644
--- a/src/com/android/settings/sim/SimSelectNotification.java
+++ b/src/com/android/settings/sim/SimSelectNotification.java
@@ -104,8 +104,8 @@
subId = SubscriptionManager.getDefaultSmsSubscriptionId();
}
- SubscriptionManager subscriptionManager = ((SubscriptionManager) context.getSystemService(
- Context.TELEPHONY_SUBSCRIPTION_SERVICE));
+ SubscriptionManager subscriptionManager = (context.getSystemService(
+ SubscriptionManager.class));
if (!subscriptionManager.isActiveSubscriptionId(subId)) {
Log.w(TAG, "onEnableMmsDataRequest invalid sub ID " + subId);
return;
@@ -130,8 +130,8 @@
return;
}
- TelephonyManager tm = ((TelephonyManager) context.getSystemService(
- Context.TELEPHONY_SERVICE)).createForSubscriptionId(subId);
+ TelephonyManager tm = (context.getSystemService(
+ TelephonyManager.class)).createForSubscriptionId(subId);
if (tm.isDataEnabledForApn(TYPE_MMS)) {
Log.w(TAG, "onEnableMmsDataRequest MMS data already enabled on sub ID " + subId);
@@ -230,14 +230,14 @@
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
- (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
notificationManager.notify(SIM_SELECT_NOTIFICATION_ID, builder.build());
}
public static void cancelSimSelectNotification(Context context) {
NotificationManager notificationManager =
- (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ context.getSystemService(NotificationManager.class);
notificationManager.cancel(SIM_SELECT_NOTIFICATION_ID);
}
@@ -270,14 +270,14 @@
// Notify the notification.
NotificationManager notificationManager =
- (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
notificationManager.notify(ENABLE_MMS_NOTIFICATION_ID, builder.build());
}
private void cancelEnableMmsNotification(Context context) {
NotificationManager notificationManager =
- (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ context.getSystemService(NotificationManager.class);
notificationManager.cancel(ENABLE_MMS_NOTIFICATION_ID);
}
diff --git a/src/com/android/settings/vpn2/AppManagementFragment.java b/src/com/android/settings/vpn2/AppManagementFragment.java
index 0543fee..4543f3f 100644
--- a/src/com/android/settings/vpn2/AppManagementFragment.java
+++ b/src/com/android/settings/vpn2/AppManagementFragment.java
@@ -319,7 +319,7 @@
@VisibleForTesting
static boolean appHasVpnPermission(Context context, @NonNull ApplicationInfo application) {
final AppOpsManager service =
- (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ context.getSystemService(AppOpsManager.class);
final List<AppOpsManager.PackageOps> ops = service.getOpsForPackage(application.uid,
application.packageName, new int[]{OP_ACTIVATE_VPN, OP_ACTIVATE_PLATFORM_VPN});
return !ArrayUtils.isEmpty(ops);
diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java
index 03e3613..24fb576 100644
--- a/src/com/android/settings/vpn2/ConfigDialog.java
+++ b/src/com/android/settings/vpn2/ConfigDialog.java
@@ -204,10 +204,16 @@
configureAdvancedOptionsVisibility();
- // Create a button to forget the profile if it has already been saved..
if (mExists) {
+ // Create a button to forget the profile if it has already been saved..
setButton(DialogInterface.BUTTON_NEUTRAL,
context.getString(R.string.vpn_forget), mListener);
+
+ // Display warning subtitle if the existing VPN is an insecure type...
+ if (VpnProfile.isLegacyType(mProfile.type)) {
+ TextView subtitle = mView.findViewById(R.id.dialog_alert_subtitle);
+ subtitle.setVisibility(View.VISIBLE);
+ }
}
// Create a button to save the profile.
diff --git a/src/com/android/settings/vpn2/ManageablePreference.java b/src/com/android/settings/vpn2/ManageablePreference.java
index 68971f2..c65073f 100644
--- a/src/com/android/settings/vpn2/ManageablePreference.java
+++ b/src/com/android/settings/vpn2/ManageablePreference.java
@@ -16,15 +16,20 @@
package com.android.settings.vpn2;
+import static android.text.Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
+
import android.content.Context;
import android.content.res.Resources;
import android.os.UserHandle;
import android.os.UserManager;
+import android.text.SpannableString;
import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import com.android.settings.R;
import com.android.settings.widget.GearPreference;
+import com.android.settingslib.Utils;
/**
* This class sets appropriate enabled state and user admin message when userId is set
@@ -34,6 +39,7 @@
public static int STATE_NONE = -1;
boolean mIsAlwaysOn = false;
+ boolean mIsInsecureVpn = false;
int mState = STATE_NONE;
int mUserId;
@@ -57,6 +63,10 @@
return mIsAlwaysOn;
}
+ public boolean isInsecureVpn() {
+ return mIsInsecureVpn;
+ }
+
public int getState() {
return mState;
}
@@ -77,8 +87,19 @@
}
/**
+ * Set whether the VPN associated with this preference has an insecure type.
+ * By default the value will be False.
+ */
+ public void setInsecureVpn(boolean isInsecureVpn) {
+ if (mIsInsecureVpn != isInsecureVpn) {
+ mIsInsecureVpn = isInsecureVpn;
+ updateSummary();
+ }
+ }
+
+ /**
* Update the preference summary string (see {@see Preference#setSummary}) with a string
- * reflecting connection status and always-on setting.
+ * reflecting connection status, always-on setting and whether the vpn is insecure.
*
* State is not shown for {@code STATE_NONE}.
*/
@@ -91,6 +112,18 @@
summary = TextUtils.isEmpty(summary) ? alwaysOnString : res.getString(
R.string.join_two_unrelated_items, summary, alwaysOnString);
}
- setSummary(summary);
+ if (mIsInsecureVpn) {
+ final String insecureString = res.getString(R.string.vpn_insecure_summary);
+ summary = TextUtils.isEmpty(summary) ? insecureString : res.getString(
+ R.string.join_two_unrelated_items, summary, insecureString);
+
+ SpannableString summarySpan = new SpannableString(summary);
+ final int colorError = Utils.getColorErrorDefaultColor(getContext());
+ summarySpan.setSpan(new ForegroundColorSpan(colorError), 0, summary.length(),
+ SPAN_EXCLUSIVE_INCLUSIVE);
+ setSummary(summarySpan);
+ } else {
+ setSummary(summary);
+ }
}
}
diff --git a/src/com/android/settings/vpn2/VpnInfoPreference.java b/src/com/android/settings/vpn2/VpnInfoPreference.java
new file mode 100644
index 0000000..cca45b5
--- /dev/null
+++ b/src/com/android/settings/vpn2/VpnInfoPreference.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 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.vpn2;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+import com.android.settingslib.HelpUtils;
+import com.android.settingslib.RestrictedPreference;
+
+
+/**
+ * A preference with an Info icon on the side
+ */
+public class VpnInfoPreference extends RestrictedPreference implements View.OnClickListener {
+
+ private boolean mIsInsecureVpn = false;
+ private String mHelpUrl;
+
+ public VpnInfoPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mHelpUrl = context.getString(R.string.help_url_insecure_vpn);
+ }
+
+ @Override
+ protected int getSecondTargetResId() {
+ // Note: in the future, we will probably want to provide a configuration option
+ // for this info to not be the warning color.
+ return R.layout.preference_widget_warning;
+ }
+
+ @Override
+ protected boolean shouldHideSecondTarget() {
+ return false;
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ final View icon = holder.findViewById(R.id.warning_button);
+ if (mIsInsecureVpn && !TextUtils.isEmpty(mHelpUrl)) {
+ icon.setVisibility(View.VISIBLE);
+ icon.setOnClickListener(this);
+ icon.setEnabled(true);
+ } else {
+ icon.setVisibility(View.GONE);
+ icon.setOnClickListener(this);
+ icon.setEnabled(false);
+ }
+
+ // Hide the divider from view
+ final View divider = holder.findViewById(R.id.two_target_divider);
+ divider.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v.getId() == R.id.warning_button) {
+ final Intent intent = HelpUtils.getHelpIntent(
+ getContext(), mHelpUrl, this.getClass().getName());
+
+ if (intent != null) {
+ ((Activity) getContext()).startActivityForResult(intent, 0);
+ }
+ }
+ }
+
+ /**
+ * Sets whether this preference corresponds to an insecure VPN. This will also affect whether
+ * the warning icon appears to the user.
+ */
+ public void setInsecureVpn(boolean isInsecureVpn) {
+ if (mIsInsecureVpn != isInsecureVpn) {
+ mIsInsecureVpn = isInsecureVpn;
+ notifyChanged();
+ }
+ }
+}
diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java
index 7635733..2620426 100644
--- a/src/com/android/settings/vpn2/VpnSettings.java
+++ b/src/com/android/settings/vpn2/VpnSettings.java
@@ -116,9 +116,9 @@
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
- mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- mVpnManager = (VpnManager) getSystemService(Context.VPN_MANAGEMENT_SERVICE);
+ mUserManager = getSystemService(UserManager.class);
+ mConnectivityManager = getSystemService(ConnectivityManager.class);
+ mVpnManager = getSystemService(VpnManager.class);
mUnavailable = isUiRestricted();
setHasOptionsMenu(!mUnavailable);
@@ -294,6 +294,7 @@
p.setState(LegacyVpnPreference.STATE_NONE);
}
p.setAlwaysOn(lockdownVpnKey != null && lockdownVpnKey.equals(profile.key));
+ p.setInsecureVpn(VpnProfile.isLegacyType(profile.type));
updates.add(p);
}
@@ -303,6 +304,7 @@
LegacyVpnPreference p = mSettings.findOrCreatePreference(stubProfile, false);
p.setState(vpn.state);
p.setAlwaysOn(lockdownVpnKey != null && lockdownVpnKey.equals(vpn.key));
+ p.setInsecureVpn(VpnProfile.isLegacyType(stubProfile.type));
updates.add(p);
}
@@ -509,7 +511,7 @@
}
// Fetch VPN-enabled apps from AppOps.
- AppOpsManager aom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ AppOpsManager aom = context.getSystemService(AppOpsManager.class);
List<AppOpsManager.PackageOps> apps =
aom.getPackagesForOps(new int[] {OP_ACTIVATE_VPN, OP_ACTIVATE_PLATFORM_VPN});
if (apps != null) {
diff --git a/src/com/android/settings/wifi/ChangeWifiStateDetails.java b/src/com/android/settings/wifi/ChangeWifiStateDetails.java
index 9841615..4e3e62e 100644
--- a/src/com/android/settings/wifi/ChangeWifiStateDetails.java
+++ b/src/com/android/settings/wifi/ChangeWifiStateDetails.java
@@ -49,7 +49,7 @@
super.onCreate(savedInstanceState);
final Context context = getActivity();
mAppBridge = new AppStateChangeWifiStateBridge(context, mState, null);
- mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ mAppOpsManager = context.getSystemService(AppOpsManager.class);
// find preferences
addPreferencesFromResource(R.xml.change_wifi_state_details);
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index ff313c7..484d3cc 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -69,7 +69,7 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
- final WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
+ final WifiManager wifiManager = getSystemService(WifiManager.class);
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new WifiP2pPreferenceController(context, getSettingsLifecycle(),
wifiManager));
diff --git a/src/com/android/settings/wifi/UseOpenWifiPreferenceController.java b/src/com/android/settings/wifi/UseOpenWifiPreferenceController.java
index 44114e5..5fa4dfb 100644
--- a/src/com/android/settings/wifi/UseOpenWifiPreferenceController.java
+++ b/src/com/android/settings/wifi/UseOpenWifiPreferenceController.java
@@ -51,7 +51,7 @@
super(context, KEY_USE_OPEN_WIFI_AUTOMATICALLY);
mContentResolver = context.getContentResolver();
mNetworkScoreManager =
- (NetworkScoreManager) context.getSystemService(Context.NETWORK_SCORE_SERVICE);
+ context.getSystemService(NetworkScoreManager.class);
mSettingObserver = new SettingObserver();
updateEnableUseWifiComponentName();
checkForFeatureSupportedScorers();
diff --git a/src/com/android/settings/wifi/WifiAPITest.java b/src/com/android/settings/wifi/WifiAPITest.java
index 15465ed..498539d 100644
--- a/src/com/android/settings/wifi/WifiAPITest.java
+++ b/src/com/android/settings/wifi/WifiAPITest.java
@@ -64,7 +64,7 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
+ mWifiManager = getSystemService(WifiManager.class);
}
@Override
diff --git a/src/com/android/settings/wifi/WifiConfigInfo.java b/src/com/android/settings/wifi/WifiConfigInfo.java
index 0de3063..18ac2e5 100644
--- a/src/com/android/settings/wifi/WifiConfigInfo.java
+++ b/src/com/android/settings/wifi/WifiConfigInfo.java
@@ -38,7 +38,7 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
+ mWifiManager = getSystemService(WifiManager.class);
setContentView(R.layout.wifi_config_info);
mConfigList = (TextView) findViewById(R.id.config_list);
}
diff --git a/src/com/android/settings/wifi/WifiEnabler.java b/src/com/android/settings/wifi/WifiEnabler.java
index dc5be42..ba1ee3c 100644
--- a/src/com/android/settings/wifi/WifiEnabler.java
+++ b/src/com/android/settings/wifi/WifiEnabler.java
@@ -75,7 +75,7 @@
public WifiEnabler(Context context, SwitchWidgetController switchWidget,
MetricsFeatureProvider metricsFeatureProvider) {
this(context, switchWidget, metricsFeatureProvider,
- (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
+ context.getSystemService(ConnectivityManager.class));
}
@VisibleForTesting
@@ -86,7 +86,7 @@
mSwitchWidget = switchWidget;
mSwitchWidget.setListener(this);
mMetricsFeatureProvider = metricsFeatureProvider;
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mWifiManager = context.getSystemService(WifiManager.class);
mConnectivityManager = connectivityManager;
mIntentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
diff --git a/src/com/android/settings/wifi/WifiNoInternetDialog.java b/src/com/android/settings/wifi/WifiNoInternetDialog.java
index 57e42f8..3cd8a8a 100644
--- a/src/com/android/settings/wifi/WifiNoInternetDialog.java
+++ b/src/com/android/settings/wifi/WifiNoInternetDialog.java
@@ -107,7 +107,7 @@
}
};
- mCM = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ mCM = getSystemService(ConnectivityManager.class);
mCM.registerNetworkCallback(request, mNetworkCallback);
final NetworkInfo ni = mCM.getNetworkInfo(mNetwork);
diff --git a/src/com/android/settings/wifi/WifiStatusTest.java b/src/com/android/settings/wifi/WifiStatusTest.java
index 249cd71..06242e3 100644
--- a/src/com/android/settings/wifi/WifiStatusTest.java
+++ b/src/com/android/settings/wifi/WifiStatusTest.java
@@ -116,7 +116,7 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
+ mWifiManager = getSystemService(WifiManager.class);
mWifiStateFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
mWifiStateFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java
index d05260a..e576851 100644
--- a/src/com/android/settings/wifi/WifiUtils.java
+++ b/src/com/android/settings/wifi/WifiUtils.java
@@ -83,7 +83,7 @@
final DevicePolicyManager dpm =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
final PackageManager pm = context.getPackageManager();
- final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ final UserManager um = context.getSystemService(UserManager.class);
// Check if device has DPM capability. If it has and dpm is still null, then we
// treat this case with suspicion and bail out.
diff --git a/src/com/android/settings/wifi/WifiWakeupPreferenceController.java b/src/com/android/settings/wifi/WifiWakeupPreferenceController.java
index e9fd350..3aa62b9 100644
--- a/src/com/android/settings/wifi/WifiWakeupPreferenceController.java
+++ b/src/com/android/settings/wifi/WifiWakeupPreferenceController.java
@@ -73,7 +73,7 @@
public WifiWakeupPreferenceController(Context context) {
super(context, KEY_ENABLE_WIFI_WAKEUP);
- mLocationManager = (LocationManager) context.getSystemService(Service.LOCATION_SERVICE);
+ mLocationManager = context.getSystemService(LocationManager.class);
mWifiManager = context.getSystemService(WifiManager.class);
}
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
index de64b91..3cfe514 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
@@ -128,8 +128,8 @@
boolean isWfcModeEditable = true;
boolean isWfcRoamingModeEditable = false;
- final CarrierConfigManager configManager = (CarrierConfigManager)
- activity.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ final CarrierConfigManager configManager =
+ activity.getSystemService(CarrierConfigManager.class);
if (configManager != null) {
PersistableBundle b =
configManager.getConfigForSubId(WifiCallingSettingsForSub.this.mSubId);
@@ -343,8 +343,8 @@
return;
}
- final CarrierConfigManager configManager = (CarrierConfigManager)
- getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ final CarrierConfigManager configManager =
+ getSystemService(CarrierConfigManager.class);
boolean isWifiOnlySupported = true;
if (configManager != null) {
diff --git a/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java b/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java
index 8f9741a..9ab64c7 100644
--- a/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/AddDevicePreferenceController2.java
@@ -42,7 +42,7 @@
public AddDevicePreferenceController2(Context context) {
super(context, KEY_ADD_DEVICE);
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mWifiManager = context.getSystemService(WifiManager.class);
}
public void setWifiEntry(WifiEntry wifiEntry) {
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index 211ceed..0c3f42d 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -42,6 +42,7 @@
import android.net.NetworkRequest;
import android.net.RouteInfo;
import android.net.Uri;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
@@ -155,6 +156,8 @@
static final String KEY_IPV6_CATEGORY = "ipv6_category";
@VisibleForTesting
static final String KEY_IPV6_ADDRESSES_PREF = "ipv6_addresses";
+ @VisibleForTesting
+ static final String KEY_WIFI_TYPE_PREF = "type";
private final WifiEntry mWifiEntry;
private final ConnectivityManager mConnectivityManager;
@@ -186,6 +189,7 @@
private Preference mGatewayPref;
private Preference mSubnetPref;
private Preference mDnsPref;
+ private Preference mTypePref;
private PreferenceCategory mIpv6Category;
private Preference mIpv6AddressPref;
private Lifecycle mLifecycle;
@@ -382,6 +386,7 @@
mGatewayPref = screen.findPreference(KEY_GATEWAY_PREF);
mSubnetPref = screen.findPreference(KEY_SUBNET_MASK_PREF);
mDnsPref = screen.findPreference(KEY_DNS_PREF);
+ mTypePref = screen.findPreference(KEY_WIFI_TYPE_PREF);
mIpv6Category = screen.findPreference(KEY_IPV6_CATEGORY);
mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
@@ -552,6 +557,8 @@
refreshEapSimSubscription();
// MAC Address Pref
refreshMacAddress();
+ // Wifi Type
+ refreshWifiType();
}
private void refreshRssiViews() {
@@ -749,6 +756,36 @@
}
}
+ private void refreshWifiType() {
+ final ConnectedInfo connectedInfo = mWifiEntry.getConnectedInfo();
+ if (connectedInfo == null) {
+ mTypePref.setVisible(false);
+ return;
+ }
+
+ final int typeString = getWifiStandardTypeString(connectedInfo.wifiStandard);
+ if (typeString != -1) {
+ mTypePref.setSummary(typeString);
+ mTypePref.setVisible(true);
+ } else {
+ mTypePref.setVisible(false);
+ }
+ }
+
+ private int getWifiStandardTypeString(int wifiStandardType) {
+ Log.d(TAG, "Wifi Type " + wifiStandardType);
+ switch (wifiStandardType) {
+ case ScanResult.WIFI_STANDARD_11AX:
+ return R.string.wifi_type_11AX;
+ case ScanResult.WIFI_STANDARD_11AC:
+ return R.string.wifi_type_11AC;
+ case ScanResult.WIFI_STANDARD_11N:
+ return R.string.wifi_type_11N;
+ default:
+ return -1;
+ }
+ }
+
private int getMacAddressTitle() {
if (mWifiEntry.getPrivacy() == WifiEntry.PRIVACY_RANDOMIZED_MAC) {
return mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED
diff --git a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
index 104761f..488ffcb 100644
--- a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
+++ b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
@@ -143,8 +143,8 @@
if (admin == null) {
final DevicePolicyManager dpm = (DevicePolicyManager)
getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
- final UserManager um = (UserManager)
- getContext().getSystemService(Context.USER_SERVICE);
+ final UserManager um =
+ getContext().getSystemService(UserManager.class);
final int profileOwnerUserId = Utils.getManagedProfileId(
um, UserHandle.myUserId());
if (profileOwnerUserId != UserHandle.USER_NULL) {
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
index c484922..72a2361 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
@@ -45,7 +45,7 @@
public WifiPrivacyPreferenceController2(Context context) {
super(context, KEY_WIFI_PRIVACY);
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mWifiManager = context.getSystemService(WifiManager.class);
}
public void setWifiEntry(WifiEntry wifiEntry) {
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index abf5bec..081e160 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -373,8 +373,8 @@
* device security or if lock screen is unlocked
*/
public static void showLockScreen(Context context, Runnable successRunnable) {
- final KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(
- Context.KEYGUARD_SERVICE);
+ final KeyguardManager keyguardManager = context.getSystemService(
+ KeyguardManager.class);
if (keyguardManager.isKeyguardSecure()) {
final BiometricPrompt.AuthenticationCallback authenticationCallback =
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pPreferenceController.java b/src/com/android/settings/wifi/p2p/WifiP2pPreferenceController.java
index 9604410..8696bef 100644
--- a/src/com/android/settings/wifi/p2p/WifiP2pPreferenceController.java
+++ b/src/com/android/settings/wifi/p2p/WifiP2pPreferenceController.java
@@ -71,7 +71,7 @@
super(context);
mWifiManager = wifiManager;
lifecycle.addObserver(this);
- mLocationManager = (LocationManager) context.getSystemService(Service.LOCATION_SERVICE);
+ mLocationManager = context.getSystemService(LocationManager.class);
}
@Override
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
index 9578c80..0aac0bb 100644
--- a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
+++ b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
@@ -200,7 +200,7 @@
public void onActivityCreated(Bundle savedInstanceState) {
final Activity activity = getActivity();
if (mWifiP2pManager == null) {
- mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
+ mWifiP2pManager = getSystemService(WifiP2pManager.class);
}
if (mWifiP2pManager != null) {
diff --git a/src/com/android/settings/wifi/qrcode/QrCamera.java b/src/com/android/settings/wifi/qrcode/QrCamera.java
index 3865eb1..274655d 100644
--- a/src/com/android/settings/wifi/qrcode/QrCamera.java
+++ b/src/com/android/settings/wifi/qrcode/QrCamera.java
@@ -202,7 +202,7 @@
}
final WindowManager winManager =
- (WindowManager) mContext.get().getSystemService(Context.WINDOW_SERVICE);
+ mContext.get().getSystemService(WindowManager.class);
final int rotation = winManager.getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
diff --git a/src/com/android/settings/wifi/tether/TetherService.java b/src/com/android/settings/wifi/tether/TetherService.java
index 5902719..a3321bb 100644
--- a/src/com/android/settings/wifi/tether/TetherService.java
+++ b/src/com/android/settings/wifi/tether/TetherService.java
@@ -255,7 +255,7 @@
}
private void disableTethering(final int tetheringType) {
- final TetheringManager tm = (TetheringManager) getSystemService(Context.TETHERING_SERVICE);
+ final TetheringManager tm = getSystemService(TetheringManager.class);
tm.stopTethering(tetheringType);
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherBasePreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherBasePreferenceController.java
index 46da097..a950dc3 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherBasePreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherBasePreferenceController.java
@@ -45,8 +45,8 @@
OnTetherConfigUpdateListener listener) {
super(context);
mListener = listener;
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
- mTm = (TetheringManager) context.getSystemService(Context.TETHERING_SERVICE);
+ mWifiManager = context.getSystemService(WifiManager.class);
+ mTm = context.getSystemService(TetheringManager.class);
mWifiRegexs = mTm.getTetherableWifiRegexs();
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherMaximizeCompatibilityPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherMaximizeCompatibilityPreferenceController.java
index bc87d5c..41532d0 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherMaximizeCompatibilityPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherMaximizeCompatibilityPreferenceController.java
@@ -86,7 +86,11 @@
if (mWifiManager.isBridgedApConcurrencySupported()) {
final boolean isEnabled = config.isBridgedModeOpportunisticShutdownEnabled();
Log.d(TAG, "isBridgedModeOpportunisticShutdownEnabled:" + isEnabled);
- return isEnabled;
+ // Because the return value defined by the Wi-Fi framework API is opposite to the UI.
+ // Compatibility on: isBridgedModeOpportunisticShutdownEnabled() = false
+ // Compatibility off: isBridgedModeOpportunisticShutdownEnabled() = true
+ // Need to return the reverse value.
+ return !isEnabled;
}
// If the BridgedAp Concurrency is not supported in early Pixel devices (e.g. Pixel 2~5),
@@ -112,7 +116,11 @@
SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ};
builder.setBands(bands);
Log.d(TAG, "setBridgedModeOpportunisticShutdownEnabled:" + enabled);
- builder.setBridgedModeOpportunisticShutdownEnabled(enabled);
+ // Because the defined value by the Wi-Fi framework API is opposite to the UI.
+ // Compatibility on: setBridgedModeOpportunisticShutdownEnabled(false)
+ // Compatibility off: setBridgedModeOpportunisticShutdownEnabled(true)
+ // Need to set the reverse value.
+ builder.setBridgedModeOpportunisticShutdownEnabled(!enabled);
} else {
int band = enabled
? SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ
diff --git a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
index 70b6a45..1fa41b2 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
@@ -63,7 +63,7 @@
boolean initSoftApManager) {
super(context);
mTetheringManager = context.getSystemService(TetheringManager.class);
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mWifiManager = context.getSystemService(WifiManager.class);
mWifiRegexs = mTetheringManager.getTetherableWifiRegexs();
mLifecycle = lifecycle;
if (lifecycle != null) {
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
index e342550..41b439b 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@@ -110,7 +110,7 @@
@Override
public void onAttach(Context context) {
super.onAttach(context);
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mWifiManager = context.getSystemService(WifiManager.class);
mTetherChangeReceiver = new TetherChangeReceiver();
mSSIDPreferenceController = use(WifiTetherSSIDPreferenceController.class);
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
index 3d8cd3e..379bf6d 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
@@ -73,8 +73,8 @@
mSwitch = mSwitchBar.getSwitch();
mDataSaverBackend = new DataSaverBackend(context);
mConnectivityManager =
- (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ context.getSystemService(ConnectivityManager.class);
+ mWifiManager = context.getSystemService(WifiManager.class);
mSwitchBar.setChecked(mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED);
updateWifiSwitch();
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceControllerTest.java
index 39a663e..01942f0 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ReduceBrightColorsPreferenceControllerTest.java
@@ -19,7 +19,6 @@
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
-import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -32,29 +31,14 @@
@RunWith(AndroidJUnit4.class)
public class ReduceBrightColorsPreferenceControllerTest {
private static final String PREF_KEY = "rbc_preference";
- private static final String RBC_ACTIVATED =
- Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED;
- private static final int ON = 1;
- private static final int OFF = 0;
private final Context mContext = ApplicationProvider.getApplicationContext();
private final ReduceBrightColorsPreferenceController mController =
new ReduceBrightColorsPreferenceController(mContext, PREF_KEY);
@Test
- public void getSummary_enabledRbc_shouldReturnOnSummary() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- RBC_ACTIVATED, ON);
-
+ public void getSummary_returnSummary() {
assertThat(mController.getSummary().toString().contains(
- mContext.getText(R.string.accessibility_feature_state_on))).isTrue();
- }
- @Test
- public void getSummary_disabledRbc_shouldReturnOffSummary() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- RBC_ACTIVATED, OFF);
-
- assertThat(mController.getSummary().toString().contains(
- mContext.getText(R.string.accessibility_feature_state_off))).isTrue();
+ mContext.getText(R.string.reduce_bright_colors_preference_summary))).isTrue();
}
}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
index b22b156..4b6a6a8 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
@@ -39,6 +39,7 @@
import android.text.TextUtils;
import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@@ -72,9 +73,13 @@
ShadowSettingsLibUtils.class})
public class AccountPreferenceControllerTest {
+ private static final String PREF_KEY_ACCOUNTS = "accounts_category";
+
@Mock(answer = RETURNS_DEEP_STUBS)
private PreferenceScreen mScreen;
@Mock(answer = RETURNS_DEEP_STUBS)
+ private PreferenceCategory mAccountsCategory;
+ @Mock(answer = RETURNS_DEEP_STUBS)
private UserManager mUserManager;
@Mock(answer = RETURNS_DEEP_STUBS)
private SettingsPreferenceFragment mFragment;
@@ -95,6 +100,9 @@
shadowApp.setSystemService(Context.ACCOUNT_SERVICE, mAccountManager);
when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+ // This is a bit ugly, but hard to avoid because of how the mocks are used in these tests.
+ // TODO: Refactor these tests to not use RETURNS_DEEP_STUBS.
+ when(mScreen.findPreference(PREF_KEY_ACCOUNTS)).thenReturn(mScreen);
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
when(mAccountManager.getAuthenticatorTypesAsUser(anyInt()))
.thenReturn(new AuthenticatorDescription[0]);
@@ -166,6 +174,7 @@
// First time resume will build the UI
mController.onResume();
reset(mScreen);
+ when(mScreen.findPreference(PREF_KEY_ACCOUNTS)).thenReturn(mScreen);
mController.onResume();
verify(mScreen, never()).addPreference(any(PreferenceGroup.class));
@@ -184,6 +193,7 @@
// add a new profile
infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE));
reset(mScreen);
+ when(mScreen.findPreference(PREF_KEY_ACCOUNTS)).thenReturn(mScreen);
mController.onResume();
verify(mScreen, times(1)).addPreference(any(PreferenceGroup.class));
diff --git a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
index 534d3c6..04db527 100644
--- a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
@@ -27,7 +27,6 @@
import static org.mockito.Mockito.verify;
import android.accounts.Account;
-import android.app.ActivityManager;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -57,7 +56,6 @@
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
-import org.robolectric.shadows.ShadowActivityManager;
import org.robolectric.shadows.ShadowContentResolver;
import org.robolectric.shadows.ShadowPackageManager;
@@ -97,31 +95,7 @@
}
@Test
- public void onStart_configDisabled_doNothing() {
- final AvatarViewMixin mixin = spy(new AvatarViewMixin(mActivity, mImageView));
- mixin.onStart();
-
- verify(mixin, never()).hasAccount();
- }
-
- @Test
- public void onStart_lowRamDevice_doNothing() {
- final AvatarViewMixin mixin = spy(new AvatarViewMixin(mActivity, mImageView));
-
- final ShadowActivityManager activityManager =
- Shadow.extract(mContext.getSystemService(ActivityManager.class));
- activityManager.setIsLowRamDevice(true);
-
- mixin.onStart();
-
- verify(mixin, never()).hasAccount();
- }
-
- @Test
- @Config(qualifiers = "mcc999",
- shadows = {
- BatteryFixSliceTest.ShadowBatteryTipLoader.class
- })
+ @Config(shadows = BatteryFixSliceTest.ShadowBatteryTipLoader.class)
public void onStart_useMockAvatarViewMixin_shouldBeExecuted() {
final AvatarViewMixin mockAvatar = spy(new AvatarViewMixin(mActivity, mImageView));
@@ -132,7 +106,6 @@
}
@Test
- @Config(qualifiers = "mcc999")
public void onStart_noAccount_mAccountNameShouldBeNull() {
final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mActivity, mImageView);
avatarViewMixin.mAccountName = FAKE_ACCOUNT;
diff --git a/tests/robotests/src/com/android/settings/accounts/TopLevelAccountEntryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/TopLevelAccountEntryPreferenceControllerTest.java
index 3a67d7f..1d63cd1 100644
--- a/tests/robotests/src/com/android/settings/accounts/TopLevelAccountEntryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/TopLevelAccountEntryPreferenceControllerTest.java
@@ -23,64 +23,33 @@
import com.android.settings.R;
import com.android.settings.core.FeatureFlags;
-import com.android.settings.testutils.shadow.ShadowAuthenticationHelper;
-import org.junit.After;
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)
-@Config(shadows = {ShadowAuthenticationHelper.class})
public class TopLevelAccountEntryPreferenceControllerTest {
private TopLevelAccountEntryPreferenceController mController;
private Context mContext;
- private String[] LABELS;
- private String[] TYPES;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mController = new TopLevelAccountEntryPreferenceController(mContext, "test_key");
- LABELS = ShadowAuthenticationHelper.getLabels();
- TYPES = ShadowAuthenticationHelper.getTypes();
FeatureFlagUtils.setEnabled(mContext, FeatureFlags.SILKY_HOME, false);
}
- @After
- public void tearDown() {
- ShadowAuthenticationHelper.reset();
- }
-
- @Test
- public void updateSummary_hasAccount_shouldDisplayUpTo3AccountTypes() {
- assertThat(mController.getSummary())
- .isEqualTo(LABELS[0] + ", " + LABELS[1] + ", and " + LABELS[2]);
- }
-
@Test
public void updateSummary_noAccount_shouldDisplayDefaultSummary() {
- ShadowAuthenticationHelper.setEnabledAccount(null);
-
assertThat(mController.getSummary()).isEqualTo(
mContext.getText(R.string.account_dashboard_default_summary));
}
@Test
- public void updateSummary_noAccountTypeLabel_shouldNotDisplayNullEntry() {
- final String[] enabledAccounts = {TYPES[0], "unlabeled_account_type", TYPES[1]};
- ShadowAuthenticationHelper.setEnabledAccount(enabledAccounts);
-
-
- // should only show the 2 accounts with labels
- assertThat(mController.getSummary()).isEqualTo(LABELS[0] + " and " + LABELS[1]);
- }
-
- @Test
public void getSummary_silkyHomeEnabled_shouldBeNull() {
FeatureFlagUtils.setEnabled(mContext, FeatureFlags.SILKY_HOME, true);
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppOpenByDefaultPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppOpenByDefaultPreferenceControllerTest.java
index 849f2ac..1073256 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppOpenByDefaultPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppOpenByDefaultPreferenceControllerTest.java
@@ -37,7 +37,7 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settings.applications.AppLaunchSettings;
+import com.android.settings.applications.intentpicker.AppLaunchSettings;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
diff --git a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
index c8891e5..8e03d68 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
@@ -62,6 +62,9 @@
private static final int BATTERY_LEVEL_RIGHT = 45;
private static final int LOW_BATTERY_LEVEL = 15;
private static final int CASE_LOW_BATTERY_LEVEL = 19;
+ private static final int LOW_BATTERY_LEVEL_THRESHOLD = 15;
+ private static final int BATTERY_LEVEL_5 = 5;
+ private static final int BATTERY_LEVEL_50 = 50;
private static final String ICON_URI = "content://test.provider/icon.png";
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
@@ -202,6 +205,70 @@
}
@Test
+ public void refresh_underLowBatteryThreshold_showAlertIcon() {
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
+ BluetoothDevice.DEVICE_TYPE_WATCH.getBytes());
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_MAIN_BATTERY)).thenReturn(
+ String.valueOf(BATTERY_LEVEL_5).getBytes());
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD)).thenReturn(
+ String.valueOf(LOW_BATTERY_LEVEL_THRESHOLD).getBytes());
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_MAIN_CHARGING)).thenReturn(
+ String.valueOf(false).getBytes());
+ when(mCachedDevice.isConnected()).thenReturn(true);
+
+ mController.refresh();
+
+ assertBatteryIcon(mLayoutPreference.findViewById(R.id.layout_middle),
+ R.drawable.ic_battery_alert_24dp);
+ }
+
+ @Test
+ public void refresh_underLowBatteryThresholdInCharging_showAlertIcon() {
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
+ BluetoothDevice.DEVICE_TYPE_WATCH.getBytes());
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_MAIN_BATTERY)).thenReturn(
+ String.valueOf(BATTERY_LEVEL_5).getBytes());
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD)).thenReturn(
+ String.valueOf(LOW_BATTERY_LEVEL_THRESHOLD).getBytes());
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_MAIN_CHARGING)).thenReturn(
+ String.valueOf(true).getBytes());
+ when(mCachedDevice.isConnected()).thenReturn(true);
+
+ mController.refresh();
+
+ assertBatteryIcon(mLayoutPreference.findViewById(R.id.layout_middle), /* resId= */-1);
+ }
+
+ @Test
+ public void refresh_aboveLowBatteryThreshold_noAlertIcon() {
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
+ BluetoothDevice.DEVICE_TYPE_WATCH.getBytes());
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_MAIN_BATTERY)).thenReturn(
+ String.valueOf(BATTERY_LEVEL_50).getBytes());
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD)).thenReturn(
+ String.valueOf(LOW_BATTERY_LEVEL_THRESHOLD).getBytes());
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_MAIN_CHARGING)).thenReturn(
+ String.valueOf(false).getBytes());
+ when(mCachedDevice.isConnected()).thenReturn(true);
+
+ mController.refresh();
+
+ assertBatteryIcon(mLayoutPreference.findViewById(R.id.layout_middle), /* resId= */-1);
+ }
+
+ @Test
public void refresh_withLowBatteryAndUncharged_showAlertIcon() {
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
diff --git a/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java
index 68b2990..1262b50 100644
--- a/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.app.time.Capabilities;
@@ -36,10 +37,13 @@
import android.os.UserHandle;
import com.android.settings.R;
+import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -53,6 +57,10 @@
private LocationManager mLocationManager;
private Context mContext;
private LocationTimeZoneDetectionPreferenceController mController;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private InstrumentedPreferenceFragment mFragment;
+ @Mock
+ private Lifecycle mLifecycle;
@Before
public void setUp() {
@@ -60,11 +68,14 @@
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager);
when(mContext.getSystemService(LocationManager.class)).thenReturn(mLocationManager);
- mController = new LocationTimeZoneDetectionPreferenceController(mContext, "key");
+ mController = new LocationTimeZoneDetectionPreferenceController(mContext);
+ mController.setFragment(mFragment);
}
@Test
- public void setChecked_withTrue_shouldUpdateSetting() {
+ public void setChecked_withTrue_shouldUpdateSetting_whenLocationIsEnabled() {
+ when(mLocationManager.isLocationEnabled()).thenReturn(true);
+
// Simulate the UI being clicked.
mController.setChecked(true);
@@ -76,6 +87,17 @@
}
@Test
+ public void setChecked_withTrue_shouldDoNothing_whenLocationIsDisabled() {
+ when(mLocationManager.isLocationEnabled()).thenReturn(false);
+
+ // Simulate the UI being clicked.
+ mController.setChecked(true);
+
+ // Verify the TimeManager was not called.
+ verifyZeroInteractions(mTimeManager);
+ }
+
+ @Test
public void setChecked_withFalse_shouldUpdateSetting() {
// Simulate the UI being clicked.
mController.setChecked(false);
diff --git a/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java
index 15f4eb9..c9b13e27 100644
--- a/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java
@@ -91,4 +91,27 @@
verify(mPreference).setDisabledByAdmin(eq(new RestrictedLockUtils.EnforcedAdmin(
TEST_COMPONENT_NAME, null, UserHandle.SYSTEM)));
}
+
+ @Test
+ public void onDeveloperOptionsSwitchEnabled_usbEnabled_shouldNotDisablePreference() {
+ when(mDevicePolicyManager.isUsbDataSignalingEnabledForUser(
+ UserHandle.myUserId())).thenReturn(true);
+ when(mDevicePolicyManager.getProfileOwner()).thenReturn(TEST_COMPONENT_NAME);
+
+ mController.onDeveloperOptionsSwitchEnabled();
+
+ verify(mPreference).setDisabledByAdmin(null);
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchEnabled_usbDisabled_shouldDisablePreference() {
+ when(mDevicePolicyManager.isUsbDataSignalingEnabledForUser(
+ UserHandle.myUserId())).thenReturn(false);
+ when(mDevicePolicyManager.getProfileOwner()).thenReturn(TEST_COMPONENT_NAME);
+
+ mController.onDeveloperOptionsSwitchEnabled();
+
+ verify(mPreference).setDisabledByAdmin(eq(new RestrictedLockUtils.EnforcedAdmin(
+ TEST_COMPONENT_NAME, null, UserHandle.SYSTEM)));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/development/UsbAudioRoutingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/UsbAudioRoutingPreferenceControllerTest.java
index 1d45c1b..69d2c99 100644
--- a/tests/robotests/src/com/android/settings/development/UsbAudioRoutingPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/UsbAudioRoutingPreferenceControllerTest.java
@@ -147,4 +147,27 @@
verify(mPreference).setEnabled(false);
verify(mPreference).setChecked(false);
}
+
+ @Test
+ public void onDeveloperOptionsSwitchEnabled_usbEnabled_shouldNotDisablePreference() {
+ when(mDevicePolicyManager.isUsbDataSignalingEnabledForUser(
+ UserHandle.myUserId())).thenReturn(true);
+ when(mDevicePolicyManager.getProfileOwner()).thenReturn(TEST_COMPONENT_NAME);
+
+ mController.onDeveloperOptionsSwitchEnabled();
+
+ verify(mPreference).setDisabledByAdmin(null);
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchEnabled_usbDisabled_shouldDisablePreference() {
+ when(mDevicePolicyManager.isUsbDataSignalingEnabledForUser(
+ UserHandle.myUserId())).thenReturn(false);
+ when(mDevicePolicyManager.getProfileOwner()).thenReturn(TEST_COMPONENT_NAME);
+
+ mController.onDeveloperOptionsSwitchEnabled();
+
+ verify(mPreference).setDisabledByAdmin(eq(new RestrictedLockUtils.EnforcedAdmin(
+ TEST_COMPONENT_NAME, null, UserHandle.SYSTEM)));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageItemPreferenceTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageItemPreferenceTest.java
index 06194b4..5795157 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageItemPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/StorageItemPreferenceTest.java
@@ -69,4 +69,11 @@
assertThat(progressBar).isNotNull();
assertThat(progressBar.getProgress()).isEqualTo(10);
}
+
+ @Test
+ public void getStorageSize_setStorageSize_getCorrectStorageSize() {
+ mPreference.setStorageSize(MEGABYTE_IN_BYTES, MEGABYTE_IN_BYTES * 10);
+
+ assertThat(mPreference.getStorageSize()).isEqualTo(MEGABYTE_IN_BYTES);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java
index 997c35e..60eab12 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java
@@ -181,8 +181,8 @@
mController.copy();
- final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
- CLIPBOARD_SERVICE);
+ final ClipboardManager clipboard = mContext.getSystemService(
+ ClipboardManager.class);
final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
assertThat(data.toString()).isEqualTo(meid);
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index 5e49aa0..6f9c451 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -43,7 +43,6 @@
import androidx.fragment.app.FragmentTransaction;
import androidx.preference.PreferenceScreen;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
@@ -51,10 +50,8 @@
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.deviceinfo.PrivateVolumeSettings;
import com.android.settings.deviceinfo.StorageItemPreference;
-import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.applications.StorageStatsSource;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
import org.junit.Before;
@@ -84,8 +81,7 @@
private FragmentTransaction mFragmentTransaction;
private StorageItemPreferenceController mController;
private StorageItemPreference mPreference;
- private FakeFeatureFactory mFakeFeatureFactory;
- private MetricsFeatureProvider mMetricsFeatureProvider;
+ private PreferenceScreen mPreferenceScreen;
@Before
public void setUp() {
@@ -94,8 +90,6 @@
when(mFragment.getFragmentManager()).thenReturn(mFragmentManager);
when(mFragmentManager.beginTransaction()).thenReturn(mFragmentTransaction);
mContext = spy(RuntimeEnvironment.application.getApplicationContext());
- mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
- mMetricsFeatureProvider = mFakeFeatureFactory.getMetricsFeatureProvider();
mVolume = spy(new VolumeInfo("id", 0, null, "id"));
// Note: null is passed as the Lifecycle because we are handling it outside of the normal
// Settings fragment lifecycle for test purposes.
@@ -105,6 +99,47 @@
// Inflate the preference and the widget.
final LayoutInflater inflater = LayoutInflater.from(mContext);
inflater.inflate(mPreference.getLayoutResource(), new LinearLayout(mContext), false);
+
+ mPreferenceScreen = getPreferenceScreen();
+ }
+
+ private PreferenceScreen getPreferenceScreen() {
+ final StorageItemPreference images = spy(new StorageItemPreference(mContext));
+ images.setIcon(R.drawable.ic_photo_library);
+ final StorageItemPreference videos = spy(new StorageItemPreference(mContext));
+ videos.setIcon(R.drawable.ic_local_movies);
+ final StorageItemPreference audios = spy(new StorageItemPreference(mContext));
+ audios.setIcon(R.drawable.ic_media_stream);
+ final StorageItemPreference apps = spy(new StorageItemPreference(mContext));
+ apps.setIcon(R.drawable.ic_storage_apps);
+ final StorageItemPreference games = spy(new StorageItemPreference(mContext));
+ games.setIcon(R.drawable.ic_videogame_vd_theme_24);
+ final StorageItemPreference documentsAndOther = spy(new StorageItemPreference(mContext));
+ documentsAndOther.setIcon(R.drawable.ic_folder_vd_theme_24);
+ final StorageItemPreference system = spy(new StorageItemPreference(mContext));
+ system.setIcon(R.drawable.ic_system_update);
+ final StorageItemPreference trash = spy(new StorageItemPreference(mContext));
+ trash.setIcon(R.drawable.ic_trash_can);
+
+ final PreferenceScreen screen = mock(PreferenceScreen.class);
+ when(screen.findPreference(eq(StorageItemPreferenceController.IMAGES_KEY)))
+ .thenReturn(images);
+ when(screen.findPreference(eq(StorageItemPreferenceController.VIDEOS_KEY)))
+ .thenReturn(videos);
+ when(screen.findPreference(eq(StorageItemPreferenceController.AUDIOS_KEY)))
+ .thenReturn(audios);
+ when(screen.findPreference(eq(StorageItemPreferenceController.APPS_KEY)))
+ .thenReturn(apps);
+ when(screen.findPreference(eq(StorageItemPreferenceController.GAMES_KEY)))
+ .thenReturn(games);
+ when(screen.findPreference(eq(StorageItemPreferenceController.DOCUMENTS_AND_OTHER_KEY)))
+ .thenReturn(documentsAndOther);
+ when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
+ .thenReturn(system);
+ when(screen.findPreference(eq(StorageItemPreferenceController.TRASH_KEY)))
+ .thenReturn(trash);
+
+ return screen;
}
@Test
@@ -114,8 +149,8 @@
}
@Test
- public void testClickPhotos() {
- mPreference.setKey("pref_photos_videos");
+ public void launchImagesIntent_resolveActionViewNull_settingsIntent() {
+ mPreference.setKey(StorageItemPreferenceController.IMAGES_KEY);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -132,8 +167,8 @@
}
@Test
- public void testClickAudio() {
- mPreference.setKey("pref_music_audio");
+ public void launchAudiosIntent_resolveActionViewNull_settingsIntent() {
+ mPreference.setKey(StorageItemPreferenceController.AUDIOS_KEY);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -151,16 +186,24 @@
}
@Test
- public void handlePreferenceTreeClick_tappingAudioWhileUninitializedDoesntCrash() {
+ public void setVolume_nullVolume_hidePreferences() {
+ mController.displayPreference(mPreferenceScreen);
+
mController.setVolume(null);
- mPreference.setKey("pref_music_audio");
- mController.handlePreferenceTreeClick(mPreference);
+ assertThat(mController.mImagesPreference.isVisible()).isFalse();
+ assertThat(mController.mVideosPreference.isVisible()).isFalse();
+ assertThat(mController.mAudiosPreference.isVisible()).isFalse();
+ assertThat(mController.mAppsPreference.isVisible()).isFalse();
+ assertThat(mController.mGamesPreference.isVisible()).isFalse();
+ assertThat(mController.mDocumentsAndOtherPreference.isVisible()).isFalse();
+ assertThat(mController.mSystemPreference.isVisible()).isFalse();
+ assertThat(mController.mTrashPreference.isVisible()).isFalse();
}
@Test
- public void testClickApps() {
- mPreference.setKey("pref_other_apps");
+ public void launchAppsIntent_forPersonal_settingsIntent() {
+ mPreference.setKey(StorageItemPreferenceController.APPS_KEY);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -177,9 +220,9 @@
}
@Test
- public void testClickAppsForWork() {
+ public void launchAppsIntent_forWork_settingsIntent() {
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp, true);
- mPreference.setKey("pref_other_apps");
+ mPreference.setKey(StorageItemPreferenceController.APPS_KEY);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -204,18 +247,10 @@
}
@Test
- public void handlePreferenceTreeClick_tappingAppsWhileUninitializedDoesntCrash() {
- mController.setVolume(null);
-
- mPreference.setKey("pref_other_apps");
- mController.handlePreferenceTreeClick(mPreference);
- }
-
- @Test
- public void testClickFiles() {
+ public void launchDocumentsAndOtherIntent_resolveActionViewNull_settingsIntent() {
when(mSvp.findEmulatedForPrivate(nullable(VolumeInfo.class))).thenReturn(mVolume);
when(mVolume.buildBrowseIntent()).thenReturn(new Intent());
- mPreference.setKey("pref_files");
+ mPreference.setKey(StorageItemPreferenceController.DOCUMENTS_AND_OTHER_KEY);
assertThat(mController.handlePreferenceTreeClick(mPreference))
.isTrue();
@@ -227,13 +262,11 @@
Intent browseIntent = mVolume.buildBrowseIntent();
assertThat(intent.getAction()).isEqualTo(browseIntent.getAction());
assertThat(intent.getData()).isEqualTo(browseIntent.getData());
- verify(mMetricsFeatureProvider, times(1))
- .action(nullable(Context.class), eq(MetricsEvent.STORAGE_FILES));
}
@Test
- public void testClickGames() {
- mPreference.setKey("pref_games");
+ public void launchGamesIntent_settingsIntent() {
+ mPreference.setKey(StorageItemPreferenceController.GAMES_KEY);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -250,8 +283,8 @@
}
@Test
- public void testClickMovies() {
- mPreference.setKey("pref_movies");
+ public void launchVideosIntent_resolveActionViewNull_settingsIntent() {
+ mPreference.setKey(StorageItemPreferenceController.VIDEOS_KEY);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -269,7 +302,7 @@
@Test
public void testClickSystem() {
- mPreference.setKey("pref_system");
+ mPreference.setKey(StorageItemPreferenceController.SYSTEM_KEY);
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
verify(mFragment.getFragmentManager().beginTransaction())
@@ -279,29 +312,7 @@
@Test
@Config(shadows = ShadowUserManager.class)
public void testMeasurementCompletedUpdatesPreferences() {
- final StorageItemPreference audio = new StorageItemPreference(mContext);
- final StorageItemPreference image = new StorageItemPreference(mContext);
- final StorageItemPreference games = new StorageItemPreference(mContext);
- final StorageItemPreference movies = new StorageItemPreference(mContext);
- final StorageItemPreference apps = new StorageItemPreference(mContext);
- final StorageItemPreference system = new StorageItemPreference(mContext);
- final StorageItemPreference files = new StorageItemPreference(mContext);
- final PreferenceScreen screen = mock(PreferenceScreen.class);
- when(screen.findPreference(eq(StorageItemPreferenceController.GAME_KEY)))
- .thenReturn(games);
- when(screen.findPreference(eq(StorageItemPreferenceController.AUDIO_KEY)))
- .thenReturn(audio);
- when(screen.findPreference(eq(StorageItemPreferenceController.PHOTO_KEY)))
- .thenReturn(image);
- when(screen.findPreference(eq(StorageItemPreferenceController.FILES_KEY)))
- .thenReturn(files);
- when(screen.findPreference(eq(StorageItemPreferenceController.MOVIES_KEY)))
- .thenReturn(movies);
- when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
- .thenReturn(system);
- when(screen.findPreference(eq(StorageItemPreferenceController.OTHER_APPS_KEY)))
- .thenReturn(apps);
- mController.displayPreference(screen);
+ mController.displayPreference(mPreferenceScreen);
mController.setUsedSize(MEGABYTE_IN_BYTES * 970); // There should 870MB attributed.
final StorageAsyncLoader.AppsStorageResult result =
@@ -321,211 +332,90 @@
results.put(0, result);
mController.onLoadFinished(results, 0);
- assertThat(audio.getSummary().toString()).isEqualTo("0.14 GB");
- assertThat(image.getSummary().toString()).isEqualTo("0.35 GB");
- assertThat(games.getSummary().toString()).isEqualTo("0.08 GB");
- assertThat(movies.getSummary().toString()).isEqualTo("0.16 GB");
- assertThat(apps.getSummary().toString()).isEqualTo("0.09 GB");
- assertThat(files.getSummary().toString()).isEqualTo("0.05 GB");
+ assertThat(mController.mImagesPreference.getSummary().toString()).isEqualTo("0.35 GB");
+ assertThat(mController.mVideosPreference.getSummary().toString()).isEqualTo("0.16 GB");
+ assertThat(mController.mAudiosPreference.getSummary().toString()).isEqualTo("0.14 GB");
+ assertThat(mController.mAppsPreference.getSummary().toString()).isEqualTo("0.09 GB");
+ assertThat(mController.mGamesPreference.getSummary().toString()).isEqualTo("0.08 GB");
+ assertThat(mController.mDocumentsAndOtherPreference.getSummary().toString())
+ .isEqualTo("0.05 GB");
}
@Test
public void settingUserIdAppliesNewIcons() {
- final StorageItemPreference audio = spy(new StorageItemPreference(mContext));
- audio.setIcon(R.drawable.ic_media_stream);
- final StorageItemPreference video = spy(new StorageItemPreference(mContext));
- video.setIcon(R.drawable.ic_local_movies);
- final StorageItemPreference image = spy(new StorageItemPreference(mContext));
- image.setIcon(R.drawable.ic_photo_library);
- final StorageItemPreference games = spy(new StorageItemPreference(mContext));
- games.setIcon(R.drawable.ic_videogame_vd_theme_24);
- final StorageItemPreference apps = spy(new StorageItemPreference(mContext));
- apps.setIcon(R.drawable.ic_storage_apps);
- final StorageItemPreference system = spy(new StorageItemPreference(mContext));
- system.setIcon(R.drawable.ic_system_update);
- final StorageItemPreference files = spy(new StorageItemPreference(mContext));
- files.setIcon(R.drawable.ic_folder_vd_theme_24);
- final PreferenceScreen screen = mock(PreferenceScreen.class);
- when(screen.findPreference(eq(StorageItemPreferenceController.GAME_KEY)))
- .thenReturn(games);
- when(screen.findPreference(eq(StorageItemPreferenceController.AUDIO_KEY)))
- .thenReturn(audio);
- when(screen.findPreference(eq(StorageItemPreferenceController.PHOTO_KEY)))
- .thenReturn(image);
- when(screen.findPreference(eq(StorageItemPreferenceController.FILES_KEY)))
- .thenReturn(files);
- when(screen.findPreference(eq(StorageItemPreferenceController.MOVIES_KEY)))
- .thenReturn(video);
- when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
- .thenReturn(system);
- when(screen.findPreference(eq(StorageItemPreferenceController.OTHER_APPS_KEY)))
- .thenReturn(apps);
- mController.displayPreference(screen);
+ mController.displayPreference(mPreferenceScreen);
mController.setUserId(new UserHandle(10));
- verify(audio, times(2)).setIcon(nullable(Drawable.class));
- verify(video, times(2)).setIcon(nullable(Drawable.class));
- verify(image, times(2)).setIcon(nullable(Drawable.class));
- verify(games, times(2)).setIcon(nullable(Drawable.class));
- verify(apps, times(2)).setIcon(nullable(Drawable.class));
- verify(system, times(2)).setIcon(nullable(Drawable.class));
- verify(files, times(2)).setIcon(nullable(Drawable.class));
+ verify(mController.mImagesPreference, times(2)).setIcon(nullable(Drawable.class));
+ verify(mController.mVideosPreference, times(2)).setIcon(nullable(Drawable.class));
+ verify(mController.mAudiosPreference, times(2)).setIcon(nullable(Drawable.class));
+ verify(mController.mAppsPreference, times(2)).setIcon(nullable(Drawable.class));
+ verify(mController.mGamesPreference, times(2)).setIcon(nullable(Drawable.class));
+ verify(mController.mDocumentsAndOtherPreference, times(2))
+ .setIcon(nullable(Drawable.class));
+ verify(mController.mSystemPreference, times(2)).setIcon(nullable(Drawable.class));
+ verify(mController.mTrashPreference, times(2)).setIcon(nullable(Drawable.class));
}
@Test
public void displayPreference_dontHideFilePreferenceWhenEmulatedInternalStorageUsed() {
- final StorageItemPreference audio = new StorageItemPreference(mContext);
- final StorageItemPreference image = new StorageItemPreference(mContext);
- final StorageItemPreference games = new StorageItemPreference(mContext);
- final StorageItemPreference apps = new StorageItemPreference(mContext);
- final StorageItemPreference system = new StorageItemPreference(mContext);
- final StorageItemPreference files = new StorageItemPreference(mContext);
- final PreferenceScreen screen = mock(PreferenceScreen.class);
- when(screen.findPreference(eq(StorageItemPreferenceController.GAME_KEY)))
- .thenReturn(games);
- when(screen.findPreference(eq(StorageItemPreferenceController.AUDIO_KEY)))
- .thenReturn(audio);
- when(screen.findPreference(eq(StorageItemPreferenceController.PHOTO_KEY)))
- .thenReturn(image);
- when(screen.findPreference(eq(StorageItemPreferenceController.FILES_KEY)))
- .thenReturn(files);
- when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
- .thenReturn(system);
- when(screen.findPreference(eq(StorageItemPreferenceController.OTHER_APPS_KEY)))
- .thenReturn(apps);
-
when(mSvp.findEmulatedForPrivate(nullable(VolumeInfo.class))).thenReturn(mVolume);
+ when(mVolume.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
+ when(mVolume.getState()).thenReturn(VolumeInfo.STATE_MOUNTED);
when(mVolume.isMountedReadable()).thenReturn(true);
- mController.displayPreference(screen);
+ mController.displayPreference(mPreferenceScreen);
- verify(screen, times(0)).removePreference(files);
+ assertThat(mController.mDocumentsAndOtherPreference.isVisible()).isTrue();
}
@Test
public void displayPreference_hideFilePreferenceWhenEmulatedStorageUnreadable() {
- final StorageItemPreference audio = new StorageItemPreference(mContext);
- final StorageItemPreference image = new StorageItemPreference(mContext);
- final StorageItemPreference games = new StorageItemPreference(mContext);
- final StorageItemPreference apps = new StorageItemPreference(mContext);
- final StorageItemPreference system = new StorageItemPreference(mContext);
- final StorageItemPreference files = new StorageItemPreference(mContext);
- final PreferenceScreen screen = mock(PreferenceScreen.class);
- when(screen.findPreference(eq(StorageItemPreferenceController.GAME_KEY)))
- .thenReturn(games);
- when(screen.findPreference(eq(StorageItemPreferenceController.AUDIO_KEY)))
- .thenReturn(audio);
- when(screen.findPreference(eq(StorageItemPreferenceController.PHOTO_KEY)))
- .thenReturn(image);
- when(screen.findPreference(eq(StorageItemPreferenceController.FILES_KEY)))
- .thenReturn(files);
- when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
- .thenReturn(system);
- when(screen.findPreference(eq(StorageItemPreferenceController.OTHER_APPS_KEY)))
- .thenReturn(apps);
-
when(mSvp.findEmulatedForPrivate(nullable(VolumeInfo.class))).thenReturn(mVolume);
when(mVolume.isMountedReadable()).thenReturn(false);
- mController.displayPreference(screen);
+ mController.displayPreference(mPreferenceScreen);
- verify(screen).removePreference(files);
+ assertThat(mController.mDocumentsAndOtherPreference.isVisible()).isFalse();
}
@Test
- public void displayPreference_hideFilePreferenceWhenNoEmulatedInternalStorage() {
- final StorageItemPreference audio = new StorageItemPreference(mContext);
- final StorageItemPreference image = new StorageItemPreference(mContext);
- final StorageItemPreference games = new StorageItemPreference(mContext);
- final StorageItemPreference apps = new StorageItemPreference(mContext);
- final StorageItemPreference system = new StorageItemPreference(mContext);
- final StorageItemPreference files = new StorageItemPreference(mContext);
- final PreferenceScreen screen = mock(PreferenceScreen.class);
- when(screen.findPreference(eq(StorageItemPreferenceController.GAME_KEY)))
- .thenReturn(games);
- when(screen.findPreference(eq(StorageItemPreferenceController.AUDIO_KEY)))
- .thenReturn(audio);
- when(screen.findPreference(eq(StorageItemPreferenceController.PHOTO_KEY)))
- .thenReturn(image);
- when(screen.findPreference(eq(StorageItemPreferenceController.FILES_KEY)))
- .thenReturn(files);
- when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
- .thenReturn(system);
- when(screen.findPreference(eq(StorageItemPreferenceController.OTHER_APPS_KEY)))
- .thenReturn(apps);
-
+ public void displayPreference_noEmulatedInternalStorage_hidePreference() {
when(mSvp.findEmulatedForPrivate(nullable(VolumeInfo.class))).thenReturn(null);
- mController.displayPreference(screen);
+ mController.displayPreference(mPreferenceScreen);
- verify(screen).removePreference(files);
+ assertThat(mController.mDocumentsAndOtherPreference.isVisible()).isFalse();
}
@Test
- public void displayPreference_updateFilePreferenceToHideAfterSettingVolume() {
- final StorageItemPreference audio = new StorageItemPreference(mContext);
- final StorageItemPreference image = new StorageItemPreference(mContext);
- final StorageItemPreference games = new StorageItemPreference(mContext);
- final StorageItemPreference apps = new StorageItemPreference(mContext);
- final StorageItemPreference system = new StorageItemPreference(mContext);
- final StorageItemPreference files = new StorageItemPreference(mContext);
- final PreferenceScreen screen = mock(PreferenceScreen.class);
- when(screen.findPreference(eq(StorageItemPreferenceController.GAME_KEY)))
- .thenReturn(games);
- when(screen.findPreference(eq(StorageItemPreferenceController.AUDIO_KEY)))
- .thenReturn(audio);
- when(screen.findPreference(eq(StorageItemPreferenceController.PHOTO_KEY)))
- .thenReturn(image);
- when(screen.findPreference(eq(StorageItemPreferenceController.FILES_KEY)))
- .thenReturn(files);
- when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
- .thenReturn(system);
- when(screen.findPreference(eq(StorageItemPreferenceController.OTHER_APPS_KEY)))
- .thenReturn(apps);
-
+ public void setVolume_updateFilePreferenceToHideAfterSettingVolume_hidePreference() {
when(mSvp.findEmulatedForPrivate(nullable(VolumeInfo.class))).thenReturn(mVolume);
+ when(mVolume.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
+ when(mVolume.getState()).thenReturn(VolumeInfo.STATE_MOUNTED);
when(mVolume.isMountedReadable()).thenReturn(true);
- mController.displayPreference(screen);
+ mController.displayPreference(mPreferenceScreen);
when(mSvp.findEmulatedForPrivate(nullable(VolumeInfo.class))).thenReturn(null);
mController.setVolume(mVolume);
- verify(screen).removePreference(files);
+ assertThat(mController.mDocumentsAndOtherPreference.isVisible()).isFalse();
}
@Test
- public void displayPreference_updateFilePreferenceToShowAfterSettingVolume() {
- final StorageItemPreference audio = new StorageItemPreference(mContext);
- final StorageItemPreference image = new StorageItemPreference(mContext);
- final StorageItemPreference games = new StorageItemPreference(mContext);
- final StorageItemPreference apps = new StorageItemPreference(mContext);
- final StorageItemPreference system = new StorageItemPreference(mContext);
- final StorageItemPreference files = new StorageItemPreference(mContext);
- final PreferenceScreen screen = mock(PreferenceScreen.class);
- when(screen.findPreference(eq(StorageItemPreferenceController.GAME_KEY)))
- .thenReturn(games);
- when(screen.findPreference(eq(StorageItemPreferenceController.AUDIO_KEY)))
- .thenReturn(audio);
- when(screen.findPreference(eq(StorageItemPreferenceController.PHOTO_KEY)))
- .thenReturn(image);
- when(screen.findPreference(eq(StorageItemPreferenceController.FILES_KEY)))
- .thenReturn(files);
- when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
- .thenReturn(system);
- when(screen.findPreference(eq(StorageItemPreferenceController.OTHER_APPS_KEY)))
- .thenReturn(apps);
-
+ public void setVolume_updateFilePreferenceToShowAfterSettingVolume_showPreference() {
// This will hide it initially.
- mController.displayPreference(screen);
-
+ mController.displayPreference(mPreferenceScreen);
when(mSvp.findEmulatedForPrivate(nullable(VolumeInfo.class))).thenReturn(mVolume);
+ when(mVolume.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
+ when(mVolume.getState()).thenReturn(VolumeInfo.STATE_MOUNTED);
when(mVolume.isMountedReadable()).thenReturn(true);
// And we bring it back.
mController.setVolume(mVolume);
- verify(screen).addPreference(files);
+ assertThat(mController.mDocumentsAndOtherPreference.isVisible()).isTrue();
}
}
diff --git a/tests/robotests/src/com/android/settings/enterprise/BasePrivacySettingsPreferenceTest.java b/tests/robotests/src/com/android/settings/enterprise/BasePrivacySettingsPreferenceTest.java
new file mode 100644
index 0000000..fdf005d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/enterprise/BasePrivacySettingsPreferenceTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2021 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.enterprise;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.widget.PreferenceCategoryController;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public abstract class BasePrivacySettingsPreferenceTest {
+
+ protected Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = ApplicationProvider.getApplicationContext();
+ }
+
+ protected static void verifyEnterpriseSearchIndexableResources(
+ List<SearchIndexableResource> searchIndexableResources) {
+ assertThat(searchIndexableResources).isNotEmpty();
+ assertThat(searchIndexableResources.size()).isEqualTo(1);
+ assertThat(searchIndexableResources.get(0).xmlResId)
+ .isEqualTo(R.xml.enterprise_privacy_settings);
+ }
+
+ protected static void verifyEnterprisePreferenceControllers(
+ List<AbstractPreferenceController> controllers) {
+ assertThat(controllers).isNotNull();
+ assertThat(controllers.size()).isEqualTo(17);
+ int position = 0;
+ assertThat(controllers.get(position++)).isInstanceOf(NetworkLogsPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(BugReportsPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ SecurityLogsPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ EnterpriseInstalledPackagesPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ AdminGrantedLocationPermissionsPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ AdminGrantedMicrophonePermissionPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ AdminGrantedCameraPermissionPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ EnterpriseSetDefaultAppsPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ AlwaysOnVpnCurrentUserPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ AlwaysOnVpnManagedProfilePreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(ImePreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ GlobalHttpProxyPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ CaCertsCurrentUserPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ CaCertsManagedProfilePreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ PreferenceCategoryController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ FailedPasswordWipeCurrentUserPreferenceController.class);
+ assertThat(controllers.get(position)).isInstanceOf(
+ FailedPasswordWipeManagedProfilePreferenceController.class);
+ }
+
+ protected static void verifyFinancedSearchIndexableResources(
+ List<SearchIndexableResource> searchIndexableResources) {
+ assertThat(searchIndexableResources).isNotEmpty();
+ assertThat(searchIndexableResources.size()).isEqualTo(1);
+ assertThat(searchIndexableResources.get(0).xmlResId)
+ .isEqualTo(R.xml.financed_privacy_settings);
+ }
+
+ protected static void verifyFinancedPreferenceControllers(
+ List<AbstractPreferenceController> controllers) {
+ assertThat(controllers).isNotNull();
+ assertThat(controllers.size()).isEqualTo(6);
+ int position = 0;
+ assertThat(controllers.get(position++)).isInstanceOf(NetworkLogsPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(BugReportsPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ SecurityLogsPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ EnterpriseInstalledPackagesPreferenceController.class);
+ assertThat(controllers.get(position++)).isInstanceOf(
+ PreferenceCategoryController.class);
+ assertThat(controllers.get(position)).isInstanceOf(
+ FailedPasswordWipeCurrentUserPreferenceController.class);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceControllerTest.java
index 6858dd3..8052357 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyPreferenceControllerTest.java
@@ -16,10 +16,15 @@
package com.android.settings.enterprise;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
import android.content.Context;
import androidx.preference.Preference;
@@ -42,9 +47,14 @@
private static final String MANAGED_WITH_NAME = "managed by Foo, Inc.";
private static final String MANAGING_ORGANIZATION = "Foo, Inc.";
private static final String KEY_ENTERPRISE_PRIVACY = "enterprise_privacy";
+ private static final String FINANCED_PREFERENCE_TITLE = "Financed device info";
+ private static final ComponentName DEVICE_OWNER_COMPONENT =
+ new ComponentName("com.android.foo", "bar");
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
+ @Mock
+ private DevicePolicyManager mDevicePolicyManager;
private FakeFeatureFactory mFeatureFactory;
private EnterprisePrivacyPreferenceController mController;
@@ -54,6 +64,14 @@
MockitoAnnotations.initMocks(this);
mFeatureFactory = FakeFeatureFactory.setupForTest();
mController = new EnterprisePrivacyPreferenceController(mContext);
+
+ when((Object) mContext.getSystemService(DevicePolicyManager.class))
+ .thenReturn(mDevicePolicyManager);
+ when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
+ when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser())
+ .thenReturn(DEVICE_OWNER_COMPONENT);
+ when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
+ .thenReturn(DEVICE_OWNER_TYPE_DEFAULT);
}
@Test
@@ -77,6 +95,25 @@
}
@Test
+ public void testUpdateState_verifyPreferenceTitleIsUpdatedForFinancedDevice() {
+ final Preference preference = new Preference(mContext, null, 0, 0);
+ when(mContext.getResources().getString(
+ R.string.enterprise_privacy_settings_summary_with_name, MANAGING_ORGANIZATION))
+ .thenReturn(MANAGED_WITH_NAME);
+ when(mContext.getString(R.string.financed_privacy_settings))
+ .thenReturn(FINANCED_PREFERENCE_TITLE);
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider.getDeviceOwnerOrganizationName())
+ .thenReturn(MANAGING_ORGANIZATION);
+ when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
+ .thenReturn(DEVICE_OWNER_TYPE_FINANCED);
+
+ mController.updateState(preference);
+
+ assertThat(preference.getTitle()).isEqualTo(FINANCED_PREFERENCE_TITLE);
+ assertThat(preference.getSummary()).isEqualTo(MANAGED_WITH_NAME);
+ }
+
+ @Test
public void testIsAvailable() {
when(mFeatureFactory.enterprisePrivacyFeatureProvider.hasDeviceOwner()).thenReturn(false);
assertThat(mController.isAvailable()).isFalse();
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
index 2d4ba62..eb70749 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
@@ -16,47 +16,70 @@
package com.android.settings.enterprise;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import android.content.Context;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.provider.SearchIndexableResource;
+
+import androidx.test.core.app.ApplicationProvider;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.widget.PreferenceCategoryController;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.drawer.CategoryKey;
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.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
+import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
-public class EnterprisePrivacySettingsTest {
+public class EnterprisePrivacySettingsTest extends BasePrivacySettingsPreferenceTest {
+ private static final ComponentName DEVICE_OWNER_COMPONENT =
+ new ComponentName("com.android.foo", "bar");
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Context mContext;
+ @Mock
+ private DevicePolicyManager mDevicePolicyManager;
+ @Mock
+ private PrivacySettingsPreference mPrivacySettingsPreference;
private FakeFeatureFactory mFeatureFactory;
private EnterprisePrivacySettings mSettings;
+ @Override
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ mContext = spy(ApplicationProvider.getApplicationContext());
mFeatureFactory = FakeFeatureFactory.setupForTest();
mSettings = new EnterprisePrivacySettings();
+ mSettings.mPrivacySettingsPreference = mPrivacySettingsPreference;
+
+ when(mContext.getSystemService(DevicePolicyManager.class)).thenReturn(mDevicePolicyManager);
+ when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
+ when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser())
+ .thenReturn(DEVICE_OWNER_COMPONENT);
+ when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
+ .thenReturn(DEVICE_OWNER_TYPE_DEFAULT);
}
@Test
public void verifyConstants() {
+ when(mPrivacySettingsPreference.getPreferenceScreenResId())
+ .thenReturn(R.xml.enterprise_privacy_settings);
+
assertThat(mSettings.getMetricsCategory())
.isEqualTo(MetricsEvent.ENTERPRISE_PRIVACY_SETTINGS);
assertThat(mSettings.getLogTag()).isEqualTo("EnterprisePrivacySettings");
@@ -76,6 +99,7 @@
@Test
public void isPageEnabled_noDeviceOwner_shouldReturnFalse() {
+ when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false);
when(mFeatureFactory.enterprisePrivacyFeatureProvider.hasDeviceOwner())
.thenReturn(false);
@@ -85,53 +109,35 @@
@Test
public void getPreferenceControllers() {
- final List<AbstractPreferenceController> controllers =
- mSettings.createPreferenceControllers(RuntimeEnvironment.application);
- verifyPreferenceControllers(controllers);
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new NetworkLogsPreferenceController(mContext));
+ when(mPrivacySettingsPreference.createPreferenceControllers(anyBoolean()))
+ .thenReturn(controllers);
+
+ final List<AbstractPreferenceController> privacyControllers =
+ mSettings.createPreferenceControllers(mContext);
+
+ assertThat(privacyControllers).isNotNull();
+ assertThat(privacyControllers.size()).isEqualTo(1);
+ assertThat(controllers.get(0)).isInstanceOf(NetworkLogsPreferenceController.class);
}
@Test
- public void getSearchIndexProviderPreferenceControllers() {
+ public void
+ getSearchIndexProviderPreferenceControllers_returnsEnterpriseSearchIndexPreferenceControllers() {
final List<AbstractPreferenceController> controllers =
EnterprisePrivacySettings.SEARCH_INDEX_DATA_PROVIDER
- .getPreferenceControllers(RuntimeEnvironment.application);
- verifyPreferenceControllers(controllers);
+ .getPreferenceControllers(mContext);
+
+ verifyEnterprisePreferenceControllers(controllers);
}
- private void verifyPreferenceControllers(List<AbstractPreferenceController> controllers) {
- assertThat(controllers).isNotNull();
- assertThat(controllers.size()).isEqualTo(17);
- int position = 0;
- assertThat(controllers.get(position++)).isInstanceOf(NetworkLogsPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(BugReportsPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- SecurityLogsPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- EnterpriseInstalledPackagesPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- AdminGrantedLocationPermissionsPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- AdminGrantedMicrophonePermissionPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- AdminGrantedCameraPermissionPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- EnterpriseSetDefaultAppsPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- AlwaysOnVpnCurrentUserPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- AlwaysOnVpnManagedProfilePreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(ImePreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- GlobalHttpProxyPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- CaCertsCurrentUserPreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- CaCertsManagedProfilePreferenceController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- PreferenceCategoryController.class);
- assertThat(controllers.get(position++)).isInstanceOf(
- FailedPasswordWipeCurrentUserPreferenceController.class);
- assertThat(controllers.get(position)).isInstanceOf(
- FailedPasswordWipeManagedProfilePreferenceController.class);
+ @Test
+ public void getXmlResourcesToIndex_returnsEnterpriseXmlResources() {
+ final List<SearchIndexableResource> searchIndexableResources =
+ EnterprisePrivacySettings.SEARCH_INDEX_DATA_PROVIDER
+ .getXmlResourcesToIndex(mContext, true);
+
+ verifyEnterpriseSearchIndexableResources(searchIndexableResources);
}
}
diff --git a/tests/robotests/src/com/android/settings/enterprise/PrivacySettingsEnterprisePreferenceTest.java b/tests/robotests/src/com/android/settings/enterprise/PrivacySettingsEnterprisePreferenceTest.java
new file mode 100644
index 0000000..68e37fc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/enterprise/PrivacySettingsEnterprisePreferenceTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 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.enterprise;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class PrivacySettingsEnterprisePreferenceTest extends BasePrivacySettingsPreferenceTest {
+
+ private PrivacySettingsEnterprisePreference mPrivacySettingsEnterprisePreference;
+
+ @Override
+ @Before
+ public void setUp() {
+ super.setUp();
+ mPrivacySettingsEnterprisePreference = new PrivacySettingsEnterprisePreference(mContext);
+ }
+
+ @Test
+ public void getPreferenceScreenResId() {
+ assertThat(mPrivacySettingsEnterprisePreference.getPreferenceScreenResId())
+ .isEqualTo(R.xml.enterprise_privacy_settings);
+ }
+
+ @Test
+ public void getXmlResourcesToIndex() {
+ final List<SearchIndexableResource> searchIndexableResources =
+ mPrivacySettingsEnterprisePreference.getXmlResourcesToIndex();
+
+ verifyEnterpriseSearchIndexableResources(searchIndexableResources);
+ }
+
+ @Test
+ public void getPreferenceControllers() {
+ final List<AbstractPreferenceController> controllers =
+ mPrivacySettingsEnterprisePreference.createPreferenceControllers(true);
+
+ verifyEnterprisePreferenceControllers(controllers);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/enterprise/PrivacySettingsFinancedPreferenceTest.java b/tests/robotests/src/com/android/settings/enterprise/PrivacySettingsFinancedPreferenceTest.java
new file mode 100644
index 0000000..fe7b214
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/enterprise/PrivacySettingsFinancedPreferenceTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 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.enterprise;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class PrivacySettingsFinancedPreferenceTest extends BasePrivacySettingsPreferenceTest {
+
+ private PrivacySettingsFinancedPreference mPrivacySettingsFinancedPreference;
+
+ @Override
+ @Before
+ public void setUp() {
+ super.setUp();
+ mPrivacySettingsFinancedPreference = new PrivacySettingsFinancedPreference(mContext);
+ }
+
+ @Test
+ public void getPreferenceScreenResId() {
+ assertThat(mPrivacySettingsFinancedPreference.getPreferenceScreenResId())
+ .isEqualTo(R.xml.financed_privacy_settings);
+ }
+
+ @Test
+ public void getXmlResourcesToIndex() {
+ final List<SearchIndexableResource> searchIndexableResources =
+ mPrivacySettingsFinancedPreference.getXmlResourcesToIndex();
+
+ verifyFinancedSearchIndexableResources(searchIndexableResources);
+ }
+
+ @Test
+ public void getPreferenceControllers() {
+ final List<AbstractPreferenceController> controllers =
+ mPrivacySettingsFinancedPreference.createPreferenceControllers(true);
+
+ verifyFinancedPreferenceControllers(controllers);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
index 775ca40..744db8c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -277,7 +277,7 @@
@Test
public void testCalculateLastFullChargeTime() {
final long currentTimeMs = System.currentTimeMillis();
- when(mBatteryUsageStats.getStatsStartRealtime()).thenReturn(
+ when(mBatteryUsageStats.getStatsStartTimestamp()).thenReturn(
currentTimeMs - TIME_SINCE_LAST_FULL_CHARGE_MS);
assertThat(mBatteryUtils.calculateLastFullChargeTime(mBatteryUsageStats, currentTimeMs))
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java
index 6199788..6954f9a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java
@@ -24,7 +24,6 @@
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.fuelgauge.batterytip.actions.BatteryDefenderAction;
-import com.android.settings.fuelgauge.batterytip.actions.BatterySaverAction;
import com.android.settings.fuelgauge.batterytip.actions.OpenBatterySaverAction;
import com.android.settings.fuelgauge.batterytip.actions.OpenRestrictAppFragmentAction;
import com.android.settings.fuelgauge.batterytip.actions.RestrictAppAction;
@@ -90,34 +89,18 @@
}
@Test
- public void testGetActionForBatteryTip_typeEarlyWarningStateNew_returnActionBatterySaver() {
+ public void testGetActionForBatteryTip_typeEarlyWarningStateNew_returnActionOpen() {
when(mEarlyWarningTip.getState()).thenReturn(BatteryTip.StateType.NEW);
assertThat(BatteryTipUtils.getActionForBatteryTip(mEarlyWarningTip, mSettingsActivity,
- mFragment)).isInstanceOf(BatterySaverAction.class);
- }
-
- @Test
- public void testGetActionForBatteryTip_typeEarlyWarningStateHandled_returnActionOpen() {
- when(mEarlyWarningTip.getState()).thenReturn(BatteryTip.StateType.HANDLED);
-
- assertThat(BatteryTipUtils.getActionForBatteryTip(mEarlyWarningTip, mSettingsActivity,
mFragment)).isInstanceOf(OpenBatterySaverAction.class);
}
@Test
- public void testGetActionForBatteryTip_typeLowBatteryStateNew_returnActionBatterySaver() {
+ public void testGetActionForBatteryTip_typeLowBatteryStateNew_returnActionOpen() {
when(mLowBatteryTip.getState()).thenReturn(BatteryTip.StateType.NEW);
assertThat(BatteryTipUtils.getActionForBatteryTip(mLowBatteryTip, mSettingsActivity,
- mFragment)).isInstanceOf(BatterySaverAction.class);
- }
-
- @Test
- public void testGetActionForBatteryTip_typeLowBatteryStateHandled_returnActionOpen() {
- when(mLowBatteryTip.getState()).thenReturn(BatteryTip.StateType.HANDLED);
-
- assertThat(BatteryTipUtils.getActionForBatteryTip(mLowBatteryTip, mSettingsActivity,
mFragment)).isInstanceOf(OpenBatterySaverAction.class);
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetectorTest.java
index dbee7f1..84411a7 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetectorTest.java
@@ -86,11 +86,11 @@
}
@Test
- public void testDetect_batterySaverOn_tipHandled() {
+ public void testDetect_batterySaverOn_tipInvisible() {
doReturn(true).when(mPowerManager).isPowerSaveMode();
assertThat(mEarlyWarningDetector.detect().getState())
- .isEqualTo(BatteryTip.StateType.HANDLED);
+ .isEqualTo(BatteryTip.StateType.INVISIBLE);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetectorTest.java
index 55020e2..245bacc 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetectorTest.java
@@ -91,10 +91,11 @@
}
@Test
- public void testDetect_batterySaverOn_tipHandled() {
+ public void testDetect_batterySaverOn_tipInvisible() {
mShadowPowerManager.setIsPowerSaveMode(true);
- assertThat(mLowBatteryDetector.detect().getState()).isEqualTo(BatteryTip.StateType.HANDLED);
+ assertThat(mLowBatteryDetector.detect().getState())
+ .isEqualTo(BatteryTip.StateType.INVISIBLE);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetectorTest.java
index 477bf49..00dcbd4 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetectorTest.java
@@ -22,26 +22,37 @@
import android.content.ContentResolver;
import android.content.Context;
+import android.os.PowerManager;
import android.provider.Settings;
+import com.android.settings.fuelgauge.BatteryInfo;
import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowPowerManager;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class SmartBatteryDetectorTest {
+ private static final int EXPECTED_BATTERY_LEVEL = 30;
+ private static final int UNEXPECTED_BATTERY_LEVEL = 31;
+
private Context mContext;
private ContentResolver mContentResolver;
private SmartBatteryDetector mSmartBatteryDetector;
private BatteryTipPolicy mPolicy;
+ private ShadowPowerManager mShadowPowerManager;
+ @Mock
+ private BatteryInfo mBatteryInfo;
@Before
public void setUp() {
@@ -50,7 +61,9 @@
mContext = RuntimeEnvironment.application;
mContentResolver = mContext.getContentResolver();
mPolicy = spy(new BatteryTipPolicy(mContext));
- mSmartBatteryDetector = new SmartBatteryDetector(mPolicy, mContentResolver);
+ mShadowPowerManager = Shadows.shadowOf(mContext.getSystemService(PowerManager.class));
+ mSmartBatteryDetector =
+ new SmartBatteryDetector(mContext, mPolicy, mBatteryInfo, mContentResolver);
}
@Test
@@ -64,14 +77,38 @@
public void testDetect_smartBatteryOff_tipVisible() {
Settings.Global.putInt(mContentResolver,
Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, 0);
+ mShadowPowerManager.setIsPowerSaveMode(false);
+ mBatteryInfo.batteryLevel = EXPECTED_BATTERY_LEVEL;
assertThat(mSmartBatteryDetector.detect().isVisible()).isTrue();
}
@Test
+ public void testDetect_batterySaverOn_tipInvisible() {
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, 0);
+ mShadowPowerManager.setIsPowerSaveMode(true);
+ mBatteryInfo.batteryLevel = EXPECTED_BATTERY_LEVEL;
+
+ assertThat(mSmartBatteryDetector.detect().isVisible()).isFalse();
+ }
+
+ @Test
+ public void testDetect_unexpectedBatteryLevel_tipInvisible() {
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, 0);
+ mShadowPowerManager.setIsPowerSaveMode(true);
+ mBatteryInfo.batteryLevel = UNEXPECTED_BATTERY_LEVEL;
+
+ assertThat(mSmartBatteryDetector.detect().isVisible()).isFalse();
+ }
+
+ @Test
public void testDetect_smartBatteryOn_tipInvisible() {
Settings.Global.putInt(mContentResolver,
Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, 1);
+ mShadowPowerManager.setIsPowerSaveMode(false);
+ mBatteryInfo.batteryLevel = EXPECTED_BATTERY_LEVEL;
assertThat(mSmartBatteryDetector.detect().isVisible()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java
index 85b00c8..aeea10f 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java
@@ -74,24 +74,13 @@
}
@Test
- public void testInfo_stateHandled_displayPowerModeHandledInfo() {
- final EarlyWarningTip tip =
- new EarlyWarningTip(BatteryTip.StateType.HANDLED, false /* powerModeOn */);
-
- assertThat(tip.getTitle(mContext)).isEqualTo("Battery Saver is on");
- assertThat(tip.getSummary(mContext)).isEqualTo("Some features may be limited");
- assertThat(tip.getIconId()).isEqualTo(R.drawable.ic_battery_status_maybe_24dp);
- assertThat(tip.getIconTintColorId()).isEqualTo(R.color.battery_maybe_color_light);
- }
-
- @Test
- public void testUpdate_powerModeTurnedOn_typeBecomeHandled() {
+ public void testUpdate_powerModeTurnedOn_typeBecomeInvisible() {
final EarlyWarningTip nextTip =
new EarlyWarningTip(BatteryTip.StateType.INVISIBLE, true /* powerModeOn */);
mEarlyWarningTip.updateState(nextTip);
- assertThat(mEarlyWarningTip.getState()).isEqualTo(BatteryTip.StateType.HANDLED);
+ assertThat(mEarlyWarningTip.getState()).isEqualTo(BatteryTip.StateType.INVISIBLE);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTipTest.java
index 11dffcd..244faea 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTipTest.java
@@ -65,13 +65,6 @@
}
@Test
- public void getSummary_tipHandled_showSummary() {
- mLowBatteryTip.mState = BatteryTip.StateType.HANDLED;
-
- assertThat(mLowBatteryTip.getSummary(mContext)).isEqualTo("Some features may be limited");
- }
-
- @Test
public void getSummary_tipNew_showSummary() {
mLowBatteryTip.mState = BatteryTip.StateType.NEW;
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java
index 11128f3..b53629e 100644
--- a/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java
@@ -51,14 +51,16 @@
public void setChecked_setBoolean_checkIsTrueOrFalse() {
mController.setChecked(false);
assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isFalse();
+ assertThat(OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext)).isTrue();
mController.setChecked(true);
assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isTrue();
+ assertThat(OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext)).isFalse();
}
@Test
public void getAvailabilityStatus_setSupportOneHandedModeProperty_shouldAvailable() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "true");
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
@@ -66,7 +68,7 @@
@Test
public void getAvailabilityStatus_unsetSupportOneHandedModeProperty_shouldUnsupported() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "false");
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsTest.java
index fcea919..2651708 100644
--- a/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsTest.java
@@ -55,7 +55,7 @@
@Test
public void isPageSearchEnabled_setSupportOneHandedModeProperty_shouldReturnTrue() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "true");
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
final Object obj = ReflectionHelpers.callInstanceMethod(
OneHandedSettings.SEARCH_INDEX_DATA_PROVIDER, "isPageSearchEnabled",
@@ -66,7 +66,7 @@
@Test
public void isPageSearchEnabled_unsetSupportOneHandedModeProperty_shouldReturnFalse() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "false");
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
final Object obj = ReflectionHelpers.callInstanceMethod(
OneHandedSettings.SEARCH_INDEX_DATA_PROVIDER, "isPageSearchEnabled",
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceControllerTest.java
index c6d8233..9f76800 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceControllerTest.java
@@ -16,10 +16,7 @@
package com.android.settings.gestures;
-import static android.provider.Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED;
-
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
import static com.google.common.truth.Truth.assertThat;
@@ -28,6 +25,7 @@
import android.provider.Settings;
import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
import org.junit.Before;
import org.junit.Test;
@@ -57,44 +55,33 @@
public void setChecked_toggledOn_enablesSwipeBottomToNotification() {
mController.setChecked(true);
- assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
- SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0)).isEqualTo(1);
+ assertThat(OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext)).isTrue();
+ assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isFalse();
}
@Test
public void setChecked_toggledOff_disablesSwipeBottomToNotification() {
mController.setChecked(false);
- assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
- SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0)).isEqualTo(0);
+ assertThat(OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext)).isFalse();
}
@Test
- public void getAvailabilityStatus_oneHandedUnsupported_returnsAvailable() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "false");
+ public void getAvailabilityStatus_oneHandedUnsupported_returnsUnsupport() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_oneHandedSupported_returnsAvailable() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
- public void getAvailabilityStatus_oneHandedDisabled_returnsAvailable() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "true");
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ONE_HANDED_MODE_ENABLED, 0);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
- }
-
- @Test
- public void getAvailabilityStatus_oneHandedEnabled_returnsDisabled() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "true");
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ONE_HANDED_MODE_ENABLED, 1);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
- }
-
- @Test
public void getSummary_gestureEnabled_returnsOnSummary() {
mController.setChecked(true);
@@ -111,8 +98,8 @@
}
@Test
- public void getDefaultConfig_returnsOffState() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "false");
+ public void isChecked_getDefaultConfig_returnFalse() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
Settings.Secure.resetToDefaults(mContext.getContentResolver(),
Settings.Secure.ONE_HANDED_MODE_ENABLED);
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationSettingsTest.java
index ad8104c..3a65b26 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationSettingsTest.java
@@ -21,7 +21,6 @@
import android.content.Context;
import android.os.SystemProperties;
import android.provider.SearchIndexableResource;
-import android.provider.Settings;
import com.android.settings.R;
@@ -64,22 +63,21 @@
}
@Test
- public void isPageSearchEnabled_oneHandedUnsupported_shouldReturnTrue() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "false");
+ public void isPageSearchEnabled_oneHandedUnsupported_shouldReturnFalse() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
final Object obj = ReflectionHelpers.callInstanceMethod(
SwipeBottomToNotificationSettings.SEARCH_INDEX_DATA_PROVIDER, "isPageSearchEnabled",
ReflectionHelpers.ClassParameter.from(Context.class, mContext));
final boolean isEnabled = (Boolean) obj;
- assertThat(isEnabled).isTrue();
+ assertThat(isEnabled).isFalse();
}
@Test
public void isPageSearchEnabled_oneHandedDisabled_shouldReturnTrue() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "true");
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ONE_HANDED_MODE_ENABLED, 0);
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+ OneHandedSettingsUtils.setSettingsOneHandedModeEnabled(mContext, false);
final Object obj = ReflectionHelpers.callInstanceMethod(
SwipeBottomToNotificationSettings.SEARCH_INDEX_DATA_PROVIDER, "isPageSearchEnabled",
@@ -91,9 +89,8 @@
@Test
public void isPageSearchEnabled_oneHandedEnabled_shouldReturnFalse() {
- SystemProperties.set(OneHandedEnablePreferenceController.SUPPORT_ONE_HANDED_MODE, "true");
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ONE_HANDED_MODE_ENABLED, 1);
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+ OneHandedSettingsUtils.setSettingsOneHandedModeEnabled(mContext, true);
final Object obj = ReflectionHelpers.callInstanceMethod(
SwipeBottomToNotificationSettings.SEARCH_INDEX_DATA_PROVIDER, "isPageSearchEnabled",
diff --git a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
index 173f625..c7a2650 100644
--- a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
@@ -25,16 +25,20 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.os.Build;
-import android.util.FeatureFlagUtils;
+import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
+import androidx.fragment.app.Fragment;
+
import com.android.settings.R;
-import com.android.settings.core.FeatureFlags;
import com.android.settings.core.HideNonSystemOverlayMixin;
+import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSliceTest;
+import com.android.settings.testutils.shadow.ShadowUserManager;
import org.junit.Before;
import org.junit.Test;
@@ -46,15 +50,20 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowActivityManager;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowUserManager.class,
+ SettingsHomepageActivityTest.ShadowSuggestionFeatureProviderImpl.class})
public class SettingsHomepageActivityTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- FeatureFlagUtils.setEnabled(RuntimeEnvironment.application, FeatureFlags.SILKY_HOME, false);
}
@Test
@@ -67,6 +76,77 @@
}
@Test
+ public void launch_configDisabled_shouldHideAvatar() {
+ final SettingsHomepageActivity activity = Robolectric.buildActivity(
+ SettingsHomepageActivity.class).create().get();
+
+ final View avatarView = activity.findViewById(R.id.account_avatar);
+ assertThat(avatarView.getVisibility()).isNotEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void launch_configEnabled_shouldShowAvatar() {
+ final SettingsHomepageActivity activity = Robolectric.buildActivity(
+ SettingsHomepageActivity.class).create().get();
+
+ final View avatarView = activity.findViewById(R.id.account_avatar);
+ assertThat(avatarView.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void launch_LowRamDevice_shouldHideAvatar() {
+ final ShadowActivityManager activityManager = Shadow.extract(
+ RuntimeEnvironment.application.getSystemService(ActivityManager.class));
+ activityManager.setIsLowRamDevice(true);
+
+ final SettingsHomepageActivity activity = Robolectric.buildActivity(
+ SettingsHomepageActivity.class).create().get();
+
+ final View avatarView = activity.findViewById(R.id.account_avatar);
+ assertThat(avatarView.getVisibility()).isNotEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void showHomepageWithSuggestion_showSuggestion() {
+ final SettingsHomepageActivity activity = Robolectric.buildActivity(
+ SettingsHomepageActivity.class).create().get();
+ final View viewRoot = activity.findViewById(R.id.settings_homepage_container);
+ final View suggestionTile = activity.findViewById(R.id.suggestion_content);
+
+ activity.showHomepageWithSuggestion(true);
+
+ assertThat(viewRoot.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(suggestionTile.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void showHomepageWithSuggestion_hideSuggestion() {
+ final SettingsHomepageActivity activity = Robolectric.buildActivity(
+ SettingsHomepageActivity.class).create().get();
+ final View viewRoot = activity.findViewById(R.id.settings_homepage_container);
+ final View suggestionTile = activity.findViewById(R.id.suggestion_content);
+
+ activity.showHomepageWithSuggestion(false);
+
+ assertThat(viewRoot.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(suggestionTile.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void showHomepageWithSuggestion_callTwice_shouldKeepPreviousVisibility() {
+ final SettingsHomepageActivity activity = Robolectric.buildActivity(
+ SettingsHomepageActivity.class).create().get();
+ final View suggestionTile = activity.findViewById(R.id.suggestion_content);
+
+ activity.showHomepageWithSuggestion(false);
+ activity.showHomepageWithSuggestion(true);
+
+ assertThat(suggestionTile.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
@Config(shadows = {
BatteryFixSliceTest.ShadowBatteryTipLoader.class
})
@@ -114,4 +194,13 @@
assertThat(paramCaptor.getValue().privateFlags
& SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS).isEqualTo(0);
}
+
+ @Implements(SuggestionFeatureProviderImpl.class)
+ public static class ShadowSuggestionFeatureProviderImpl {
+
+ @Implementation
+ public Class<? extends Fragment> getContextualSuggestionFragment() {
+ return Fragment.class;
+ }
+ }
}
diff --git a/tests/robotests/src/com/android/settings/network/BluetoothTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/BluetoothTetherPreferenceControllerTest.java
index d3a3129..53dd959 100644
--- a/tests/robotests/src/com/android/settings/network/BluetoothTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/BluetoothTetherPreferenceControllerTest.java
@@ -57,7 +57,7 @@
mContext = spy(ApplicationProvider.getApplicationContext());
mSwitchPreference = spy(SwitchPreference.class);
- when(mContext.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
+ when(mContext.getSystemService(TetheringManager.class)).thenReturn(mTetheringManager);
when(mTetheringManager.getTetherableBluetoothRegexs()).thenReturn(new String[] {""});
mController = new BluetoothTetherPreferenceController(mContext, "BLUETOOTH");
mController.setTetherEnabler(mTetherEnabler);
diff --git a/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java
index 8a81908..de642f6 100644
--- a/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java
@@ -62,9 +62,9 @@
public void setUp() {
mContext = spy(ApplicationProvider.getApplicationContext());
mPreference = spy(SwitchPreference.class);
- when(mContext.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
+ when(mContext.getSystemService(TetheringManager.class)).thenReturn(mTetheringManager);
when(mTetheringManager.getTetherableIfaces()).thenReturn(new String[]{ETHERNET_REGEX});
- when(mContext.getSystemService(Context.ETHERNET_SERVICE)).thenReturn(mEthernetManager);
+ when(mContext.getSystemService(EthernetManager.class)).thenReturn(mEthernetManager);
mController = new EthernetTetherPreferenceController(mContext, "ethernet");
mController.setTetherEnabler(mTetherEnabler);
ReflectionHelpers.setField(mController, "mEthernetRegex", ETHERNET_REGEX);
diff --git a/tests/robotests/src/com/android/settings/network/NetworkResetRestrictionCheckerTest.java b/tests/robotests/src/com/android/settings/network/NetworkResetRestrictionCheckerTest.java
index 8996c1d..293b649 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkResetRestrictionCheckerTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkResetRestrictionCheckerTest.java
@@ -45,14 +45,14 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
mRestrictionChecker = spy(new NetworkResetRestrictionChecker(mContext));
}
@Test
public void testHasRestriction_notAdmin_shouldReturnTrue() {
final Context context = mock(Context.class);
- when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(context.getSystemService(UserManager.class)).thenReturn(mUserManager);
when(mUserManager.isAdminUser()).thenReturn(false);
assertThat(mRestrictionChecker.hasRestriction()).isTrue();
diff --git a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
index 390a674..fce9517 100644
--- a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
@@ -125,7 +125,7 @@
mContext = spy(RuntimeEnvironment.application);
mContentResolver = mContext.getContentResolver();
mShadowContentResolver = Shadow.extract(mContentResolver);
- when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
+ when(mContext.getSystemService(ConnectivityManager.class))
.thenReturn(mConnectivityManager);
doNothing().when(mConnectivityManager).registerDefaultNetworkCallback(
mCallbackCaptor.capture(), nullable(Handler.class));
diff --git a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
index bb4b0c4..cd93865 100644
--- a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
@@ -95,10 +95,10 @@
AtomicReference<BluetoothPan> panReference = spy(AtomicReference.class);
mSwitchBar = spy(new SwitchBar(context));
mSwitchWidgetController = spy(new SwitchBarController(mSwitchBar));
- when(context.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
- when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
+ when(context.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
+ when(context.getSystemService(ConnectivityManager.class)).thenReturn(
mConnectivityManager);
- when(context.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
+ when(context.getSystemService(TetheringManager.class)).thenReturn(mTetheringManager);
when(context.getSystemService(Context.NETWORK_POLICY_SERVICE)).thenReturn(
mNetworkPolicyManager);
when(mTetheringManager.getTetherableIfaces()).thenReturn(new String[0]);
@@ -311,4 +311,4 @@
assertThat(TetherEnabler.isTethering(TETHERING_ETHERNET_ON, TETHERING_ETHERNET)).isTrue();
assertThat(TetherEnabler.isTethering(~TETHERING_ETHERNET_ON, TETHERING_ETHERNET)).isFalse();
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/network/UsbTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/UsbTetherPreferenceControllerTest.java
index e02da90..0639ef3 100644
--- a/tests/robotests/src/com/android/settings/network/UsbTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/UsbTetherPreferenceControllerTest.java
@@ -55,7 +55,7 @@
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
- when(mContext.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
+ when(mContext.getSystemService(TetheringManager.class)).thenReturn(mTetheringManager);
when(mTetheringManager.getTetherableUsbRegexs()).thenReturn(new String[]{""});
mController = new UsbTetherPreferenceController(mContext, "USB");
mController.setTetherEnabler(mTetherEnabler);
diff --git a/tests/robotests/src/com/android/settings/network/WifiTetherDisablePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/WifiTetherDisablePreferenceControllerTest.java
index a82a71f..22ed55c 100644
--- a/tests/robotests/src/com/android/settings/network/WifiTetherDisablePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/WifiTetherDisablePreferenceControllerTest.java
@@ -100,7 +100,7 @@
mContext = spy(ApplicationProvider.getApplicationContext());
mPreference = spy(SwitchPreference.class);
- when(mContext.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
+ when(mContext.getSystemService(TetheringManager.class)).thenReturn(mTetheringManager);
when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(new String[]{""});
mController = new WifiTetherDisablePreferenceController(mContext, WIFI_TETHER_DISABLE_KEY);
mController.setTetherEnabler(mTetherEnabler);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java
index ba37c30..acc6b1a 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java
@@ -74,7 +74,7 @@
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+ doReturn(mTelephonyManager).when(mContext).getSystemService(TelephonyManager.class);
doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class);
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
diff --git a/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java b/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java
index 6bee38f..0d86408 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java
@@ -77,7 +77,7 @@
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+ when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index 7bd7813..b7e6ffd 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -43,6 +43,7 @@
import com.android.settings.panel.PanelFeatureProvider;
import com.android.settings.search.SearchFeatureProvider;
import com.android.settings.security.SecurityFeatureProvider;
+import com.android.settings.security.SecuritySettingsFeatureProvider;
import com.android.settings.slices.SlicesFeatureProvider;
import com.android.settings.users.UserFeatureProvider;
import com.android.settings.wifi.WifiTrackerLibProvider;
@@ -83,6 +84,7 @@
public WifiTrackerLibProvider wifiTrackerLibProvider;
public ExtraAppInfoFeatureProvider extraAppInfoFeatureProvider;
+ public SecuritySettingsFeatureProvider securitySettingsFeatureProvider;
/**
* Call this in {@code @Before} method of the test class to use fake factory.
@@ -130,6 +132,7 @@
mFaceFeatureProvider = mock(FaceFeatureProvider.class);
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
extraAppInfoFeatureProvider = mock(ExtraAppInfoFeatureProvider.class);
+ securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
}
@Override
@@ -256,4 +259,9 @@
public ExtraAppInfoFeatureProvider getExtraAppInfoFeatureProvider() {
return extraAppInfoFeatureProvider;
}
+
+ @Override
+ public SecuritySettingsFeatureProvider getSecuritySettingsFeatureProvider() {
+ return securitySettingsFeatureProvider;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
index 094e282..be3267e 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
@@ -78,7 +78,7 @@
mActivity = spy(activity);
mWifiManager = mock(WifiManager.class);
- when(mActivity.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
+ when(mActivity.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java
index 65cc811..2475d80 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiEnablerTest.java
@@ -53,7 +53,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
+ when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
mEnabler = new WifiEnabler(mContext, mock(SwitchWidgetController.class),
mock(MetricsFeatureProvider.class), mConnectivityManager);
}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiPrimarySwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiPrimarySwitchPreferenceControllerTest.java
index b94df29..4100d05 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiPrimarySwitchPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiPrimarySwitchPreferenceControllerTest.java
@@ -78,7 +78,7 @@
when(mContext.getSystemService(NetworkScoreManager.class)).thenReturn(mNetworkScoreManager);
mController = new WifiPrimarySwitchPreferenceController(mContext, mMetricsFeatureProvider);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
- when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
+ when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_DISABLED);
}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
index 7eba586..428a360 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
@@ -209,7 +209,7 @@
final Resources.Theme theme = mContext.getTheme();
when(activity.getTheme()).thenReturn(theme);
UserManager userManager = mock(UserManager.class);
- when(activity.getSystemService(Context.USER_SERVICE))
+ when(activity.getSystemService(UserManager.class))
.thenReturn(userManager);
when(mWifiSettings.findPreference(WifiSettings.PREF_KEY_DATA_USAGE))
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/DisclaimerItemListAdapterTest.java b/tests/robotests/src/com/android/settings/wifi/calling/DisclaimerItemListAdapterTest.java
index 8478a54..3e15348 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/DisclaimerItemListAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/DisclaimerItemListAdapterTest.java
@@ -77,7 +77,7 @@
when(mLayoutInflater.inflate(anyInt(), anyObject(), anyBoolean())).thenReturn(mView);
when(mViewGroup.getContext()).thenReturn(mContext);
- when(mViewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).thenReturn(
+ when(mViewGroup.getContext().getSystemService(LayoutInflater.class)).thenReturn(
mLayoutInflater);
when(mView.findViewById(ID_DISCLAIMER_ITEM_TITLE)).thenReturn(mTestView);
when(mView.findViewById(ID_DISCLAIMER_ITEM_DESCRIPTION)).thenReturn(mDescView);
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/EmergencyCallLimitationDisclaimerTest.java b/tests/robotests/src/com/android/settings/wifi/calling/EmergencyCallLimitationDisclaimerTest.java
index 985edda..c15e850 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/EmergencyCallLimitationDisclaimerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/EmergencyCallLimitationDisclaimerTest.java
@@ -54,7 +54,7 @@
mContext = spy(RuntimeEnvironment.application);
doReturn(mCarrierConfigManager).when(mContext).getSystemService(
- Context.CARRIER_CONFIG_SERVICE);
+ CarrierConfigManager.class);
when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mBundle);
doReturn(getSharedPreferences()).when(mContext).getSharedPreferences(anyString(), anyInt());
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/LocationPolicyDisclaimerTest.java b/tests/robotests/src/com/android/settings/wifi/calling/LocationPolicyDisclaimerTest.java
index 3fe9678..108acf8 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/LocationPolicyDisclaimerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/LocationPolicyDisclaimerTest.java
@@ -54,7 +54,7 @@
mContext = spy(RuntimeEnvironment.application);
doReturn(mCarrierConfigManager).when(mContext).getSystemService(
- Context.CARRIER_CONFIG_SERVICE);
+ CarrierConfigManager.class);
when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mBundle);
doReturn(getSharedPreferences()).when(mContext).getSharedPreferences(anyString(), anyInt());
}
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
index c5f2a7f..3e0e22f 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
@@ -52,6 +52,7 @@
import android.net.NetworkRequest;
import android.net.RouteInfo;
import android.net.Uri;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
@@ -83,6 +84,7 @@
import com.android.wifitrackerlib.NetworkDetailsTracker;
import com.android.wifitrackerlib.WifiEntry;
import com.android.wifitrackerlib.WifiEntry.ConnectCallback;
+import com.android.wifitrackerlib.WifiEntry.ConnectedInfo;
import org.junit.Before;
import org.junit.Test;
@@ -189,6 +191,8 @@
@Mock
private Preference mMockDnsPref;
@Mock
+ private Preference mMockTypePref;
+ @Mock
private PreferenceCategory mMockIpv6Category;
@Mock
private Preference mMockIpv6AddressesPref;
@@ -390,6 +394,8 @@
.thenReturn(mMockSubnetPref);
when(mMockScreen.findPreference(WifiDetailPreferenceController2.KEY_DNS_PREF))
.thenReturn(mMockDnsPref);
+ when(mMockScreen.findPreference(WifiDetailPreferenceController2.KEY_WIFI_TYPE_PREF))
+ .thenReturn(mMockTypePref);
when(mMockScreen.findPreference(WifiDetailPreferenceController2.KEY_IPV6_CATEGORY))
.thenReturn(mMockIpv6Category);
when(mMockScreen.findPreference(WifiDetailPreferenceController2.KEY_IPV6_ADDRESSES_PREF))
@@ -931,6 +937,44 @@
}
@Test
+ public void onConnectedNetwork_getKnownNetworkType_visibleWifiTypePref() {
+ setUpForConnectedNetwork();
+ setUpSpyController();
+ setWifiType(ScanResult.WIFI_STANDARD_11AX);
+
+ displayAndResume();
+
+ verify(mMockTypePref).setSummary(R.string.wifi_type_11AX);
+ verify(mMockTypePref).setVisible(true);
+ }
+
+ @Test
+ public void onConnectedNetwork_getUnKnownNetworkType_invisibleWifiTypePref() {
+ setUpForConnectedNetwork();
+ setUpSpyController();
+ setWifiType(ScanResult.WIFI_STANDARD_UNKNOWN);
+
+ displayAndResume();
+
+ verify(mMockTypePref).setVisible(false);
+ }
+
+ @Test
+ public void onDisconnectedNetwork_resumeUI_invisibleWifiTypePref() {
+ setUpForDisconnectedNetwork();
+
+ displayAndResume();
+
+ verify(mMockTypePref).setVisible(false);
+ }
+
+ private void setWifiType(int type) {
+ ConnectedInfo connectedInfo = new ConnectedInfo();
+ connectedInfo.wifiStandard = type;
+ when(mMockWifiEntry.getConnectedInfo()).thenReturn(connectedInfo);
+ }
+
+ @Test
public void noCurrentNetwork_shouldNotFinishActivityForConnectedNetwork() {
setUpForConnectedNetwork();
setUpSpyController();
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
index d777a59..252d876 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
@@ -73,8 +73,8 @@
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mPreference = new ListPreference(RuntimeEnvironment.application);
- when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
- when(mContext.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
+ when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
+ when(mContext.getSystemService(TetheringManager.class)).thenReturn(mTetheringManager);
when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(new String[]{"1", "2"});
when(mContext.getResources()).thenReturn(RuntimeEnvironment.application.getResources());
when(mScreen.findPreference(anyString())).thenReturn(mPreference);
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
index 2ecc7d2..9a34323 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
@@ -80,10 +80,10 @@
MockitoAnnotations.initMocks(this);
doReturn(mConnectivityManager)
- .when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);
- doReturn(mTetheringManager).when(mContext).getSystemService(Context.TETHERING_SERVICE);
+ .when(mContext).getSystemService(ConnectivityManager.class);
+ doReturn(mTetheringManager).when(mContext).getSystemService(TetheringManager.class);
doReturn(WIFI_REGEXS).when(mTetheringManager).getTetherableWifiRegexs();
- doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
+ doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
mWifiTetherSettings = new WifiTetherSettings();
}
@@ -133,7 +133,7 @@
when(settings.getContext()).thenReturn(mContext);
final Resources.Theme theme = mContext.getTheme();
when(activity.getTheme()).thenReturn(theme);
- when(activity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(activity.getSystemService(UserManager.class)).thenReturn(mUserManager);
doNothing().when(settings)
.onCreatePreferences(any(Bundle.class), nullable(String.class));
final FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index b7ac4b1..5582ff4 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -34,6 +34,8 @@
"ub-uiautomator",
"SettingsLibSettingsSpinner",
"SettingsLibUsageProgressBarPreference",
+ "SettingsLibTwoTargetPreference",
+ "SettingsLibMainSwitchPreference",
],
// Include all test java files.
diff --git a/tests/unit/src/com/android/settings/applications/HibernatedAppsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/HibernatedAppsPreferenceControllerTest.java
index cf4c53e..a34e634 100644
--- a/tests/unit/src/com/android/settings/applications/HibernatedAppsPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/HibernatedAppsPreferenceControllerTest.java
@@ -23,9 +23,18 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.apphibernation.AppHibernationManager;
import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.provider.DeviceConfig;
import androidx.test.core.app.ApplicationProvider;
@@ -34,23 +43,40 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
-/**
- * TODO(b/181172051): test getNumberHibernated() when the API implemented
- */
+import java.util.Arrays;
+
@RunWith(AndroidJUnit4.class)
public class HibernatedAppsPreferenceControllerTest {
+ public static final String HIBERNATED_PACKAGE_NAME = "hibernated_package";
+ public static final String AUTO_REVOKED_PACKAGE_NAME = "auto_revoked_package";
+ public static final String PERMISSION = "permission";
+ @Mock
+ PackageManager mPackageManager;
+ @Mock
+ AppHibernationManager mAppHibernationManager;
private static final String KEY = "key";
private Context mContext;
private HibernatedAppsPreferenceController mController;
+ private PackageInfo mHibernatedPackage;
+ private PackageInfo mAutoRevokedPackage;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
"true", false);
mContext = spy(ApplicationProvider.getApplicationContext());
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mContext.getSystemService(AppHibernationManager.class))
+ .thenReturn(mAppHibernationManager);
mController = new HibernatedAppsPreferenceController(mContext, KEY);
+ mHibernatedPackage =
+ getHibernatedPackage(mAppHibernationManager, mPackageManager, mContext);
+ mAutoRevokedPackage = getAutoRevokedPackage(mPackageManager, mContext);
}
@Test
@@ -60,4 +86,38 @@
assertThat((mController).getAvailabilityStatus()).isNotEqualTo(AVAILABLE);
}
+
+ @Test
+ public void getSummary_shouldReturnCorrectly() {
+ when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(
+ Arrays.asList(mHibernatedPackage, mAutoRevokedPackage, new PackageInfo()));
+ when(mContext.getResources()).thenReturn(mock(Resources.class));
+ final int totalHibernated = 2;
+
+ mController.getSummary();
+ verify(mContext.getResources()).getQuantityString(
+ anyInt(), eq(totalHibernated), eq(totalHibernated));
+ }
+
+ private static PackageInfo getHibernatedPackage(
+ AppHibernationManager apm, PackageManager pm, Context context) {
+ final PackageInfo pi = new PackageInfo();
+ pi.packageName = HIBERNATED_PACKAGE_NAME;
+ pi.requestedPermissions = new String[] {PERMISSION};
+ when(apm.getHibernatingPackagesForUser()).thenReturn(Arrays.asList(pi.packageName));
+ when(pm.getPermissionFlags(
+ pi.requestedPermissions[0], pi.packageName, context.getUser()))
+ .thenReturn(PackageManager.FLAG_PERMISSION_AUTO_REVOKED);
+ return pi;
+ }
+
+ private static PackageInfo getAutoRevokedPackage(PackageManager pm, Context context) {
+ final PackageInfo pi = new PackageInfo();
+ pi.packageName = AUTO_REVOKED_PACKAGE_NAME;
+ pi.requestedPermissions = new String[] {PERMISSION};
+ when(pm.getPermissionFlags(
+ pi.requestedPermissions[0], pi.packageName, context.getUser()))
+ .thenReturn(PackageManager.FLAG_PERMISSION_AUTO_REVOKED);
+ return pi;
+ }
}
diff --git a/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java
index e27942a..65ffe4b 100644
--- a/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/appinfo/HibernationSwitchPreferenceControllerTest.java
@@ -70,9 +70,9 @@
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
- when(mPackageManager.getPackageUidAsUser(eq(VALID_PACKAGE_NAME), anyInt()))
+ when(mPackageManager.getPackageUid(eq(VALID_PACKAGE_NAME), anyInt()))
.thenReturn(PACKAGE_UID);
- when(mPackageManager.getPackageUidAsUser(eq(INVALID_PACKAGE_NAME), anyInt()))
+ when(mPackageManager.getPackageUid(eq(INVALID_PACKAGE_NAME), anyInt()))
.thenThrow(new PackageManager.NameNotFoundException());
when(mPackageManager.getTargetSdkVersion(eq(EXEMPTED_PACKAGE_NAME)))
.thenReturn(android.os.Build.VERSION_CODES.Q);
diff --git a/tests/unit/src/com/android/settings/applications/autofill/PasswordsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/autofill/PasswordsPreferenceControllerTest.java
index 216658f..25d9893 100644
--- a/tests/unit/src/com/android/settings/applications/autofill/PasswordsPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/autofill/PasswordsPreferenceControllerTest.java
@@ -21,21 +21,26 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+
import android.content.ComponentName;
import android.content.Context;
import android.os.Looper;
import android.service.autofill.AutofillServiceInfo;
+import androidx.lifecycle.Lifecycle;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
+import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.collect.Lists;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -100,11 +105,15 @@
assertThat(mPasswordsPreferenceCategory.getPreferenceCount()).isEqualTo(0);
}
+ @Ignore("TODO: Fix the test to handle the service binding.")
@Test
+ @UiThreadTest
public void displayPreference_withPasswords_addsPreference() {
AutofillServiceInfo service = createServiceWithPasswords();
PasswordsPreferenceController controller =
createControllerWithServices(Lists.newArrayList(service));
+ controller.onCreate(() -> mock(Lifecycle.class));
+
controller.displayPreference(mScreen);
assertThat(mPasswordsPreferenceCategory.getPreferenceCount()).isEqualTo(1);
diff --git a/tests/unit/src/com/android/settings/network/EraseEuiccDataControllerTest.java b/tests/unit/src/com/android/settings/network/EraseEuiccDataControllerTest.java
index 6ddef5d..879b9f7 100644
--- a/tests/unit/src/com/android/settings/network/EraseEuiccDataControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/EraseEuiccDataControllerTest.java
@@ -18,8 +18,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.spy;
-
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
diff --git a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/VpnPreferenceControllerTest.java
similarity index 72%
rename from tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/network/VpnPreferenceControllerTest.java
index fb66d29..ee239ba 100644
--- a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/VpnPreferenceControllerTest.java
@@ -22,7 +22,6 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -32,34 +31,38 @@
import android.net.ConnectivityManager;
import android.net.NetworkRequest;
import android.net.VpnManager;
+import android.os.Looper;
import android.os.UserHandle;
+import android.provider.Settings;
import android.provider.SettingsSlicesContract;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
+import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.net.VpnConfig;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-@RunWith(RobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
public class VpnPreferenceControllerTest {
+ private static final String VPN_PREFERENCE_KEY = "vpn_settings";
- @Mock
private Context mContext;
@Mock
private ConnectivityManager mConnectivityManager;
@Mock
private VpnManager mVpnManager;
- @Mock
private PreferenceScreen mScreen;
@Mock
private Preference mPreference;
@@ -68,12 +71,21 @@
private LifecycleOwner mLifecycleOwner;
@Before
+ @UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
+ mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(mConnectivityManager);
when(mContext.getSystemService(VpnManager.class)).thenReturn(mVpnManager);
- when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+ PreferenceManager preferenceManager = new PreferenceManager(mContext);
+ mScreen = preferenceManager.createPreferenceScreen(mContext);
+ when(mPreference.getKey()).thenReturn(VPN_PREFERENCE_KEY);
+ mScreen.addPreference(mPreference);
mController = spy(new VpnPreferenceController(mContext));
mLifecycleOwner = () -> mLifecycle;
@@ -83,13 +95,20 @@
@Test
public void displayPreference_available_shouldSetDependency() {
- doReturn(true).when(mController).isAvailable();
- mController.displayPreference(mScreen);
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, "");
+ VpnPreferenceController controller = spy(new VpnPreferenceController(mContext));
+ doReturn(true).when(controller).isAvailable();
+
+ controller.displayPreference(mScreen);
verify(mPreference).setDependency(SettingsSlicesContract.KEY_AIRPLANE_MODE);
}
@Test
+ // TODO(b/176821216) re-enable this test once VpnPreferenceController is edited to notify
+ // the preference of legacy VPNs
+ @Ignore
public void goThroughLifecycle_shouldRegisterUnregisterListener() {
doReturn(true).when(mController).isAvailable();
@@ -107,7 +126,7 @@
final VpnConfig config = new VpnConfig();
config.legacy = true;
final VpnPreferenceController controller =
- new VpnPreferenceController(RuntimeEnvironment.application);
+ new VpnPreferenceController(ApplicationProvider.getApplicationContext());
final String summary = controller.getNameForVpnConfig(config, UserHandle.CURRENT);
diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
index 45f3693..0c8ffb9 100644
--- a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
@@ -74,7 +74,7 @@
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
- doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+ doReturn(mTelephonyManager).when(mContext).getSystemService(TelephonyManager.class);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
diff --git a/tests/unit/src/com/android/settings/security/SecuritySettingsFeatureProviderImplTest.java b/tests/unit/src/com/android/settings/security/SecuritySettingsFeatureProviderImplTest.java
new file mode 100644
index 0000000..5b0c7b5
--- /dev/null
+++ b/tests/unit/src/com/android/settings/security/SecuritySettingsFeatureProviderImplTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 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.security;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class SecuritySettingsFeatureProviderImplTest {
+
+ private SecuritySettingsFeatureProviderImpl mSecuritySettingsFeatureProvider;
+
+ @Before
+ public void setUp() {
+ mSecuritySettingsFeatureProvider = new SecuritySettingsFeatureProviderImpl();
+ }
+
+ @Test
+ public void hasAlternativeSecuritySettingsFragment_returnsFalse() {
+ assertThat(mSecuritySettingsFeatureProvider.hasAlternativeSecuritySettingsFragment())
+ .isFalse();
+ }
+
+ @Test
+ public void getAlternativeSecuritySettingsFragmentClassname_returnsNull() {
+ String alternativeFragmentClassname =
+ mSecuritySettingsFeatureProvider.getAlternativeSecuritySettingsFragmentClassname();
+ assertThat(alternativeFragmentClassname).isNull();
+ }
+}
diff --git a/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java b/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java
new file mode 100644
index 0000000..a9acd2a
--- /dev/null
+++ b/tests/unit/src/com/android/settings/security/TopLevelSecurityEntryPreferenceControllerTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 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.security;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.preference.Preference;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.SettingsActivity;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class TopLevelSecurityEntryPreferenceControllerTest {
+
+ private static final String PREFERENCE_KEY = "top_level_security";
+ private static final String ALTERNATIVE_FRAGMENT_CLASSNAME = "AlternativeFragmentClassname";
+
+ private TopLevelSecurityEntryPreferenceController mTopLevelSecurityEntryPreferenceController;
+ private Preference mPreference;
+ private FakeFeatureFactory mFeatureFactory;
+ private SecuritySettingsFeatureProvider mSecuritySettingsFeatureProvider;
+
+ @Mock
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mSecuritySettingsFeatureProvider = mFeatureFactory.getSecuritySettingsFeatureProvider();
+
+ mPreference = new Preference(ApplicationProvider.getApplicationContext());
+ mPreference.setKey(PREFERENCE_KEY);
+
+ doNothing().when(mContext).startActivity(any(Intent.class));
+ mTopLevelSecurityEntryPreferenceController =
+ new TopLevelSecurityEntryPreferenceController(mContext, PREFERENCE_KEY);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_forDifferentPreferenceKey_isNotHandled() {
+ Preference preference = new Preference(ApplicationProvider.getApplicationContext());
+ preference.setKey("some_other_preference");
+
+ boolean preferenceHandled =
+ mTopLevelSecurityEntryPreferenceController.handlePreferenceTreeClick(preference);
+
+ assertThat(preferenceHandled).isFalse();
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_withAlternativeFragment_launchesAlternativeFragment() {
+ when(mSecuritySettingsFeatureProvider.hasAlternativeSecuritySettingsFragment())
+ .thenReturn(true);
+ when(mSecuritySettingsFeatureProvider.getAlternativeSecuritySettingsFragmentClassname())
+ .thenReturn(ALTERNATIVE_FRAGMENT_CLASSNAME);
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+
+ boolean preferenceHandled =
+ mTopLevelSecurityEntryPreferenceController.handlePreferenceTreeClick(mPreference);
+
+ assertThat(preferenceHandled).isTrue();
+ verify(mContext).startActivity(intentCaptor.capture());
+ assertThat(intentCaptor.getValue().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(ALTERNATIVE_FRAGMENT_CLASSNAME);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_withDisabledAlternative_isNotHandled() {
+ when(mSecuritySettingsFeatureProvider.hasAlternativeSecuritySettingsFragment())
+ .thenReturn(false);
+ when(mSecuritySettingsFeatureProvider.getAlternativeSecuritySettingsFragmentClassname())
+ .thenReturn(ALTERNATIVE_FRAGMENT_CLASSNAME);
+
+ boolean preferenceHandled =
+ mTopLevelSecurityEntryPreferenceController.handlePreferenceTreeClick(mPreference);
+
+ assertThat(preferenceHandled).isFalse();
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_withoutAlternativeFragmentName_isNotHandled() {
+ when(mSecuritySettingsFeatureProvider.hasAlternativeSecuritySettingsFragment())
+ .thenReturn(true);
+ when(mSecuritySettingsFeatureProvider.getAlternativeSecuritySettingsFragmentClassname())
+ .thenReturn(null);
+
+ boolean preferenceHandled =
+ mTopLevelSecurityEntryPreferenceController.handlePreferenceTreeClick(mPreference);
+
+ assertThat(preferenceHandled).isFalse();
+ }
+}
diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
index a90c9bf..b6f330b 100644
--- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -41,6 +41,7 @@
import com.android.settings.panel.PanelFeatureProvider;
import com.android.settings.search.SearchFeatureProvider;
import com.android.settings.security.SecurityFeatureProvider;
+import com.android.settings.security.SecuritySettingsFeatureProvider;
import com.android.settings.slices.SlicesFeatureProvider;
import com.android.settings.users.UserFeatureProvider;
import com.android.settings.wifi.WifiTrackerLibProvider;
@@ -78,6 +79,7 @@
public WifiTrackerLibProvider wifiTrackerLibProvider;
public ExtraAppInfoFeatureProvider extraAppInfoFeatureProvider;
+ public SecuritySettingsFeatureProvider securitySettingsFeatureProvider;
/**
* Call this in {@code @Before} method of the test class to use fake factory.
@@ -116,6 +118,7 @@
mFaceFeatureProvider = mock(FaceFeatureProvider.class);
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
extraAppInfoFeatureProvider = mock(ExtraAppInfoFeatureProvider.class);
+ securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
}
@Override
@@ -242,4 +245,9 @@
public ExtraAppInfoFeatureProvider getExtraAppInfoFeatureProvider() {
return extraAppInfoFeatureProvider;
}
+
+ @Override
+ public SecuritySettingsFeatureProvider getSecuritySettingsFeatureProvider() {
+ return securitySettingsFeatureProvider;
+ }
}
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherMaximizeCompatibilityPreferenceControllerTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherMaximizeCompatibilityPreferenceControllerTest.java
index a2b99bf..0729780 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherMaximizeCompatibilityPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherMaximizeCompatibilityPreferenceControllerTest.java
@@ -121,20 +121,20 @@
}
@Test
- public void isMaximizeCompatibilityEnabled_concurrencySupportedAndEnabled_returnTure() {
+ public void isMaximizeCompatibilityEnabled_concurrencySupportedAndEnabled_returnFalse() {
// The preconditions are ready in setup().
- assertThat(mController.isMaximizeCompatibilityEnabled()).isEqualTo(true);
+ assertThat(mController.isMaximizeCompatibilityEnabled()).isEqualTo(false);
}
@Test
- public void isMaximizeCompatibilityEnabled_concurrencySupportedAndDisabled_returnFalse() {
+ public void isMaximizeCompatibilityEnabled_concurrencySupportedAndDisabled_returnTrue() {
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setBridgedModeOpportunisticShutdownEnabled(false)
.build();
doReturn(config).when(mWifiManager).getSoftApConfiguration();
- assertThat(mController.isMaximizeCompatibilityEnabled()).isEqualTo(false);
+ assertThat(mController.isMaximizeCompatibilityEnabled()).isEqualTo(true);
}
@Test
@@ -171,25 +171,25 @@
}
@Test
- public void setupMaximizeCompatibility_concurrencySupportedAndDisabled_setDisabled() {
+ public void setupMaximizeCompatibility_concurrencySupportedAndDisabled_setEnabled() {
// The precondition of the concurrency supported is ready in setup().
mController.onPreferenceChange(mPreference, false);
SoftApConfiguration.Builder builder = new SoftApConfiguration.Builder();
mController.setupMaximizeCompatibility(builder);
- assertThat(builder.build().isBridgedModeOpportunisticShutdownEnabled()).isEqualTo(false);
+ assertThat(builder.build().isBridgedModeOpportunisticShutdownEnabled()).isEqualTo(true);
}
@Test
- public void setupMaximizeCompatibility_concurrencySupportedAndEnabled_setEnabled() {
+ public void setupMaximizeCompatibility_concurrencySupportedAndEnabled_setDisabled() {
// The precondition of the concurrency supported is ready in setup().
mController.onPreferenceChange(mPreference, true);
SoftApConfiguration.Builder builder = new SoftApConfiguration.Builder();
mController.setupMaximizeCompatibility(builder);
- assertThat(builder.build().isBridgedModeOpportunisticShutdownEnabled()).isEqualTo(true);
+ assertThat(builder.build().isBridgedModeOpportunisticShutdownEnabled()).isEqualTo(false);
}
@Test