Merge changes from topic "a11y_image_preference_bc" into sc-dev
* changes:
Update the Lottie images for Accessibility features.
Update the material next style for AnimatedImagePreference.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0a40c89..570b53d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -713,7 +713,8 @@
<activity
android:name="Settings$ManageAssistActivity"
android:exported="true"
- android:label="@string/assist_and_voice_input_title">
+ android:label="@string/assist_and_voice_input_title"
+ android:theme="@style/Theme.SubSettings">
<intent-filter android:priority="1">
<action android:name="android.settings.VOICE_INPUT_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index b9f5009..bb414ad 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -1125,22 +1125,6 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <color name="contextual_card_stroke_color">#1f000000</color>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/colors.xml"
- line="106"
- column="5"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" <color name="switchbar_switch_track_tint">#BFFFFFFF</color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -4293,22 +4277,6 @@
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
- errorLine1=" <item name="strokeColor">@color/contextual_card_stroke_color</item>"
- errorLine2=" ^">
- <location
- file="res/values/styles.xml"
- line="475"
- column="34"/>
- </issue>
-
- <issue
- id="HardCodedColor"
- severity="Error"
- message="Avoid using hardcoded color"
- category="Correctness"
- priority="4"
- summary="Using hardcoded color"
- explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" <item name="android:trackTint">@color/switchbar_switch_track_tint</item>"
errorLine2=" ^">
<location
diff --git a/res/drawable/ic_no_internet_airplane.xml b/res/drawable/ic_no_internet_airplane.xml
deleted file mode 100644
index 3b22811..0000000
--- a/res/drawable/ic_no_internet_airplane.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- 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.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10c0.34,0 0.68,-0.02 1.01,-0.05V20h-1v-0.04c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96H13v-2H9.66c-0.09,-0.66 -0.16,-1.32 -0.16,-2s0.07,-1.35 0.16,-2H21.8C20.87,5.44 16.83,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56C16.43,5.07 17.96,6.35 18.92,8zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82C10.52,6.57 11.17,5.24 12,4.04zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2s0.06,1.34 0.14,2H4.26zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56C7.57,18.93 6.04,17.66 5.08,16zM8.03,8H5.08c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8z"
- android:fillAlpha="0.3"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M22,19.3v-0.9l-3.37,-2.25v-2.47C18.63,13.3 18.35,13 18,13s-0.63,0.3 -0.63,0.68v2.47L14,18.4v0.9l3.37,-1.12v2.48l-0.84,0.68V22L18,21.55L19.47,22v-0.67l-0.84,-0.68v-2.48L22,19.3z"/>
-</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_no_internet_unavailable.xml b/res/drawable/ic_no_internet_unavailable.xml
new file mode 100644
index 0000000..049034a
--- /dev/null
+++ b/res/drawable/ic_no_internet_unavailable.xml
@@ -0,0 +1,28 @@
+<!--
+ 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.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M2,12C2,6.48 6.47,2 11.99,2C17.52,2 22,6.48 22,12c0,0.34 -0.02,0.67 -0.05,1h-2.02c0.04,-0.33 0.07,-0.66 0.07,-1c0,-0.69 -0.1,-1.36 -0.26,-2h-3.38c0.08,0.66 0.14,1.32 0.14,2c0,0.34 -0.01,0.67 -0.04,1h-2.01c0.03,-0.33 0.05,-0.66 0.05,-1c0,-0.68 -0.07,-1.35 -0.16,-2H9.66c-0.09,0.65 -0.16,1.32 -0.16,2s0.07,1.34 0.16,2H13v2h-2.91c0.43,1.43 1.08,2.76 1.91,3.96V20h1v1.95C12.67,21.98 12.33,22 11.99,22C6.47,22 2,17.52 2,12zM15.97,8h2.95c-0.96,-1.65 -2.49,-2.93 -4.33,-3.56C15.19,5.55 15.65,6.75 15.97,8zM13.91,8C13.48,6.57 12.83,5.24 12,4.04c-0.83,1.2 -1.48,2.53 -1.91,3.96H13.91zM4,12c0,0.69 0.1,1.36 0.26,2h3.38c-0.08,-0.66 -0.14,-1.32 -0.14,-2s0.06,-1.34 0.14,-2H4.26C4.1,10.64 4,11.31 4,12zM8.03,16H5.08c0.96,1.66 2.49,2.93 4.33,3.56C8.81,18.45 8.35,17.25 8.03,16zM5.08,8h2.95c0.32,-1.25 0.78,-2.45 1.38,-3.56C7.57,5.07 6.04,6.34 5.08,8z"
+ android:fillAlpha="0.3"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+</vector>
diff --git a/res/drawable/ic_password.xml b/res/drawable/ic_password.xml
index 1924f6e..341e544 100644
--- a/res/drawable/ic_password.xml
+++ b/res/drawable/ic_password.xml
@@ -20,15 +20,15 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
- android:fillColor="?attr/colorAccent"
+ android:fillColor="?android:attr/colorAccent"
android:pathData="M21.5,9.39l-1.63,0l0.81,-1.42l-0.86,-0.5l-0.82,1.42l-0.82,-1.42l-0.86,0.5l0.81,1.42l-1.63,0l0,1l1.63,0l-0.81,1.41l0.86,0.5l0.82,-1.41l0.82,1.41l0.86,-0.5l-0.81,-1.41l1.63,0z" />
<path
- android:fillColor="?attr/colorAccent"
+ android:fillColor="?android:attr/colorAccent"
android:pathData="M13.68,7.97l-0.86,-0.5l-0.82,1.42l-0.82,-1.42l-0.86,0.5l0.81,1.42l-1.63,0l0,1l1.63,0l-0.81,1.41l0.86,0.5l0.82,-1.41l0.82,1.41l0.86,-0.5l-0.81,-1.41l1.63,0l0,-1l-1.63,0z" />
<path
- android:fillColor="?attr/colorAccent"
+ android:fillColor="?android:attr/colorAccent"
android:pathData="M6.68,7.97l-0.86,-0.5l-0.82,1.42l-0.82,-1.42l-0.86,0.5l0.81,1.42l-1.63,0l0,1l1.63,0l-0.81,1.41l0.86,0.5l0.82,-1.41l0.82,1.41l0.86,-0.5l-0.81,-1.41l1.63,0l0,-1l-1.63,0z" />
<path
- android:fillColor="?attr/colorAccent"
+ android:fillColor="?android:attr/colorAccent"
android:pathData="M21,17.89H3c-0.28,0 -0.5,-0.22 -0.5,-0.5v-1c0,-0.28 0.22,-0.5 0.5,-0.5h18c0.28,0 0.5,0.22 0.5,0.5v1C21.5,17.66 21.28,17.89 21,17.89z" />
</vector>
diff --git a/res/drawable/ic_pattern.xml b/res/drawable/ic_pattern.xml
index 3320aea..788eaa7 100644
--- a/res/drawable/ic_pattern.xml
+++ b/res/drawable/ic_pattern.xml
@@ -20,18 +20,18 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
- android:fillColor="?attr/colorAccent"
+ android:fillColor="?android:attr/colorAccent"
android:pathData="M4,4m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0" />
<path
- android:fillColor="?attr/colorAccent"
+ android:fillColor="?android:attr/colorAccent"
android:pathData="M4,12m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0" />
<path
- android:fillColor="?attr/colorAccent"
+ android:fillColor="?android:attr/colorAccent"
android:pathData="M12,4m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0" />
<path
- android:fillColor="?attr/colorAccent"
+ android:fillColor="?android:attr/colorAccent"
android:pathData="M20,12m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0" />
<path
- android:fillColor="?attr/colorAccent"
+ android:fillColor="?android:attr/colorAccent"
android:pathData="M20,18c-0.93,0 -1.7,0.64 -1.93,1.5h-4.14c-0.22,-0.86 -1,-1.5 -1.93,-1.5s-1.7,0.64 -1.93,1.5H5.93c-0.05,-0.18 -0.12,-0.35 -0.21,-0.51l5.28,-5.28C11.29,13.89 11.63,14 12,14c1.1,0 2,-0.9 2,-2c0,-0.37 -0.11,-0.71 -0.28,-1.01l5.28,-5.28C19.29,5.89 19.63,6 20,6c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2s-2,0.9 -2,2c0,0.37 0.11,0.71 0.28,1.01l-5.28,5.28C12.71,10.11 12.37,10 12,10c-1.1,0 -2,0.9 -2,2c0,0.37 0.11,0.71 0.28,1.01l-5.28,5.28C4.71,18.11 4.37,18 4,18c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c0.93,0 1.7,-0.64 1.93,-1.5h4.14c0.22,0.86 1,1.5 1.93,1.5s1.7,-0.64 1.93,-1.5h4.14c0.22,0.86 1,1.5 1.93,1.5c1.1,0 2,-0.9 2,-2S21.1,18 20,18z" />
</vector>
diff --git a/res/drawable/ic_pin.xml b/res/drawable/ic_pin.xml
index d8c3ae3..682e934 100644
--- a/res/drawable/ic_pin.xml
+++ b/res/drawable/ic_pin.xml
@@ -20,6 +20,6 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
- android:fillColor="?attr/colorAccent"
+ android:fillColor="?android:attr/colorAccent"
android:pathData="M20,4L4,4A2,2 0,0 0,2 6L2,18a2,2 0,0 0,2 2L20,20a2,2 0,0 0,2 -2L22,6A2,2 0,0 0,20 4ZM7.1,15L5.9,15L5.9,10.2L4.7,10.2L4.7,9L7.1,9v6ZM13.2,11.4A1.2,1.2 0,0 1,12 12.6L10.8,12.6v1.2h2.4L13.2,15L9.6,15L9.6,12.6a1.2,1.2 0,0 1,1.2 -1.2L12,11.4L12,10.2L9.6,10.2L9.6,9L12,9a1.2,1.2 0,0 1,1.2 1.2v1.2ZM19.3,11.1a0.9,0.9 0,0 1,-0.9 0.9,0.9 0.9,0 0,1 0.9,0.9v0.9A1.2,1.2 0,0 1,18.1 15L15.7,15L15.7,13.8h2.4L18.1,12.6L16.9,12.6L16.9,11.4h1.2L18.1,10.2L15.7,10.2L15.7,9h2.4a1.2,1.2 0,0 1,1.2 1.2v0.9Z" />
</vector>
diff --git a/res/drawable/ic_upload.xml b/res/drawable/ic_upload.xml
new file mode 100644
index 0000000..f95ffd4
--- /dev/null
+++ b/res/drawable/ic_upload.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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="24.0dp"
+ android:height="24.0dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M18,15v3H6v-3H4v3c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-3H18z M7,9l1.41,1.41L11,7.83V16h2V7.83l2.59,2.58L17,9l-5-5L7,9z" />
+</vector>
diff --git a/res/drawable/progress_horizontal.xml b/res/drawable/progress_horizontal.xml
deleted file mode 100644
index f2a4cc4..0000000
--- a/res/drawable/progress_horizontal.xml
+++ /dev/null
@@ -1,38 +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.
--->
-
-<layer-list
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-
- <item
- android:id="@android:id/background">
- <shape>
- <corners android:radius="8dp" />
- <solid android:color="?androidprv:attr/colorSurfaceVariant" />
- </shape>
- </item>
-
- <item
- android:id="@android:id/progress">
- <clip>
- <shape>
- <corners android:radius="8dp" />
- <solid android:color="?android:attr/textColorPrimary" />
- </shape>
- </clip>
- </item>
-</layer-list>
diff --git a/res/layout-land/request_manage_credentials.xml b/res/layout-land/request_manage_credentials.xml
new file mode 100644
index 0000000..0c7bded
--- /dev/null
+++ b/res/layout-land/request_manage_credentials.xml
@@ -0,0 +1,140 @@
+<?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:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:weightSum="2">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ style="@style/RequestManageCredentialsHeaderLandscape">
+
+ <ScrollView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scrollbars="none">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/credential_management_app_icon"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:contentDescription="@null" />
+
+ <TextView
+ android:id="@+id/credential_management_app_title"
+ style="@style/RequestManageCredentialsTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/credential_management_app_description"
+ style="@style/RequestManageCredentialsDescription"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/request_manage_credentials_description" />
+
+ </LinearLayout>
+
+ </ScrollView>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_weight="1">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <androidx.coordinatorlayout.widget.CoordinatorLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="true">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/apps_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <LinearLayout
+ android:id="@+id/button_panel"
+ style="@style/RequestManageCredentialsButtonPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:id="@+id/dont_allow_button"
+ style="@style/RequestManageCredentialsDontAllowButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/request_manage_credentials_dont_allow" />
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+
+ <Button
+ android:id="@+id/allow_button"
+ style="@style/RequestManageCredentialsAllowButton"
+ android:theme="@style/RoundedCornerButtonTheme"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/request_manage_credentials_allow" />
+
+ </LinearLayout>
+
+ </RelativeLayout>
+
+ <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
+ android:id="@+id/extended_fab"
+ style="@style/RequestManageCredentialsFab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/request_manage_credentials_more"
+ android:theme="@style/Theme.CollapsingToolbar.Settings"
+ app:backgroundTint="?android:attr/colorAccent"
+ app:elevation="3dp"
+ app:icon="@drawable/ic_arrow_downward"
+ app:iconTint="?android:attr/textColorPrimary"
+ app:layout_anchor="@id/apps_list"
+ app:layout_anchorGravity="bottom|center" />
+
+ </androidx.coordinatorlayout.widget.CoordinatorLayout>
+
+ </RelativeLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/res/layout/card_preference_layout.xml b/res/layout/card_preference_layout.xml
index bcaeb86..90e3388 100644
--- a/res/layout/card_preference_layout.xml
+++ b/res/layout/card_preference_layout.xml
@@ -29,6 +29,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="-8dp"
- layout="@layout/preference_material" />
+ layout="@layout/settingslib_preference" />
</com.google.android.material.card.MaterialCardView>
</FrameLayout>
diff --git a/res/layout/face_enroll_education.xml b/res/layout/face_enroll_education.xml
index a8455da..53a584e 100644
--- a/res/layout/face_enroll_education.xml
+++ b/res/layout/face_enroll_education.xml
@@ -38,7 +38,7 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginVertical="12dp">
+ android:layout_marginTop="-32dp">
<com.google.android.setupdesign.view.IllustrationVideoView
android:id="@+id/illustration_default"
@@ -51,11 +51,13 @@
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/illustration_lottie"
android:layout_width="match_parent"
- android:layout_height="340dp"
- android:scaleType="fitCenter"
- android:visibility="invisible"
+ android:layout_height="400dp"
+ android:layout_marginTop="-48dp"
+ android:scaleType="centerCrop"
+ android:visibility="gone"
app:lottie_autoPlay="true"
- app:lottie_loop="true" />
+ app:lottie_loop="true"
+ app:lottie_speed="1.5" />
<ImageView
android:id="@+id/illustration_accessibility"
diff --git a/res/layout/manage_apps_filter_spinner.xml b/res/layout/manage_apps_filter_spinner.xml
new file mode 100644
index 0000000..8283bb8
--- /dev/null
+++ b/res/layout/manage_apps_filter_spinner.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@android:color/transparent">
+
+ <com.android.settingslib.widget.settingsspinner.SettingsSpinner
+ android:id="@+id/filter_spinner"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="8dp"
+ android:theme="@style/Widget.PopupWindow.Settings"/>
+</FrameLayout>
diff --git a/res/layout/remove_account_button.xml b/res/layout/remove_account_button.xml
index 6b47c37..070ecc5 100644
--- a/res/layout/remove_account_button.xml
+++ b/res/layout/remove_account_button.xml
@@ -20,13 +20,14 @@
android:orientation="vertical">
<Button
- android:id="@+id/button"
- android:text="@string/remove_account_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="20dip"
- android:layout_marginBottom="12dip"
- android:gravity="center" />
+ android:id="@+id/button"
+ android:text="@string/remove_account_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="20dp"
+ android:layout_marginBottom="12dp"
+ android:gravity="center"
+ style="@style/ActionPrimaryButton" />
</LinearLayout>
diff --git a/res/layout/request_manage_credentials.xml b/res/layout/request_manage_credentials.xml
index ee3751c..c8167b6 100644
--- a/res/layout/request_manage_credentials.xml
+++ b/res/layout/request_manage_credentials.xml
@@ -52,6 +52,7 @@
<Button
android:id="@+id/allow_button"
style="@style/RequestManageCredentialsAllowButton"
+ android:theme="@style/RoundedCornerButtonTheme"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/request_manage_credentials_allow"/>
@@ -70,8 +71,8 @@
app:layout_anchorGravity="bottom|center"
app:elevation="3dp"
app:icon="@drawable/ic_arrow_downward"
- app:iconTint="?android:attr/colorAccent"
- app:backgroundTint="?android:attr/colorPrimary"
+ app:iconTint="?android:attr/textColorPrimary"
+ app:backgroundTint="?android:attr/colorAccent"
android:theme="@style/Theme.CollapsingToolbar.Settings"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 0b26c13..db525d5 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -103,9 +103,7 @@
<color name="homepage_wallpaper_background">#E51AD1</color>
<color name="homepage_notification_background">#DD4C9D</color>
- <color name="contextual_card_stroke_color">#1f000000</color>
<color name="contextual_card_dismissal_background">@*android:color/material_grey_100</color>
- <color name="contextual_card_background">@*android:color/background_device_default_light</color>
<!-- End of dashboard/homepage icon background colors -->
<color name="switchbar_background_color">@*android:color/material_grey_600</color>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b99dfc7..60b8cd2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -856,8 +856,6 @@
<!-- 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] -->
- <string name="security_settings_face_settings_top_intro">Use Face Unlock to unlock your device, sign in to apps, and confirm payments.</string>
- <!-- Text shown in face settings explaining what your face can be used for. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_footer">Use your face to unlock your phone or for authentication in apps, like when you sign in or approve a purchase.\n\nKeep in mind:\nYou can only have one face set up at a time. To add another face, delete the current one.\n\nLooking at the phone can unlock it when you don\u2019t intend to.\n\nYour phone can be unlocked by someone else if it\u2019s held up to your face.\n\nYour phone can be unlocked by someone who looks a lot like you, like an identical sibling.</string>
<!-- Text shown in face settings explaining what your face can be used for. Used when attention checking is not supported. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_footer_attention_not_supported">Use your face to unlock your phone or for authentication in apps, like when you sign in or approve a purchase.\n\nKeep in mind:\nYou can only have one face set up at a time. To add another face, delete the current one.\n\nLooking at the phone can unlock it when you don\u2019t intend to.\n\nYour phone can be unlocked by someone else if it\u2019s held up to your face, even if your eyes are closed.\n\nYour phone can be unlocked by someone who looks a lot like you, like an identical sibling.</string>
@@ -3168,8 +3166,8 @@
<string name="wallpaper_settings_title">Wallpaper</string>
<!-- Styles & Wallpapers settings title [CHAR LIMIT=30] -->
<string name="style_and_wallpaper_settings_title">Wallpaper & style</string>
- <!-- Summary for the top level Styles & wallpapers Settings [CHAR LIMIT=NONE]-->
- <string name="wallpaper_dashboard_summary">Colors, themed icons, app grid</string>
+ <!-- Summary for the top level wallpapers settings [CHAR LIMIT=NONE]-->
+ <string name="wallpaper_dashboard_summary">Home, lock screen</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] -->
@@ -6791,9 +6789,9 @@
<string name="cert_not_installed">Certificate not installed</string>
<!-- Title of screen shown to the user when an app requests to manage the user's KeyChain credentials [CHAR LIMIT=NONE] -->
- <string name="request_manage_credentials_title">Allow <xliff:g id="app_name" example="Ping">%s</xliff:g> to install certificates on this device?</string>
+ <string name="request_manage_credentials_title">Allow <b><xliff:g id="app_name" example="Ping">^1</xliff:g></b> to install certificates on this device?</string>
<!-- Description of screen shown to the user when an app requests to manage the user's KeyChain credentials [CHAR LIMIT=NONE] -->
- <string name="request_manage_credentials_description">These certificates will identify you to the apps and URLs below</string>
+ <string name="request_manage_credentials_description">These certificates will verify you by sharing your device\u2019s unique ID with the apps and URLs below</string>
<!-- Label for button to not allow an app to manage the user's KeyChain credentials [CHAR_LIMIT=50] -->
<string name="request_manage_credentials_dont_allow">Don\u2019t allow</string>
<!-- Label for button to allow an app to manage the user's KeyChain credentials [CHAR_LIMIT=50] -->
@@ -6805,7 +6803,9 @@
<!-- Summary if there is no certificate management app [CHAR_LIMIT=NONE] -->
<string name="no_certificate_management_app">None</string>
<!-- Summary of preference if there is a certificate management app [CHAR LIMIT=NONE] -->
- <string name="certificate_management_app_description">Certificates installed by this app identify you to the apps and URLs below</string>
+ <string name="certificate_management_app_description">Certificates will verify you when you use the apps and URLs below</string>
+ <!-- Label for button to uninstall all certificates installed by the credential management app [CHAR LIMIT=30] -->
+ <string name="uninstall_certs_credential_management_app">Uninstall certificates</string>
<!-- Label for button to remove the credential management app [CHAR LIMIT=30] -->
<string name="remove_credential_management_app">Remove</string>
<!-- List item found in the credential management app's authentication policy [CHAR LIMIT=NONE] -->
@@ -11676,7 +11676,7 @@
<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>
+ <string name="one_handed_title">One-handed mode</string>
<!-- Preference Switch for enabling one handed [CHAR LIMIT=60] -->
<string name="one_handed_mode_enabled">Use one-handed mode</string>
<!-- Preference Switch for app taps to exit one handed [CHAR LIMIT=60] -->
@@ -11691,6 +11691,19 @@
<string name="one_handed_timeout_long">12 seconds</string>
<!-- Search keywords for "One-Handed" settings [CHAR_LIMIT=NONE] -->
<string name="keywords_one_handed">reachability</string>
+ <!-- Category title for one handed swipe down [CHAR_LIMIT=60] -->
+ <string name="one_handed_mode_swipe_down_category">Swipe down to</string>
+ <!-- One-handed mode Intro Text [CHAR_LIMIT=NONE] -->
+ <string name="one_handed_mode_intro_text">To use one handed mode, swipe down from the bottom edge of the screen. To use this feature, make sure gesture navigation is turned on in system navigation settings.</string>
+ <!-- One-handed mode pull down screen into reach action title [CHAR_LIMIT=60] -->
+ <string name="one_handed_action_pull_down_screen_title">Pull screen into reach</string>
+ <!-- One-handed mode pull down screen into reach action title [CHAR_LIMIT=NONE] -->
+ <string name="one_handed_action_pull_down_screen_summary">The top of the screen will move into reach of your thumb.</string>
+ <!-- One-handed mode show notification action [CHAR_LIMIT=60] -->
+ <string name="one_handed_action_show_notification_title">Show notifications</string>
+ <!-- One-handed mode show notification action [CHAR_LIMIT=NONE] -->
+ <string name="one_handed_action_show_notification_summary">Notification and settings will appear.</string>
+ <!-- One-handed mode Intro text for gesture navigation [CHAR_LIMIT=NONE] -->
<!-- Summary text for ambient display double tap [CHAR LIMIT=NONE]-->
<string name="ambient_display_summary">To check time, notifications, and other info, double-tap your screen.</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 6021a7c..63ea86e 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -13,7 +13,8 @@
limitations under the License.
-->
-<resources>
+<resources
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="Widget.ActionBar.Base"
parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid"/>
@@ -404,12 +405,6 @@
<item name="android:progressDrawable">@drawable/ring_progress</item>
</style>
- <style name="HorizontalProgressBarStyle"
- parent="android:style/Widget.Material.ProgressBar.Horizontal">
- <item name="android:progressDrawable">@drawable/progress_horizontal</item>
- <item name="android:scaleY">0.5</item>
- </style>
-
<style name="ActionPrimaryButton" parent="android:Widget.DeviceDefault.Button.Colored">
<item name="android:theme">@style/RoundedCornerThemeOverlay</item>
</style>
@@ -417,6 +412,8 @@
<style name="RoundedCornerThemeOverlay">
<item name="android:buttonCornerRadius">24dp</item>
+ <item name="android:paddingStart">16dp</item>
+ <item name="android:paddingEnd">16dp</item>
</style>
<style name="LockPatternContainerStyle">
@@ -470,11 +467,9 @@
<item name="android:layout_marginBottom">@dimen/contextual_card_vertical_margin</item>
<item name="android:layout_marginStart">@dimen/contextual_card_side_margin</item>
<item name="android:layout_marginEnd">@dimen/contextual_card_side_margin</item>
- <item name="cardBackgroundColor">@color/contextual_card_background</item>
+ <item name="cardBackgroundColor">?androidprv:attr/colorSurface</item>
<item name="cardCornerRadius">@dimen/contextual_card_corner_radius</item>
<item name="cardElevation">0dp</item>
- <item name="strokeColor">@color/contextual_card_stroke_color</item>
- <item name="strokeWidth">1dp</item>
<item name="rippleColor">?android:attr/colorControlHighlight</item>
</style>
@@ -799,10 +794,19 @@
<item name="android:background">?android:colorBackground</item>
</style>
+ <style name="RoundedCornerButtonTheme">
+ <item name="android:buttonCornerRadius">50dp</item>
+ <item name="android:paddingStart">20dp</item>
+ <item name="android:paddingEnd">20dp</item>
+ <item name="android:paddingTop">18dp</item>
+ <item name="android:paddingBottom">18dp</item>
+ </style>
+
<style name="RequestManageCredentialsAllowButton" parent="@style/ActionPrimaryButton">
<item name="android:fontFamily">google-sans-medium</item>
<item name="android:textSize">14sp</item>
<item name="android:textAllCaps">false</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="RequestManageCredentialsDontAllowButton"
@@ -810,13 +814,13 @@
<item name="android:fontFamily">google-sans-medium</item>
<item name="android:textSize">14sp</item>
<item name="android:textAllCaps">false</item>
- <item name="android:textColor">?android:attr/colorAccent</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="RequestManageCredentialsFab">
<item name="android:textSize">14sp</item>
<item name="android:textAllCaps">false</item>
- <item name="android:textColor">?android:attr/colorAccent</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:layout_marginBottom">12dp</item>
</style>
@@ -828,6 +832,13 @@
<item name="android:orientation">vertical</item>
</style>
+ <style name="RequestManageCredentialsHeaderLandscape">
+ <item name="android:paddingStart">24dp</item>
+ <item name="android:paddingEnd">24dp</item>
+ <item name="android:paddingTop">24dp</item>
+ <item name="android:paddingBottom">24dp</item>
+ </style>
+
<style name="RequestManageCredentialsTitle">
<item name="android:layout_marginTop">24dp</item>
<item name="android:textSize">36sp</item>
@@ -838,6 +849,7 @@
<item name="android:layout_marginTop">24dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:alpha">0.7</item>
</style>
<style name="AppAuthenticationPolicyItem">
diff --git a/res/values/themes.xml b/res/values/themes.xml
index df7d433..4c5cdb7 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -32,7 +32,6 @@
<item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:datePickerDialogTheme">@style/PickerDialogTheme.Settings</item>
- <item name="android:progressBarStyleHorizontal">@style/HorizontalProgressBarStyle</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
<item name="face_layout_theme">@style/FaceLayoutTheme</item>
diff --git a/res/xml/credential_management_app_fragment.xml b/res/xml/credential_management_app_fragment.xml
index d4b61ac..7a5403b 100644
--- a/res/xml/credential_management_app_fragment.xml
+++ b/res/xml/credential_management_app_fragment.xml
@@ -27,19 +27,11 @@
android:order="-10000"
settings:controller="com.android.settings.security.CredentialManagementAppHeaderController"/>
- <com.android.settingslib.widget.TopIntroPreference
- android:key="top_intro_request_manage_credentials"
- android:order="-9999"
- android:title="@string/request_manage_credentials_description"
- settings:searchable="false"/>
-
<!-- Buttons -->
<com.android.settingslib.widget.ActionButtonsPreference
android:key="buttons"
android:selectable="true"
android:order="-9998"
- settings:allowDividerAbove="true"
- settings:allowDividerBelow="true"
settings:controller="com.android.settings.security.CredentialManagementAppButtonsController"/>
<!-- Authentication Policy -->
@@ -47,7 +39,6 @@
android:key="authentication_policy"
android:layout="@layout/preference_category_no_label"
android:title="@string/summary_placeholder"
- settings:allowDividerAbove="true"
settings:controller="com.android.settings.security.CredentialManagementAppPolicyController"/>
</PreferenceScreen>
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index 1f4895e..6de9c1a 100644
--- a/res/xml/gestures.xml
+++ b/res/xml/gestures.xml
@@ -34,13 +34,6 @@
settings:controller="com.android.settings.gestures.SwipeToNotificationPreferenceController" />
<Preference
- android:key="gesture_swipe_bottom_to_notification"
- android:title="@string/swipe_bottom_to_notifications_title"
- android:fragment="com.android.settings.gestures.SwipeBottomToNotificationSettings"
- settings:searchable="false"
- settings:controller="com.android.settings.gestures.SwipeBottomToNotificationPreferenceController" />
-
- <Preference
android:key="gesture_double_tap_power_input_summary"
android:title="@string/double_tap_power_for_camera_title"
android:fragment="com.android.settings.gestures.DoubleTapPowerSettings"
diff --git a/res/xml/one_handed_settings.xml b/res/xml/one_handed_settings.xml
index b2c7de9..f46b7ea 100644
--- a/res/xml/one_handed_settings.xml
+++ b/res/xml/one_handed_settings.xml
@@ -21,12 +21,6 @@
android:persistent="false"
android:title="@string/one_handed_title">
- <com.android.settingslib.widget.MainSwitchPreference
- android:key="gesture_one_handed_mode_enabled"
- android:title="@string/one_handed_mode_enabled"
- settings:keywords="@string/keywords_one_handed"
- settings:controller="com.android.settings.gestures.OneHandedEnablePreferenceController"/>
-
<com.android.settingslib.widget.LayoutPreference
android:key="one_handed_header"
android:layout="@layout/one_handed_header"
@@ -35,16 +29,31 @@
settings:allowDividerBelow="false"
settings:searchable="false"/>
- <SwitchPreference
- android:key="gesture_app_taps_to_exit"
- android:title="@string/one_handed_app_taps_to_exit"
- settings:controller="com.android.settings.gestures.OneHandedAppTapsExitPreferenceController"/>
+ <com.android.settingslib.widget.MainSwitchPreference
+ android:key="gesture_one_handed_mode_enabled_main_switch"
+ android:title="@string/one_handed_mode_enabled"
+ settings:keywords="@string/keywords_one_handed"
+ settings:controller="com.android.settings.gestures.OneHandedMainSwitchPreferenceController"/>
- <ListPreference
- android:key="gesture_one_handed_timeout"
- android:entries="@array/one_handed_timeout_title"
- android:entryValues="@array/one_handed_timeout_values"
- android:persistent="false"
- android:title="@string/one_handed_timeout_title"
- settings:controller="com.android.settings.gestures.OneHandedTimeoutPreferenceController"/>
+ <com.android.settingslib.widget.TopIntroPreference
+ android:key="gesture_one_handed_mode_intro_text"
+ android:title="@string/one_handed_mode_intro_text"/>
+
+ <PreferenceCategory
+ android:key="gesture_one_handed_mode_swipe_down"
+ android:title="@string/one_handed_mode_swipe_down_category">
+
+ <com.android.settingslib.widget.RadioButtonPreference
+ android:key="gesture_one_handed_action_pull_screen_down"
+ android:title="@string/one_handed_action_pull_down_screen_title"
+ android:summary="@string/one_handed_action_pull_down_screen_summary"
+ settings:controller="com.android.settings.gestures.OneHandedActionPullDownPrefController"/>
+
+ <com.android.settingslib.widget.RadioButtonPreference
+ android:key="gesture_one_handed_action_show_notification"
+ android:title="@string/one_handed_action_show_notification_title"
+ android:summary="@string/one_handed_action_show_notification_summary"
+ settings:controller="com.android.settings.gestures.OneHandedActionShowNotificationPrefController"/>
+
+ </PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml
index 6d7c0ba..4529a01 100644
--- a/res/xml/security_settings_face.xml
+++ b/res/xml/security_settings_face.xml
@@ -19,10 +19,6 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/security_settings_face_preference_title">
- <com.android.settingslib.widget.TopIntroPreference
- android:title="@string/security_settings_face_settings_top_intro"
- settings:searchable="false"/>
-
<PreferenceCategory
android:key="security_settings_face_unlock_category"
android:title="@string/security_settings_face_settings_use_face_category"
diff --git a/res/xml/storage_category_fragment.xml b/res/xml/storage_category_fragment.xml
index fb62bee..08f3f27 100644
--- a/res/xml/storage_category_fragment.xml
+++ b/res/xml/storage_category_fragment.xml
@@ -19,7 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/storage_settings">
- <Preference
+ <com.android.settings.widget.CardPreference
android:key="free_up_space"
android:order="4"
android:title="@string/storage_free_up_space_title"
diff --git a/res/xml/storage_dashboard_fragment.xml b/res/xml/storage_dashboard_fragment.xml
index fff3235..8edf4bf 100644
--- a/res/xml/storage_dashboard_fragment.xml
+++ b/res/xml/storage_dashboard_fragment.xml
@@ -38,7 +38,7 @@
android:icon="@drawable/ic_storage"
android:order="3"
settings:controller="com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchPreferenceController"/>
- <Preference
+ <com.android.settings.widget.CardPreference
android:key="free_up_space"
android:order="4"
android:title="@string/storage_free_up_space_title"
diff --git a/res/xml/swipe_bottom_to_notification_settings.xml b/res/xml/swipe_bottom_to_notification_settings.xml
deleted file mode 100644
index 2a75c14..0000000
--- a/res/xml/swipe_bottom_to_notification_settings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 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/swipe_bottom_to_notifications_title">
-
- <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"
- android:title="@string/swipe_bottom_to_notifications_title"
- android:summary="@string/swipe_bottom_to_notifications_summary"
- settings:controller="com.android.settings.gestures.SwipeBottomToNotificationPreferenceController"
- settings:allowDividerAbove="true" />
-
-</PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
index fe08d6b..98090ac 100644
--- a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
@@ -78,10 +78,12 @@
// Settings animated image.
final int animatedImageRes = arguments.getInt(
AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES);
- mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
- .authority(mComponentName.getPackageName())
- .appendPath(String.valueOf(animatedImageRes))
- .build();
+ if (animatedImageRes > 0) {
+ mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+ .authority(mComponentName.getPackageName())
+ .appendPath(String.valueOf(animatedImageRes))
+ .build();
+ }
// Settings html description.
mHtmlDescription = arguments.getCharSequence(AccessibilitySettings.EXTRA_HTML_DESCRIPTION);
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index 9d94858..9349071 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -396,10 +396,12 @@
// Settings animated image.
final int animatedImageRes = arguments.getInt(
AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES);
- mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
- .authority(mComponentName.getPackageName())
- .appendPath(String.valueOf(animatedImageRes))
- .build();
+ if (animatedImageRes > 0) {
+ mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+ .authority(mComponentName.getPackageName())
+ .appendPath(String.valueOf(animatedImageRes))
+ .build();
+ }
// Get Accessibility service name.
mPackageName = getAccessibilityServiceInfo().getResolveInfo().loadLabel(
diff --git a/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java b/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java
index b4dbf3d..238e937 100644
--- a/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java
+++ b/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java
@@ -17,16 +17,19 @@
package com.android.settings.accounts;
import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.widget.FooterPreference;
public class EnterpriseDisclosurePreferenceController extends BasePreferenceController {
-
private final EnterprisePrivacyFeatureProvider mFeatureProvider;
public EnterpriseDisclosurePreferenceController(Context context, String key) {
@@ -37,6 +40,16 @@
}
@Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ final CharSequence disclosure = getDisclosure();
+ if (disclosure == null) {
+ return;
+ }
+ updateFooterPreference(screen, disclosure);
+ }
+
+ @Override
public int getAvailabilityStatus() {
if (getDisclosure() == null) {
return UNSUPPORTED_ON_DEVICE;
@@ -49,12 +62,18 @@
return mFeatureProvider.getDeviceOwnerDisclosure();
}
- @Override
- public void updateState(Preference preference) {
- final CharSequence disclosure = getDisclosure();
- if (disclosure == null) {
- return;
- }
- preference.setTitle(disclosure);
+ void updateFooterPreference(PreferenceScreen screen, CharSequence disclosure) {
+ final FooterPreference footerPreference = screen.findPreference(getPreferenceKey());
+ footerPreference.setTitle(disclosure);
+ footerPreference.setLearnMoreAction(view -> {
+ mContext.startActivity(new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS));
+ });
+ final String learnMoreContentDescription = mContext.getString(
+ R.string.footer_learn_more_content_description, getLabelName());
+ footerPreference.setLearnMoreContentDescription(learnMoreContentDescription);
+ }
+
+ private String getLabelName() {
+ return mContext.getString(R.string.header_add_an_account);
}
}
diff --git a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java
index 79cae92..1f0777a 100644
--- a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java
@@ -118,7 +118,8 @@
final UserManager userManager =
(UserManager) mContext.getSystemService(Context.USER_SERVICE);
final BatteryEntry entry = new BatteryEntry(mContext, /* handler */null, userManager,
- mUidBatteryConsumer, /* isHidden */ false, /* packages */ null, mPackageName);
+ mUidBatteryConsumer, /* isHidden */ false,
+ mUidBatteryConsumer.getUid(), /* packages */ null, mPackageName);
AdvancedPowerUsageDetail.startBatteryDetailPage(mParent.getActivity(), mParent,
entry, mBatteryPercent);
} else {
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 62513db..7509a78 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -434,7 +434,7 @@
final Activity activity = getActivity();
final FrameLayout pinnedHeader = mRootView.findViewById(R.id.pinned_header);
mSpinnerHeader = activity.getLayoutInflater()
- .inflate(R.layout.apps_filter_spinner, pinnedHeader, false);
+ .inflate(R.layout.manage_apps_filter_spinner, pinnedHeader, false);
mFilterSpinner = mSpinnerHeader.findViewById(R.id.filter_spinner);
mFilterAdapter = new FilterSpinnerAdapter(this);
mFilterSpinner.setAdapter(mFilterAdapter);
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 09d8e71..580c753 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -29,6 +29,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
@@ -36,9 +37,12 @@
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
+import com.google.android.setupdesign.GlifLayout;
import com.google.android.setupdesign.span.LinkSpan;
+import com.google.android.setupdesign.template.RequireScrollMixin;
import com.google.android.setupdesign.util.DynamicColorPalette;
/**
@@ -180,6 +184,29 @@
launchConfirmLock(getConfirmLockTitleResId());
}
}
+
+ final GlifLayout layout = getLayout();
+ mFooterBarMixin = layout.getMixin(FooterBarMixin.class);
+ mFooterBarMixin.setPrimaryButton(getPrimaryFooterButton());
+ mFooterBarMixin.setSecondaryButton(getSecondaryFooterButton(), true /* usePrimaryStyle */);
+ mFooterBarMixin.getSecondaryButton().setVisibility(View.INVISIBLE);
+
+ final RequireScrollMixin requireScrollMixin = layout.getMixin(RequireScrollMixin.class);
+ requireScrollMixin.requireScrollWithButton(this, getPrimaryFooterButton(),
+ getMoreButtonTextRes(), this::onNextButtonClick);
+ requireScrollMixin.setOnRequireScrollStateChangedListener(
+ scrollNeeded -> {
+ // Update text of primary button from "More" to "Agree".
+ final int primaryButtonTextRes = scrollNeeded
+ ? getMoreButtonTextRes()
+ : getAgreeButtonTextRes();
+ getPrimaryFooterButton().setText(this, primaryButtonTextRes);
+
+ // Show secondary button once scroll is completed.
+ if (!scrollNeeded) {
+ getSecondaryFooterButton().setVisibility(View.VISIBLE);
+ }
+ });
}
@Override
@@ -335,4 +362,16 @@
}
return mIconColorFilter;
}
+
+ @NonNull
+ protected abstract FooterButton getPrimaryFooterButton();
+
+ @NonNull
+ protected abstract FooterButton getSecondaryFooterButton();
+
+ @StringRes
+ protected abstract int getAgreeButtonTextRes();
+
+ @StringRes
+ protected abstract int getMoreButtonTextRes();
}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index d564547..8e733b4 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -26,6 +26,10 @@
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollIntroduction;
@@ -34,11 +38,9 @@
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.span.LinkSpan;
-import com.google.android.setupdesign.template.RequireScrollMixin;
import java.util.List;
@@ -51,6 +53,8 @@
private FaceManager mFaceManager;
private FaceFeatureProvider mFaceFeatureProvider;
+ @Nullable private FooterButton mPrimaryFooterButton;
+ @Nullable private FooterButton mSecondaryFooterButton;
@Override
protected void onCancelButtonClick(View view) {
@@ -81,32 +85,6 @@
mFaceFeatureProvider = FeatureFactory.getFactory(getApplicationContext())
.getFaceFeatureProvider();
- mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
- mFooterBarMixin.setSecondaryButton(
- new FooterButton.Builder(this)
- .setText(R.string.security_settings_face_enroll_introduction_no_thanks)
- .setListener(this::onSkipButtonClick)
- .setButtonType(FooterButton.ButtonType.NEXT)
- .setTheme(R.style.SudGlifButton_Primary)
- .build(),
- true /* usePrimaryStyle */);
-
- FooterButton.Builder nextButtonBuilder = new FooterButton.Builder(this)
- .setText(R.string.security_settings_face_enroll_introduction_agree)
- .setButtonType(FooterButton.ButtonType.OPT_IN)
- .setTheme(R.style.SudGlifButton_Primary);
- if (maxFacesEnrolled()) {
- nextButtonBuilder.setListener(this::onNextButtonClick);
- mFooterBarMixin.setPrimaryButton(nextButtonBuilder.build());
- } else {
- final FooterButton agreeButton = nextButtonBuilder.build();
- mFooterBarMixin.setPrimaryButton(agreeButton);
- final RequireScrollMixin requireScrollMixin = getLayout().getMixin(
- RequireScrollMixin.class);
- requireScrollMixin.requireScrollWithButton(this, agreeButton,
- R.string.security_settings_face_enroll_introduction_more,
- this::onNextButtonClick);
- }
// This path is an entry point for SetNewPasswordController, e.g.
// adb shell am start -a android.app.action.SET_NEW_PASSWORD
@@ -232,4 +210,44 @@
public void onClick(LinkSpan span) {
// TODO(b/110906762)
}
+
+ @Override
+ @NonNull
+ protected FooterButton getPrimaryFooterButton() {
+ if (mPrimaryFooterButton == null) {
+ mPrimaryFooterButton = new FooterButton.Builder(this)
+ .setText(R.string.security_settings_face_enroll_introduction_agree)
+ .setButtonType(FooterButton.ButtonType.OPT_IN)
+ .setListener(this::onNextButtonClick)
+ .setTheme(R.style.SudGlifButton_Primary)
+ .build();
+ }
+ return mPrimaryFooterButton;
+ }
+
+ @Override
+ @NonNull
+ protected FooterButton getSecondaryFooterButton() {
+ if (mSecondaryFooterButton == null) {
+ mSecondaryFooterButton = new FooterButton.Builder(this)
+ .setText(R.string.security_settings_face_enroll_introduction_no_thanks)
+ .setListener(this::onSkipButtonClick)
+ .setButtonType(FooterButton.ButtonType.NEXT)
+ .setTheme(R.style.SudGlifButton_Primary)
+ .build();
+ }
+ return mSecondaryFooterButton;
+ }
+
+ @Override
+ @StringRes
+ protected int getAgreeButtonTextRes() {
+ return R.string.security_settings_fingerprint_enroll_introduction_agree;
+ }
+
+ @Override
+ @StringRes
+ protected int getMoreButtonTextRes() {
+ return R.string.security_settings_face_enroll_introduction_more;
+ }
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 18b1116..5142e21 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -27,6 +27,10 @@
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollIntroduction;
@@ -35,10 +39,8 @@
import com.android.settingslib.HelpUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.span.LinkSpan;
-import com.google.android.setupdesign.template.RequireScrollMixin;
import java.util.List;
@@ -47,6 +49,8 @@
private static final String TAG = "FingerprintIntro";
private FingerprintManager mFingerprintManager;
+ @Nullable private FooterButton mPrimaryFooterButton;
+ @Nullable private FooterButton mSecondaryFooterButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -69,29 +73,6 @@
iconDelete.getDrawable().setColorFilter(getIconColorFilter());
iconInfo.getDrawable().setColorFilter(getIconColorFilter());
iconLink.getDrawable().setColorFilter(getIconColorFilter());
-
- mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
- mFooterBarMixin.setSecondaryButton(
- new FooterButton.Builder(this)
- .setText(getNegativeButtonTextId())
- .setListener(this::onSkipButtonClick)
- .setButtonType(FooterButton.ButtonType.NEXT)
- .setTheme(R.style.SudGlifButton_Primary)
- .build(),
- true /* usePrimaryStyle */);
-
- final FooterButton nextButton = new FooterButton.Builder(this)
- .setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
- .setListener(this::onNextButtonClick)
- .setButtonType(FooterButton.ButtonType.OPT_IN)
- .setTheme(R.style.SudGlifButton_Primary)
- .build();
-
- mFooterBarMixin.setPrimaryButton(nextButton);
- final RequireScrollMixin requireScrollMixin =
- getLayout().getMixin(RequireScrollMixin.class);
- requireScrollMixin.requireScrollWithButton(this, nextButton,
- R.string.security_settings_face_enroll_introduction_more, this::onNextButtonClick);
}
int getNegativeButtonTextId() {
@@ -216,4 +197,44 @@
}
}
}
+
+ @Override
+ @NonNull
+ protected FooterButton getPrimaryFooterButton() {
+ if (mPrimaryFooterButton == null) {
+ mPrimaryFooterButton = new FooterButton.Builder(this)
+ .setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
+ .setListener(this::onNextButtonClick)
+ .setButtonType(FooterButton.ButtonType.OPT_IN)
+ .setTheme(R.style.SudGlifButton_Primary)
+ .build();
+ }
+ return mPrimaryFooterButton;
+ }
+
+ @Override
+ @NonNull
+ protected FooterButton getSecondaryFooterButton() {
+ if (mSecondaryFooterButton == null) {
+ mSecondaryFooterButton = new FooterButton.Builder(this)
+ .setText(getNegativeButtonTextId())
+ .setListener(this::onSkipButtonClick)
+ .setButtonType(FooterButton.ButtonType.NEXT)
+ .setTheme(R.style.SudGlifButton_Primary)
+ .build();
+ }
+ return mSecondaryFooterButton;
+ }
+
+ @Override
+ @StringRes
+ protected int getAgreeButtonTextRes() {
+ return R.string.security_settings_fingerprint_enroll_introduction_agree;
+ }
+
+ @Override
+ @StringRes
+ protected int getMoreButtonTextRes() {
+ return R.string.security_settings_face_enroll_introduction_more;
+ }
}
diff --git a/src/com/android/settings/core/SubSettingLauncher.java b/src/com/android/settings/core/SubSettingLauncher.java
index 893d592..0a6966f 100644
--- a/src/com/android/settings/core/SubSettingLauncher.java
+++ b/src/com/android/settings/core/SubSettingLauncher.java
@@ -28,6 +28,7 @@
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
+import com.android.settings.Utils;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.transition.SettingsTransitionHelper.TransitionType;
@@ -181,8 +182,10 @@
@VisibleForTesting
void launchAsUser(Intent intent, UserHandle userHandle) {
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ if (!Utils.isPageTransitionEnabled(mContext)) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ }
mContext.startActivityAsUser(intent, userHandle);
}
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 0de86f5..a03a4f9 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -360,6 +360,11 @@
// Icon provided by the content provider overrides any static icon.
if (tile.getMetaData() != null
&& tile.getMetaData().containsKey(META_DATA_PREFERENCE_ICON_URI)) {
+ // Set a transparent color before starting to fetch the real icon, this is necessary
+ // to avoid preference padding change.
+ setPreferenceIcon(preference, tile, forceRoundedIcon, mContext.getPackageName(),
+ Icon.createWithResource(mContext, android.R.color.transparent));
+
ThreadUtils.postOnBackgroundThread(() -> {
final Intent intent = tile.getIntent();
String packageName = null;
diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
index 8c25a05..f8d5f96 100644
--- a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
+++ b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
@@ -16,15 +16,25 @@
package com.android.settings.display;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.provider.Settings.Secure.CAMERA_AUTOROTATE;
+import static com.android.settings.display.SmartAutoRotateController.hasSufficientPermission;
+import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable;
+
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.SensorPrivacyManager;
+import android.os.PowerManager;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.view.RotationPolicy;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
@@ -41,8 +51,21 @@
private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
private Preference mPreference;
+ private final SensorPrivacyManager mPrivacyManager;
+ private final PowerManager mPowerManager;
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ refreshSummary(mPreference);
+ }
+ };
+
public SmartAutoRotatePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
+ mPrivacyManager = SensorPrivacyManager.getInstance(context);
+ mPrivacyManager
+ .addSensorPrivacyListener(CAMERA, (sensor, enabled) -> refreshSummary(mPreference));
+ mPowerManager = context.getSystemService(PowerManager.class);
}
@Override
@@ -59,6 +82,8 @@
@Override
public void onStart() {
+ mContext.registerReceiver(mReceiver,
+ new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
if (mRotationPolicyListener == null) {
mRotationPolicyListener = new RotationPolicy.RotationPolicyListener() {
@Override
@@ -75,12 +100,27 @@
@Override
public void onStop() {
+ mContext.unregisterReceiver(mReceiver);
if (mRotationPolicyListener != null) {
RotationPolicy.unregisterRotationPolicyListener(mContext,
mRotationPolicyListener);
}
}
+ /**
+ * Need this because all controller tests use Roboelectric. No easy way to mock this service,
+ * so we mock the call we need
+ */
+ @VisibleForTesting
+ boolean isCameraLocked() {
+ return mPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA);
+ }
+
+ @VisibleForTesting
+ boolean isPowerSaveMode() {
+ return mPowerManager.isPowerSaveMode();
+ }
+
@Override
public CharSequence getSummary() {
int activeStringId = R.string.auto_rotate_option_off;
@@ -89,7 +129,11 @@
mContext.getContentResolver(),
CAMERA_AUTOROTATE,
0, UserHandle.USER_CURRENT);
- activeStringId = cameraRotate == 1 ? R.string.auto_rotate_option_face_based
+ activeStringId = cameraRotate == 1 && isRotationResolverServiceAvailable(mContext)
+ && hasSufficientPermission(mContext)
+ && !isCameraLocked()
+ && !isPowerSaveMode()
+ ? R.string.auto_rotate_option_face_based
: R.string.auto_rotate_option_on;
}
return mContext.getString(activeStringId);
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
index f461fe1..7d722fc 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
@@ -100,9 +100,6 @@
} else {
disclosure.append(mResources.getString(R.string.do_disclosure_generic));
}
- disclosure.append(mResources.getString(R.string.do_disclosure_learn_more_separator));
- disclosure.append(mResources.getString(R.string.learn_more),
- new EnterprisePrivacySpan(mContext), 0);
return disclosure;
}
diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
index 891b6d6..1dc572d 100644
--- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
@@ -55,6 +55,7 @@
import com.android.settingslib.utils.StringUtil;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.List;
/**
@@ -66,6 +67,7 @@
static final boolean USE_FAKE_DATA = false;
private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 20;
private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
+ private static final String MEDIASERVER_PACKAGE_NAME = "mediaserver";
private final String mPreferenceKey;
@VisibleForTesting
@@ -303,27 +305,17 @@
final ArrayList<BatteryEntry> results = new ArrayList<>();
final List<UidBatteryConsumer> uidBatteryConsumers =
mBatteryUsageStats.getUidBatteryConsumers();
+
+ // Sort to have all apps with "real" UIDs first, followed by apps that are supposed
+ // to be combined with the real ones.
+ uidBatteryConsumers.sort(Comparator.comparingInt(
+ consumer -> consumer.getUid() == getRealUid(consumer) ? 0 : 1));
+
for (int i = 0, size = uidBatteryConsumers.size(); i < size; i++) {
final UidBatteryConsumer consumer = uidBatteryConsumers.get(i);
- int realUid = consumer.getUid();
+ final int uid = getRealUid(consumer);
- // Check if this UID is a shared GID. If so, we combine it with the OWNER's
- // actual app UID.
- if (isSharedGid(consumer.getUid())) {
- realUid = UserHandle.getUid(UserHandle.USER_SYSTEM,
- UserHandle.getAppIdFromSharedAppGid(consumer.getUid()));
- }
-
- // Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc).
- if (isSystemUid(realUid)
- && !"mediaserver".equals(consumer.getPackageWithHighestDrain())) {
- // Use the system UID for all UIDs running in their own sandbox that
- // are not apps. We exclude mediaserver because we already are expected to
- // report that as a separate item.
- realUid = Process.SYSTEM_UID;
- }
-
- final String[] packages = mPackageManager.getPackagesForUid(consumer.getUid());
+ final String[] packages = mPackageManager.getPackagesForUid(uid);
if (mBatteryUtils.shouldHideUidBatteryConsumerUnconditionally(consumer, packages)) {
continue;
}
@@ -333,11 +325,11 @@
continue;
}
- final int index = batteryEntryList.indexOfKey(realUid);
+ final int index = batteryEntryList.indexOfKey(uid);
if (index < 0) {
// New entry.
- batteryEntryList.put(realUid, new BatteryEntry(mContext, mHandler, mUserManager,
- consumer, isHidden, packages, null, loadDataInBackground));
+ batteryEntryList.put(uid, new BatteryEntry(mContext, mHandler, mUserManager,
+ consumer, isHidden, uid, packages, null, loadDataInBackground));
} else {
// Combine BatterySippers if we already have one with this UID.
final BatteryEntry existingSipper = batteryEntryList.valueAt(index);
@@ -385,7 +377,8 @@
for (int i = 0, size = userBatteryConsumers.size(); i < size; i++) {
final UserBatteryConsumer consumer = userBatteryConsumers.get(i);
results.add(new BatteryEntry(mContext, mHandler, mUserManager,
- consumer, /* isHidden */ true, null, null, loadDataInBackground));
+ consumer, /* isHidden */ true, Process.INVALID_UID, null, null,
+ loadDataInBackground));
}
}
@@ -400,6 +393,27 @@
return results;
}
+ private int getRealUid(UidBatteryConsumer consumer) {
+ int realUid = consumer.getUid();
+
+ // Check if this UID is a shared GID. If so, we combine it with the OWNER's
+ // actual app UID.
+ if (isSharedGid(consumer.getUid())) {
+ realUid = UserHandle.getUid(UserHandle.USER_SYSTEM,
+ UserHandle.getAppIdFromSharedAppGid(consumer.getUid()));
+ }
+
+ // Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc).
+ if (isSystemUid(realUid)
+ && !MEDIASERVER_PACKAGE_NAME.equals(consumer.getPackageWithHighestDrain())) {
+ // Use the system UID for all UIDs running in their own sandbox that
+ // are not apps. We exclude mediaserver because we already are expected to
+ // report that as a separate item.
+ realUid = Process.SYSTEM_UID;
+ }
+ return realUid;
+ }
+
@VisibleForTesting
void setUsageSummary(Preference preference, BatteryEntry entry) {
// Only show summary when usage time is longer than one minute
diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
index ffbd2d9..3c9cbaa 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
@@ -272,7 +272,7 @@
final Map<String, BatteryHistEntry> entryMap = batteryHistoryMap.get(timestamp);
if (entryMap == null || entryMap.isEmpty()) {
Log.e(TAG, "abnormal entry list in the timestamp:"
- + ConvertUtils.utcToLocalTime(timestamp));
+ + ConvertUtils.utcToLocalTime(mPrefContext, timestamp));
continue;
}
// Averages the battery level in each time slot to avoid corner conditions.
@@ -287,7 +287,7 @@
Log.d(TAG, String.format(
"setBatteryHistoryMap() size=%d\nkeys=%s\nlevels=%s",
batteryHistoryMap.size(),
- utcToLocalTime(mBatteryHistoryKeys),
+ utcToLocalTime(mPrefContext, mBatteryHistoryKeys),
Arrays.toString(mBatteryHistoryLevels)));
// Loads item icon and label in the background.
@@ -496,9 +496,9 @@
if (mTrapezoidIndex < 0) {
return null;
}
- final String fromHour = ConvertUtils.utcToLocalTimeHour(
+ final String fromHour = ConvertUtils.utcToLocalTimeHour(mPrefContext,
mBatteryHistoryKeys[mTrapezoidIndex * 2], mIs24HourFormat);
- final String toHour = ConvertUtils.utcToLocalTimeHour(
+ final String toHour = ConvertUtils.utcToLocalTimeHour(mPrefContext,
mBatteryHistoryKeys[(mTrapezoidIndex + 1) * 2], mIs24HourFormat);
return String.format("%s - %s", fromHour, toHour);
}
@@ -584,11 +584,11 @@
mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference));
}
- private static String utcToLocalTime(long[] timestamps) {
+ private static String utcToLocalTime(Context context, long[] timestamps) {
final StringBuilder builder = new StringBuilder();
for (int index = 0; index < timestamps.length; index++) {
builder.append(String.format("%s| ",
- ConvertUtils.utcToLocalTime(timestamps[index])));
+ ConvertUtils.utcToLocalTime(context, timestamps[index])));
}
return builder.toString();
}
diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java
index ed64177..b721f14 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartView.java
@@ -56,14 +56,8 @@
private static final List<String> ACCESSIBILITY_SERVICE_NAMES =
Arrays.asList("SwitchAccessService", "TalkBackService", "JustSpeakService");
- // For drawing the percentage information.
- private static final String[] PERCENTAGES = new String[] {
- formatPercentage(/*percentage=*/ 100, /*round=*/ true),
- formatPercentage(/*percentage=*/ 50, /*round=*/ true),
- formatPercentage(/*percentage=*/ 0, /*round=*/ true)};
-
private static final int DEFAULT_TRAPEZOID_COUNT = 12;
- private static final int DEFAULT_TIMESTAMP_COUNT = 4;
+ private static final int DEFAULT_TIMESTAMP_COUNT = 5;
private static final int DIVIDER_COLOR = Color.parseColor("#CDCCC5");
private static final long UPDATE_STATE_DELAYED_TIME = 500L;
@@ -82,6 +76,7 @@
private float mTrapezoidVOffset;
private float mTrapezoidHOffset;
private boolean mIsSlotsClickabled;
+ private String[] mPercentages = getPercentages();
@VisibleForTesting int mSelectedIndex;
@VisibleForTesting String[] mTimestamps;
@@ -96,7 +91,7 @@
new Rect[] {new Rect(), new Rect(), new Rect()};
// For drawing the timestamp information.
private final Rect[] mTimestampsBounds =
- new Rect[] {new Rect(), new Rect(), new Rect(), new Rect()};
+ new Rect[] {new Rect(), new Rect(), new Rect(), new Rect(), new Rect()};
@VisibleForTesting
Handler mHandler = new Handler();
@@ -107,6 +102,7 @@
private Paint mTextPaint;
private Paint mDividerPaint;
private Paint mTrapezoidPaint;
+
@VisibleForTesting
Paint mTrapezoidCurvePaint = null;
private TrapezoidSlot[] mTrapezoidSlots;
@@ -201,12 +197,13 @@
if (mTimestamps == null) {
mTimestamps = new String[DEFAULT_TIMESTAMP_COUNT];
}
- final long timeSlotOffset = DateUtils.HOUR_IN_MILLIS * 8;
+ final long timeSlotOffset = DateUtils.HOUR_IN_MILLIS * 6;
final boolean is24HourFormat = DateFormat.is24HourFormat(getContext());
for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) {
mTimestamps[index] =
ConvertUtils.utcToLocalTimeHour(
- latestTimestamp - (3 - index) * timeSlotOffset,
+ getContext(),
+ latestTimestamp - (4 - index) * timeSlotOffset,
is24HourFormat);
}
requestLayout();
@@ -217,9 +214,9 @@
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Measures text bounds and updates indent configuration.
if (mTextPaint != null) {
- for (int index = 0; index < PERCENTAGES.length; index++) {
+ for (int index = 0; index < mPercentages.length; index++) {
mTextPaint.getTextBounds(
- PERCENTAGES[index], 0, PERCENTAGES[index].length(),
+ mPercentages[index], 0, mPercentages[index].length(),
mPercentageBounds[index]);
}
// Updates the indent configurations.
@@ -396,7 +393,7 @@
private void drawPercentage(Canvas canvas, int index, float offsetY) {
if (mTextPaint != null) {
canvas.drawText(
- PERCENTAGES[index],
+ mPercentages[index],
getWidth() - mPercentageBounds[index].width() - mPercentageBounds[index].left,
offsetY + mPercentageBounds[index].height() *.5f,
mTextPaint);
@@ -429,7 +426,7 @@
final float baselineX = mDividerWidth * .5f;
final float offsetX = mDividerWidth + unitWidth;
for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) {
- xOffsets[index] = baselineX + index * offsetX * 4;
+ xOffsets[index] = baselineX + index * offsetX * 3;
}
drawTimestamp(canvas, xOffsets);
}
@@ -443,11 +440,11 @@
getTimestampY(0), mTextPaint);
// Draws the last timestamp info.
canvas.drawText(
- mTimestamps[3],
- xOffsets[3] - mTimestampsBounds[3].width() - mTimestampsBounds[3].left,
- getTimestampY(3), mTextPaint);
+ mTimestamps[4],
+ xOffsets[4] - mTimestampsBounds[4].width() - mTimestampsBounds[4].left,
+ getTimestampY(4), mTextPaint);
// Draws the rest of timestamp info since it is located in the center.
- for (int index = 1; index <= 2; index++) {
+ for (int index = 1; index <= 3; index++) {
canvas.drawText(
mTimestamps[index],
xOffsets[index] -
@@ -544,6 +541,13 @@
&& mLevels[trapezoidIndex + 1] != 0;
}
+ private static String[] getPercentages() {
+ return new String[] {
+ formatPercentage(/*percentage=*/ 100, /*round=*/ true),
+ formatPercentage(/*percentage=*/ 50, /*round=*/ true),
+ formatPercentage(/*percentage=*/ 0, /*round=*/ true)};
+ }
+
@VisibleForTesting
static boolean isAccessibilityEnabled(Context context) {
final AccessibilityManager accessibilityManager =
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index 78ab962..0478c8b 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -159,12 +159,15 @@
private final Context mContext;
private final BatteryConsumer mBatteryConsumer;
+ private final int mUid;
private final boolean mIsHidden;
@ConvertUtils.ConsumerType
private final int mConsumerType;
@BatteryConsumer.PowerComponent
private final int mPowerComponentId;
private long mUsageDurationMs;
+ private long mTimeInForegroundMs;
+ private long mTimeInBackgroundMs;
public String name;
public Drawable icon;
@@ -180,13 +183,13 @@
}
public BatteryEntry(Context context, Handler handler, UserManager um,
- @NonNull BatteryConsumer batteryConsumer, boolean isHidden, String[] packages,
+ @NonNull BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
String packageName) {
- this(context, handler, um, batteryConsumer, isHidden, packages, packageName, true);
+ this(context, handler, um, batteryConsumer, isHidden, uid, packages, packageName, true);
}
public BatteryEntry(Context context, Handler handler, UserManager um,
- @NonNull BatteryConsumer batteryConsumer, boolean isHidden, String[] packages,
+ @NonNull BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
String packageName, boolean loadDataInBackground) {
sHandler = handler;
mContext = context;
@@ -196,11 +199,11 @@
mPowerComponentId = -1;
if (batteryConsumer instanceof UidBatteryConsumer) {
+ mUid = uid;
mConsumerType = ConvertUtils.CONSUMER_TYPE_UID_BATTERY;
mConsumedPower = batteryConsumer.getConsumedPower();
UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
- int uid = uidBatteryConsumer.getUid();
if (mDefaultPackageName == null) {
// Apps should only have one package
if (packages != null && packages.length == 1) {
@@ -222,7 +225,12 @@
}
}
getQuickNameIconForUid(uid, packages, loadDataInBackground);
+ mTimeInForegroundMs =
+ uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND);
+ mTimeInBackgroundMs =
+ uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND);
} else if (batteryConsumer instanceof UserBatteryConsumer) {
+ mUid = Process.INVALID_UID;
mConsumerType = ConvertUtils.CONSUMER_TYPE_USER_BATTERY;
mConsumedPower = batteryConsumer.getConsumedPower();
final NameAndIcon nameAndIcon = getNameAndIconFromUserId(
@@ -239,6 +247,7 @@
double appsPowerMah, long usageDurationMs) {
mContext = context;
mBatteryConsumer = null;
+ mUid = Process.INVALID_UID;
mIsHidden = false;
mPowerComponentId = powerComponentId;
mConsumedPower =
@@ -261,6 +270,7 @@
double devicePowerMah, double appsPowerMah) {
mContext = context;
mBatteryConsumer = null;
+ mUid = Process.INVALID_UID;
mIsHidden = false;
mPowerComponentId = powerComponentId;
@@ -438,7 +448,7 @@
*/
public String getKey() {
if (mBatteryConsumer instanceof UidBatteryConsumer) {
- return Integer.toString(((UidBatteryConsumer) mBatteryConsumer).getUid());
+ return Integer.toString(mUid);
} else if (mBatteryConsumer instanceof UserBatteryConsumer) {
return "U|" + ((UserBatteryConsumer) mBatteryConsumer).getUserId();
} else {
@@ -482,11 +492,7 @@
* Returns the UID of the app described by this entry.
*/
public int getUid() {
- if (mBatteryConsumer instanceof UidBatteryConsumer) {
- return ((UidBatteryConsumer) mBatteryConsumer).getUid();
- } else {
- return Process.INVALID_UID;
- }
+ return mUid;
}
/**
@@ -494,8 +500,7 @@
*/
public long getTimeInForegroundMs() {
if (mBatteryConsumer instanceof UidBatteryConsumer) {
- return ((UidBatteryConsumer) mBatteryConsumer).getTimeInStateMs(
- UidBatteryConsumer.STATE_FOREGROUND);
+ return mTimeInForegroundMs;
} else {
return mUsageDurationMs;
}
@@ -506,8 +511,7 @@
*/
public long getTimeInBackgroundMs() {
if (mBatteryConsumer instanceof UidBatteryConsumer) {
- return ((UidBatteryConsumer) mBatteryConsumer).getTimeInStateMs(
- UidBatteryConsumer.STATE_BACKGROUND);
+ return mTimeInBackgroundMs;
} else {
return 0;
}
@@ -526,9 +530,15 @@
*/
public void add(BatteryConsumer batteryConsumer) {
mConsumedPower += batteryConsumer.getConsumedPower();
- if (mDefaultPackageName == null && batteryConsumer instanceof UidBatteryConsumer) {
- mDefaultPackageName =
- ((UidBatteryConsumer) batteryConsumer).getPackageWithHighestDrain();
+ if (batteryConsumer instanceof UidBatteryConsumer) {
+ UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
+ mTimeInForegroundMs += uidBatteryConsumer.getTimeInStateMs(
+ UidBatteryConsumer.STATE_FOREGROUND);
+ mTimeInBackgroundMs += uidBatteryConsumer.getTimeInStateMs(
+ UidBatteryConsumer.STATE_BACKGROUND);
+ if (mDefaultPackageName == null) {
+ mDefaultPackageName = uidBatteryConsumer.getPackageWithHighestDrain();
+ }
}
}
diff --git a/src/com/android/settings/fuelgauge/BatteryHistEntry.java b/src/com/android/settings/fuelgauge/BatteryHistEntry.java
index d83d814..4c8ecee 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistEntry.java
@@ -184,7 +184,8 @@
@Override
public String toString() {
- final String recordAtDateTime = ConvertUtils.utcToLocalTime(mTimestamp);
+ final String recordAtDateTime =
+ ConvertUtils.utcToLocalTime(/*context=*/ null, mTimestamp);
final StringBuilder builder = new StringBuilder()
.append("\nBatteryHistEntry{")
.append(String.format("\n\tpackage=%s|label=%s|uid=%d|userId=%d|isHidden=%b",
diff --git a/src/com/android/settings/fuelgauge/ConvertUtils.java b/src/com/android/settings/fuelgauge/ConvertUtils.java
index 1980564..01f510e 100644
--- a/src/com/android/settings/fuelgauge/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/ConvertUtils.java
@@ -17,6 +17,7 @@
import android.content.ContentValues;
import android.content.Context;
import android.os.BatteryUsageStats;
+import android.os.LocaleList;
import android.os.UserHandle;
import android.text.format.DateUtils;
import android.util.Log;
@@ -133,8 +134,8 @@
}
/** Converts UTC timestamp to human readable local time string. */
- public static String utcToLocalTime(long timestamp) {
- final Locale currentLocale = Locale.getDefault();
+ public static String utcToLocalTime(Context context, long timestamp) {
+ final Locale currentLocale = getLocale(context);
final String currentZoneId = TimeZone.getDefault().getID();
if (!currentZoneId.equals(sZoneId)
|| !currentLocale.equals(sLocale)
@@ -148,8 +149,9 @@
}
/** Converts UTC timestamp to local time hour data. */
- public static String utcToLocalTimeHour(long timestamp, boolean is24HourFormat) {
- final Locale currentLocale = Locale.getDefault();
+ public static String utcToLocalTimeHour(
+ Context context, long timestamp, boolean is24HourFormat) {
+ final Locale currentLocale = getLocale(context);
final String currentZoneId = TimeZone.getDefault().getID();
if (!currentZoneId.equals(sZoneIdForHour)
|| !currentLocale.equals(sLocaleForHour)
@@ -159,7 +161,7 @@
sZoneIdForHour = currentZoneId;
sIs24HourFormat = is24HourFormat;
sSimpleDateFormatForHour = new SimpleDateFormat(
- sIs24HourFormat ? "HH" : "h aa", currentLocale);
+ sIs24HourFormat ? "HH" : "h", currentLocale);
}
return sSimpleDateFormatForHour.format(new Date(timestamp))
.toLowerCase(currentLocale);
@@ -356,4 +358,15 @@
? entry3 : null;
}
}
+
+ @VisibleForTesting
+ static Locale getLocale(Context context) {
+ if (context == null) {
+ return Locale.getDefault();
+ }
+ final LocaleList locales =
+ context.getResources().getConfiguration().getLocales();
+ return locales != null && !locales.isEmpty() ? locales.get(0)
+ : Locale.getDefault();
+ }
}
diff --git a/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java b/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java
new file mode 100644
index 0000000..84ea8b6
--- /dev/null
+++ b/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java
@@ -0,0 +1,101 @@
+/*
+ * 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.gestures;
+
+import android.content.Context;
+import android.net.Uri;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+/**
+ * The controller to handle one-handed mode pull screen into reach preference.
+ **/
+public class OneHandedActionPullDownPrefController extends BasePreferenceController
+ implements OneHandedSettingsUtils.TogglesCallback, LifecycleObserver, OnStart, OnStop {
+
+ private final OneHandedSettingsUtils mUtils;
+
+ private Preference mPreference;
+
+ public OneHandedActionPullDownPrefController(Context context, String key) {
+ super(context, key);
+ mUtils = new OneHandedSettingsUtils(context);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (preference instanceof RadioButtonPreference) {
+ ((RadioButtonPreference) preference).setChecked(
+ !OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext));
+ }
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return (OneHandedSettingsUtils.isSupportOneHandedMode()
+ && OneHandedSettingsUtils.canEnableController(mContext))
+ ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!getPreferenceKey().equals(preference.getKey())) {
+ return false;
+ }
+ OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, false);
+ if (preference instanceof RadioButtonPreference) {
+ ((RadioButtonPreference) preference).setChecked(true);
+ }
+ return true;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ }
+
+ @Override
+ public void onStart() {
+ mUtils.registerToggleAwareObserver(this);
+ }
+
+ @Override
+ public void onStop() {
+ mUtils.unregisterToggleAwareObserver();
+ }
+
+ @Override
+ public void onChange(Uri uri) {
+ if (mPreference == null) {
+ return;
+ }
+ if (uri.equals(OneHandedSettingsUtils.ONE_HANDED_MODE_ENABLED_URI)) {
+ mPreference.setEnabled(OneHandedSettingsUtils.canEnableController(mContext));
+ } else if (uri.equals(OneHandedSettingsUtils.SHOW_NOTIFICATION_ENABLED_URI)) {
+ updateState(mPreference);
+ }
+ }
+}
diff --git a/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java b/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java
new file mode 100644
index 0000000..5644299
--- /dev/null
+++ b/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java
@@ -0,0 +1,101 @@
+/*
+ * 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.gestures;
+
+import android.content.Context;
+import android.net.Uri;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+/**
+ * The controller to handle one-handed mode show notification preference.
+ **/
+public class OneHandedActionShowNotificationPrefController extends BasePreferenceController
+ implements OneHandedSettingsUtils.TogglesCallback, LifecycleObserver, OnStart, OnStop {
+
+ private final OneHandedSettingsUtils mUtils;
+
+ private Preference mPreference;
+
+ public OneHandedActionShowNotificationPrefController(Context context, String key) {
+ super(context, key);
+ mUtils = new OneHandedSettingsUtils(context);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (preference instanceof RadioButtonPreference) {
+ ((RadioButtonPreference) preference).setChecked(
+ OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext));
+ }
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return (OneHandedSettingsUtils.isSupportOneHandedMode()
+ && OneHandedSettingsUtils.canEnableController(mContext))
+ ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!getPreferenceKey().equals(preference.getKey())) {
+ return false;
+ }
+ OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, true);
+ if (preference instanceof RadioButtonPreference) {
+ ((RadioButtonPreference) preference).setChecked(true);
+ }
+ return true;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ }
+
+ @Override
+ public void onStart() {
+ mUtils.registerToggleAwareObserver(this);
+ }
+
+ @Override
+ public void onStop() {
+ mUtils.unregisterToggleAwareObserver();
+ }
+
+ @Override
+ public void onChange(Uri uri) {
+ if (mPreference == null) {
+ return;
+ }
+ if (uri.equals(OneHandedSettingsUtils.ONE_HANDED_MODE_ENABLED_URI)) {
+ mPreference.setEnabled(OneHandedSettingsUtils.canEnableController(mContext));
+ } else if (uri.equals(OneHandedSettingsUtils.SHOW_NOTIFICATION_ENABLED_URI)) {
+ updateState(mPreference);
+ }
+ }
+}
diff --git a/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceController.java b/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceController.java
deleted file mode 100644
index 1cc7911..0000000
--- a/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceController.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import android.content.Context;
-import android.net.Uri;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.core.TogglePreferenceController;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
-
-/**
- * The Controller to handle app taps to exit of one-handed mode
- */
-public class OneHandedAppTapsExitPreferenceController extends TogglePreferenceController implements
- LifecycleObserver, OnStart, OnStop, OneHandedSettingsUtils.TogglesCallback {
-
- private final OneHandedSettingsUtils mUtils;
-
- private Preference mPreference;
-
- public OneHandedAppTapsExitPreferenceController(Context context, String key) {
- super(context, key);
-
- mUtils = new OneHandedSettingsUtils(context);
-
- // By default, app taps to stop one-handed is enabled, this will get default value once.
- OneHandedSettingsUtils.setTapsAppToExitEnabled(mContext, isChecked());
- }
-
- @Override
- public int getAvailabilityStatus() {
- return OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)
- ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreference = screen.findPreference(getPreferenceKey());
- }
-
- @Override
- public void updateState(Preference preference) {
- super.updateState(preference);
-
- final int availabilityStatus = getAvailabilityStatus();
- preference.setEnabled(
- availabilityStatus == AVAILABLE || availabilityStatus == AVAILABLE_UNSEARCHABLE);
- }
-
- @Override
- public boolean setChecked(boolean isChecked) {
- return OneHandedSettingsUtils.setTapsAppToExitEnabled(mContext, isChecked);
- }
-
- @Override
- public boolean isChecked() {
- return OneHandedSettingsUtils.isTapsAppToExitEnabled(mContext);
- }
-
- @Override
- public void onStart() {
- mUtils.registerToggleAwareObserver(this);
- }
-
- @Override
- public void onStop() {
- mUtils.unregisterToggleAwareObserver();
- }
-
- @Override
- public void onChange(Uri uri) {
- updateState(mPreference);
- }
-}
diff --git a/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java b/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java
index 1e9c240..e388585 100644
--- a/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java
+++ b/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java
@@ -19,38 +19,25 @@
import android.content.Context;
import com.android.settings.R;
-import com.android.settings.widget.SettingsMainSwitchPreferenceController;
+import com.android.settings.core.BasePreferenceController;
/**
* The controller to handle one-handed mode enable or disable state.
**/
-public class OneHandedEnablePreferenceController extends SettingsMainSwitchPreferenceController {
+public class OneHandedEnablePreferenceController extends BasePreferenceController {
- public OneHandedEnablePreferenceController(Context context, String key) {
- super(context, key);
+ public OneHandedEnablePreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
}
- @Override
public int getAvailabilityStatus() {
- return OneHandedSettingsUtils.isFeatureAvailable(mContext)
- ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
- }
-
- @Override
- public boolean setChecked(boolean isChecked) {
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, isChecked);
- OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, !isChecked);
- return true;
- }
-
- @Override
- public boolean isChecked() {
- return OneHandedSettingsUtils.isOneHandedModeEnabled(mContext);
+ return OneHandedSettingsUtils.isSupportOneHandedMode() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public CharSequence getSummary() {
return mContext.getText(
- isChecked() ? R.string.gesture_setting_on : R.string.gesture_setting_off);
+ OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)
+ ? R.string.gesture_setting_on : R.string.gesture_setting_off);
}
}
diff --git a/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceController.java b/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceController.java
new file mode 100644
index 0000000..043588e
--- /dev/null
+++ b/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceController.java
@@ -0,0 +1,56 @@
+/*
+ * 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.gestures;
+
+import android.content.Context;
+
+import com.android.settings.widget.SettingsMainSwitchPreferenceController;
+
+/**
+ * The controller to handle one-handed mode main switch enable or disable state.
+ **/
+public class OneHandedMainSwitchPreferenceController extends
+ SettingsMainSwitchPreferenceController {
+
+ public OneHandedMainSwitchPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return (OneHandedSettingsUtils.isSupportOneHandedMode()
+ && OneHandedSettingsUtils.getNavigationBarMode(mContext) != 0 /* 3-button mode */)
+ ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return OneHandedSettingsUtils.isOneHandedModeEnabled(mContext);
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ if (isChecked) {
+ // Set default value for TapsAppToExit and Timeout
+ OneHandedSettingsUtils.setTapsAppToExitEnabled(mContext, true);
+ OneHandedSettingsUtils.setTimeoutValue(mContext,
+ OneHandedSettingsUtils.OneHandedTimeout.MEDIUM.getValue());
+ }
+ OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, isChecked);
+ return true;
+ }
+}
diff --git a/src/com/android/settings/gestures/OneHandedSettingsUtils.java b/src/com/android/settings/gestures/OneHandedSettingsUtils.java
index 21998a6..a931129 100644
--- a/src/com/android/settings/gestures/OneHandedSettingsUtils.java
+++ b/src/com/android/settings/gestures/OneHandedSettingsUtils.java
@@ -26,6 +26,8 @@
import android.os.UserHandle;
import android.provider.Settings;
+import androidx.annotation.VisibleForTesting;
+
/**
* The Util to query one-handed mode settings config
*/
@@ -34,6 +36,10 @@
static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
static final int OFF = 0;
static final int ON = 1;
+ static final Uri ONE_HANDED_MODE_ENABLED_URI =
+ Settings.Secure.getUriFor(Settings.Secure.ONE_HANDED_MODE_ENABLED);
+ static final Uri SHOW_NOTIFICATION_ENABLED_URI =
+ Settings.Secure.getUriFor(Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED);
public enum OneHandedTimeout {
NEVER(0), SHORT(4), MEDIUM(8), LONG(12);
@@ -177,6 +183,21 @@
}
/**
+ * Set NavigationBar mode flag to Settings provider.
+ * @param context App context
+ * @param value Navigation bar mode:
+ * 0 = 3 button
+ * 1 = 2 button
+ * 2 = fully gestural
+ * @return true if the value was set, false on database errors.
+ */
+ @VisibleForTesting
+ public boolean setNavigationBarMode(Context context, String value) {
+ return Settings.Secure.putStringForUser(context.getContentResolver(),
+ Settings.Secure.NAVIGATION_MODE, value, UserHandle.myUserId());
+ }
+
+ /**
* Get NavigationBar mode flag from Settings provider.
* @param context App context
* @return Navigation bar mode:
@@ -190,12 +211,17 @@
}
/**
- *
+ * Check if One-handed mode settings controllers can enabled or disabled.
* @param context App context
- * @return Support One-Handed mode feature or not.
+ * @return true if controllers are able to enabled, false otherwise.
+ *
+ * Note: For better UX experience, just disabled controls that let users know to use
+ * this feature, they need to make sure gesture navigation is turned on in system
+ * navigation settings.
*/
- public static boolean isFeatureAvailable(Context context) {
- return isSupportOneHandedMode() && getNavigationBarMode(context) != 0;
+ public static boolean canEnableController(Context context) {
+ return (OneHandedSettingsUtils.isOneHandedModeEnabled(context)
+ && OneHandedSettingsUtils.getNavigationBarMode(context) != 0 /* 3-button mode */);
}
/**
@@ -218,9 +244,6 @@
private final class SettingsObserver extends ContentObserver {
private TogglesCallback mCallback;
- private final Uri mOneHandedEnabledAware = Settings.Secure.getUriFor(
- Settings.Secure.ONE_HANDED_MODE_ENABLED);
-
SettingsObserver(Handler handler) {
super(handler);
}
@@ -231,7 +254,8 @@
public void observe() {
final ContentResolver resolver = mContext.getContentResolver();
- resolver.registerContentObserver(mOneHandedEnabledAware, true, this);
+ resolver.registerContentObserver(ONE_HANDED_MODE_ENABLED_URI, true, this);
+ resolver.registerContentObserver(SHOW_NOTIFICATION_ENABLED_URI, true, this);
}
@Override
diff --git a/src/com/android/settings/gestures/OneHandedTimeoutPreferenceController.java b/src/com/android/settings/gestures/OneHandedTimeoutPreferenceController.java
deleted file mode 100644
index 8ce0e86..0000000
--- a/src/com/android/settings/gestures/OneHandedTimeoutPreferenceController.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import android.content.Context;
-import android.net.Uri;
-
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The Controller to handle one-handed mode timeout state.
- **/
-public class OneHandedTimeoutPreferenceController extends BasePreferenceController implements
- Preference.OnPreferenceChangeListener, LifecycleObserver, OnStart, OnStop,
- OneHandedSettingsUtils.TogglesCallback {
-
- private final Map<String, String> mTimeoutMap;
- private final OneHandedSettingsUtils mUtils;
-
- private Preference mTimeoutPreference;
-
- public OneHandedTimeoutPreferenceController(Context context, String preferenceKey) {
- super(context, preferenceKey);
-
- mTimeoutMap = new HashMap<>();
- initTimeoutMap();
- mUtils = new OneHandedSettingsUtils(context);
- }
-
- @Override
- public int getAvailabilityStatus() {
- return OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)
- ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object object) {
- if (!(preference instanceof ListPreference)) {
- return false;
- }
- final int newValue = Integer.parseInt((String) object);
- OneHandedSettingsUtils.setTimeoutValue(mContext, newValue);
- updateState(preference);
- return true;
- }
-
- @Override
- public void updateState(Preference preference) {
- super.updateState(preference);
- if (!(preference instanceof ListPreference)) {
- return;
- }
- final ListPreference listPreference = (ListPreference) preference;
- listPreference.setValue(getTimeoutValue());
-
- final int availabilityStatus = getAvailabilityStatus();
- preference.setEnabled(
- availabilityStatus == AVAILABLE || availabilityStatus == AVAILABLE_UNSEARCHABLE);
- }
-
- @Override
- public CharSequence getSummary() {
- if (OneHandedSettingsUtils.getTimeoutValue(mContext) == 0) {
- return mContext.getResources().getString(R.string.screensaver_settings_summary_never);
- }
- return String.format(mContext.getResources().getString(
- R.string.screen_timeout_summary), mTimeoutMap.get(getTimeoutValue()));
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mTimeoutPreference = screen.findPreference(mPreferenceKey);
- }
-
- @Override
- public void onStart() {
- mUtils.registerToggleAwareObserver(this);
- }
-
- @Override
- public void onStop() {
- mUtils.unregisterToggleAwareObserver();
- }
-
- @Override
- public void onChange(Uri uri) {
- updateState(mTimeoutPreference);
- }
-
- private String getTimeoutValue() {
- return String.valueOf(OneHandedSettingsUtils.getTimeoutValue(mContext));
- }
-
- private void initTimeoutMap() {
- if (mTimeoutMap.size() != 0) {
- return;
- }
-
- final String[] timeoutValues = mContext.getResources().getStringArray(
- R.array.one_handed_timeout_values);
- final String[] timeoutTitles = mContext.getResources().getStringArray(
- R.array.one_handed_timeout_title);
-
- if (timeoutValues.length != timeoutTitles.length) {
- return;
- }
-
- for (int i = 0; i < timeoutValues.length; i++) {
- mTimeoutMap.put(timeoutValues[i], timeoutTitles[i]);
- }
- }
-}
diff --git a/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceController.java
deleted file mode 100644
index ec81482..0000000
--- a/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceController.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-
-import android.content.Context;
-
-import com.android.settings.R;
-import com.android.settings.core.TogglePreferenceController;
-
-/**
- * Handles swipe bottom to expand notification panel gesture.
- **/
-public class SwipeBottomToNotificationPreferenceController extends TogglePreferenceController {
-
- public SwipeBottomToNotificationPreferenceController(Context context, String key) {
- super(context, key);
- }
-
- @Override
- public int getAvailabilityStatus() {
- return OneHandedSettingsUtils.isFeatureAvailable(mContext)
- ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
- }
-
- @Override
- public boolean isSliceable() {
- return true;
- }
-
- @Override
- public boolean isPublicSlice() {
- return true;
- }
-
- @Override
- public boolean setChecked(boolean isChecked) {
- if (isChecked) {
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
- }
- OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, isChecked);
- return true;
- }
-
- @Override
- public boolean isChecked() {
- return OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext);
- }
-
- @Override
- public CharSequence getSummary() {
- // This toggle preference summary will be updated in gesture preference page since we bound
- // it with entry preference in gesture.xml
- return mContext.getText(
- isChecked() ? R.string.gesture_setting_on : R.string.gesture_setting_off);
- }
-}
diff --git a/src/com/android/settings/gestures/SwipeBottomToNotificationSettings.java b/src/com/android/settings/gestures/SwipeBottomToNotificationSettings.java
deleted file mode 100644
index 9d85f11..0000000
--- a/src/com/android/settings/gestures/SwipeBottomToNotificationSettings.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-
-import com.android.settings.R;
-import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-
-/**
- * The Fragment for swipe bottom to notification gesture settings.
- */
-public class SwipeBottomToNotificationSettings extends DashboardFragment {
-
- private static final String TAG = "SwipeBottomToNotificationSettings";
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.SETTINGS_SWIPE_BOTTOM_TO_NOTIFICATION;
- }
-
- @Override
- protected String getLogTag() {
- return TAG;
- }
-
- @Override
- protected int getPreferenceScreenResId() {
- return R.xml.swipe_bottom_to_notification_settings;
- }
-
- public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider(R.xml.swipe_bottom_to_notification_settings) {
-
- @Override
- protected boolean isPageSearchEnabled(Context context) {
- if (!OneHandedSettingsUtils.isSupportOneHandedMode()) {
- return false;
- }
- return !OneHandedSettingsUtils.isOneHandedModeEnabled(context);
- }
- };
-}
diff --git a/src/com/android/settings/location/LocationInjectedServiceBasePreferenceController.java b/src/com/android/settings/location/LocationInjectedServiceBasePreferenceController.java
new file mode 100644
index 0000000..3b593b9
--- /dev/null
+++ b/src/com/android/settings/location/LocationInjectedServiceBasePreferenceController.java
@@ -0,0 +1,121 @@
+/*
+ * 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.location;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.location.SettingInjectorService;
+import android.os.UserHandle;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.Utils;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A abstract class which is responsible for creating the injected location services items.
+ * Developer needs to implement the {@link #injectLocationServices(PreferenceScreen)}.
+ */
+public abstract class LocationInjectedServiceBasePreferenceController
+ extends LocationBasePreferenceController implements LifecycleObserver{
+
+ private static final String TAG = "LocationPrefCtrl";
+ @VisibleForTesting
+ static final IntentFilter INTENT_FILTER_INJECTED_SETTING_CHANGED =
+ new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED);
+
+ @VisibleForTesting
+ AppSettingsInjector mInjector;
+ /** Receives UPDATE_INTENT */
+ @VisibleForTesting
+ BroadcastReceiver mInjectedSettingsReceiver;
+
+ public LocationInjectedServiceBasePreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public void init(DashboardFragment fragment) {
+ super.init(fragment);
+ mInjector = new AppSettingsInjector(mContext, getMetricsCategory());
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ injectLocationServices(screen);
+ }
+
+ /**
+ * Override this method to inject location services in preference screen.
+ * @param screen
+ */
+ protected abstract void injectLocationServices(PreferenceScreen screen);
+
+ @Override
+ public void onLocationModeChanged(int mode, boolean restricted) {
+ // As a safety measure, also reloads on location mode change to ensure the settings are
+ // up-to-date even if an affected app doesn't send the setting changed broadcast.
+ mInjector.reloadStatusMessages();
+ }
+
+ /** @OnLifecycleEvent(ON_RESUME) */
+ @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
+ public void onResume() {
+ if (mInjectedSettingsReceiver == null) {
+ mInjectedSettingsReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Received settings change intent: " + intent);
+ }
+ mInjector.reloadStatusMessages();
+ }
+ };
+ }
+ mContext.registerReceiver(
+ mInjectedSettingsReceiver, INTENT_FILTER_INJECTED_SETTING_CHANGED);
+ }
+
+ /** @OnLifecycleEvent(ON_PAUSE) */
+ @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
+ public void onPause() {
+ mContext.unregisterReceiver(mInjectedSettingsReceiver);
+ }
+
+ protected Map<Integer, List<Preference>> getLocationServices() {
+ // If location access is locked down by device policy then we only show injected settings
+ // for the primary profile.
+ final int profileUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
+
+ return mInjector.getInjectedSettings(mFragment.getPreferenceManager().getContext(),
+ (profileUserId != UserHandle.USER_NULL
+ && mLocationEnabler.getShareLocationEnforcedAdmin(profileUserId) != null)
+ ? UserHandle.myUserId() : UserHandle.USER_CURRENT);
+ }
+}
diff --git a/src/com/android/settings/location/LocationInjectedServicesForWorkPreferenceController.java b/src/com/android/settings/location/LocationInjectedServicesForWorkPreferenceController.java
index 571b4a7..b7e6cf2 100644
--- a/src/com/android/settings/location/LocationInjectedServicesForWorkPreferenceController.java
+++ b/src/com/android/settings/location/LocationInjectedServicesForWorkPreferenceController.java
@@ -20,6 +20,8 @@
import android.os.UserHandle;
import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
import com.android.settings.widget.RestrictedAppPreference;
@@ -30,7 +32,7 @@
* Retrieve the Location Services used in work profile user.
*/
public class LocationInjectedServicesForWorkPreferenceController extends
- LocationInjectedServicesPreferenceController {
+ LocationInjectedServiceBasePreferenceController {
private static final String TAG = "LocationWorkPrefCtrl";
public LocationInjectedServicesForWorkPreferenceController(Context context, String key) {
@@ -38,10 +40,10 @@
}
@Override
- public void updateState(Preference preference) {
- mCategoryLocationServices.removeAll();
+ protected void injectLocationServices(PreferenceScreen screen) {
+ final PreferenceCategory categoryLocationServices =
+ screen.findPreference(getPreferenceKey());
final Map<Integer, List<Preference>> prefs = getLocationServices();
- boolean show = false;
for (Map.Entry<Integer, List<Preference>> entry : prefs.entrySet()) {
for (Preference pref : entry.getValue()) {
if (pref instanceof RestrictedAppPreference) {
@@ -49,11 +51,8 @@
}
}
if (entry.getKey() != UserHandle.myUserId()) {
- LocationSettings.addPreferencesSorted(entry.getValue(),
- mCategoryLocationServices);
- show = true;
+ LocationSettings.addPreferencesSorted(entry.getValue(), categoryLocationServices);
}
}
- mCategoryLocationServices.setVisible(show);
}
}
diff --git a/src/com/android/settings/location/LocationInjectedServicesPreferenceController.java b/src/com/android/settings/location/LocationInjectedServicesPreferenceController.java
index 8573307..d623bae 100644
--- a/src/com/android/settings/location/LocationInjectedServicesPreferenceController.java
+++ b/src/com/android/settings/location/LocationInjectedServicesPreferenceController.java
@@ -15,25 +15,14 @@
*/
package com.android.settings.location;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.location.SettingInjectorService;
import android.os.UserHandle;
-import android.util.Log;
-import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
-import com.android.settings.Utils;
-import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.widget.RestrictedAppPreference;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
import java.util.List;
import java.util.Map;
@@ -41,42 +30,20 @@
/**
* Preference controller for the injected Location Services.
*/
-public class LocationInjectedServicesPreferenceController extends LocationBasePreferenceController
- implements LifecycleObserver, OnResume, OnPause {
+public class LocationInjectedServicesPreferenceController
+ extends LocationInjectedServiceBasePreferenceController {
private static final String TAG = "LocationPrefCtrl";
- @VisibleForTesting
- static final IntentFilter INTENT_FILTER_INJECTED_SETTING_CHANGED =
- new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED);
-
- protected PreferenceCategory mCategoryLocationServices;
- @VisibleForTesting
- AppSettingsInjector mInjector;
- /** Receives UPDATE_INTENT */
- @VisibleForTesting
- BroadcastReceiver mInjectedSettingsReceiver;
public LocationInjectedServicesPreferenceController(Context context, String key) {
super(context, key);
}
@Override
- public void init(DashboardFragment fragment) {
- super.init(fragment);
- mInjector = new AppSettingsInjector(mContext, getMetricsCategory());
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mCategoryLocationServices = screen.findPreference(getPreferenceKey());
- }
-
- @Override
- public void updateState(Preference preference) {
- mCategoryLocationServices.removeAll();
+ protected void injectLocationServices(PreferenceScreen screen) {
+ final PreferenceCategory categoryLocationServices =
+ screen.findPreference(getPreferenceKey());
final Map<Integer, List<Preference>> prefs = getLocationServices();
- boolean show = false;
for (Map.Entry<Integer, List<Preference>> entry : prefs.entrySet()) {
for (Preference pref : entry.getValue()) {
if (pref instanceof RestrictedAppPreference) {
@@ -84,53 +51,11 @@
}
}
if (entry.getKey() == UserHandle.myUserId()) {
- if (mCategoryLocationServices != null) {
+ if (categoryLocationServices != null) {
LocationSettings.addPreferencesSorted(entry.getValue(),
- mCategoryLocationServices);
+ categoryLocationServices);
}
- show = true;
}
}
- mCategoryLocationServices.setVisible(show);
- }
-
- @Override
- public void onLocationModeChanged(int mode, boolean restricted) {
- // As a safety measure, also reloads on location mode change to ensure the settings are
- // up-to-date even if an affected app doesn't send the setting changed broadcast.
- mInjector.reloadStatusMessages();
- }
-
- @Override
- public void onResume() {
- if (mInjectedSettingsReceiver == null) {
- mInjectedSettingsReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Received settings change intent: " + intent);
- }
- mInjector.reloadStatusMessages();
- }
- };
- }
- mContext.registerReceiver(
- mInjectedSettingsReceiver, INTENT_FILTER_INJECTED_SETTING_CHANGED);
- }
-
- @Override
- public void onPause() {
- mContext.unregisterReceiver(mInjectedSettingsReceiver);
- }
-
- protected Map<Integer, List<Preference>> getLocationServices() {
- // If location access is locked down by device policy then we only show injected settings
- // for the primary profile.
- final int profileUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
-
- return mInjector.getInjectedSettings(mFragment.getPreferenceManager().getContext(),
- (profileUserId != UserHandle.USER_NULL
- && mLocationEnabler.getShareLocationEnforcedAdmin(profileUserId) != null)
- ? UserHandle.myUserId() : UserHandle.USER_CURRENT);
}
}
diff --git a/src/com/android/settings/network/InternetPreferenceController.java b/src/com/android/settings/network/InternetPreferenceController.java
index 639bab5..a58e69a 100644
--- a/src/com/android/settings/network/InternetPreferenceController.java
+++ b/src/com/android/settings/network/InternetPreferenceController.java
@@ -65,7 +65,7 @@
@VisibleForTesting
static Map<Integer, Integer> sIconMap = new HashMap<>();
static {
- sIconMap.put(INTERNET_OFF, R.drawable.ic_no_internet_airplane);
+ sIconMap.put(INTERNET_OFF, R.drawable.ic_no_internet_unavailable);
sIconMap.put(INTERNET_NETWORKS_AVAILABLE, R.drawable.ic_no_internet_available);
sIconMap.put(INTERNET_WIFI, R.drawable.ic_wifi_signal_4);
sIconMap.put(INTERNET_CELLULAR, R.drawable.ic_network_cell);
diff --git a/src/com/android/settings/network/ProviderModelSlice.java b/src/com/android/settings/network/ProviderModelSlice.java
index cfaef53..1df77bc 100644
--- a/src/com/android/settings/network/ProviderModelSlice.java
+++ b/src/com/android/settings/network/ProviderModelSlice.java
@@ -20,6 +20,7 @@
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static com.android.settings.slices.CustomSliceRegistry.PROVIDER_MODEL_SLICE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
import android.annotation.ColorInt;
import android.app.PendingIntent;
@@ -64,7 +65,6 @@
public class ProviderModelSlice extends WifiSlice {
private static final String TAG = "ProviderModelSlice";
- protected static final String ACTION_TITLE_CONNECT_TO_CARRIER = "Connect_To_Carrier";
private final ProviderModelSliceHelper mHelper;
@@ -89,78 +89,77 @@
@Override
public Slice getSlice() {
// The provider model slice step:
- // First section: Add a Wi-Fi item which state is connected.
- // Second section: Add a carrier item.
- // Third section: Add the Wi-Fi items which are not connected.
- // Fourth section: If device has connection problem, this row show the message for user.
- @InternetUpdater.InternetType int internetType = getInternetType();
+ // First section: Add the Ethernet item.
+ // Second section: Add the carrier item.
+ // Third section: Add the Wi-Fi toggle item.
+ // Fourth section: Add the connected Wi-Fi item.
+ // Fifth section: Add the Wi-Fi items which are not connected.
+ // Sixth section: Add the See All item.
final ListBuilder listBuilder = mHelper.createListBuilder(getUri());
- if (mHelper.isAirplaneModeEnabled() && !mWifiManager.isWifiEnabled()
- && internetType != InternetUpdater.INTERNET_ETHERNET) {
- log("Airplane mode is enabled.");
- return listBuilder.build();
- }
-
int maxListSize = 0;
- List<WifiSliceItem> wifiList = null;
final NetworkProviderWorker worker = getWorker();
if (worker != null) {
- // get Wi-Fi list.
- wifiList = worker.getResults();
maxListSize = worker.getApRowCount();
} else {
log("network provider worker is null.");
}
- final boolean hasCarrier = mHelper.hasCarrier();
- log("hasCarrier: " + hasCarrier);
-
- // First section: Add a Ethernet or Wi-Fi item which state is connected.
- boolean isConnectedWifiAddedTop = false;
- final WifiSliceItem connectedWifiItem = mHelper.getConnectedWifiItem(wifiList);
- if (internetType == InternetUpdater.INTERNET_ETHERNET) {
+ // First section: Add the Ethernet item.
+ if (getInternetType() == InternetUpdater.INTERNET_ETHERNET) {
log("get Ethernet item which is connected");
listBuilder.addRow(createEthernetRow());
maxListSize--;
- } else {
- if (connectedWifiItem != null && internetType == InternetUpdater.INTERNET_WIFI) {
- log("get Wi-Fi item which is connected to internet");
- listBuilder.addRow(getWifiSliceItemRow(connectedWifiItem));
- isConnectedWifiAddedTop = true;
+ }
+
+ // Second section: Add the carrier item.
+ if (!mHelper.isAirplaneModeEnabled()) {
+ final boolean hasCarrier = mHelper.hasCarrier();
+ log("hasCarrier: " + hasCarrier);
+ if (hasCarrier) {
+ mHelper.updateTelephony();
+ listBuilder.addRow(
+ mHelper.createCarrierRow(
+ worker != null ? worker.getNetworkTypeDescription() : ""));
maxListSize--;
}
}
- // Second section: Add a carrier item.
- if (hasCarrier) {
- mHelper.updateTelephony();
- listBuilder.addRow(
- mHelper.createCarrierRow(
- worker != null ? worker.getNetworkTypeDescription() : ""));
- maxListSize--;
+ // Third section: Add the Wi-Fi toggle item.
+ final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
+ listBuilder.addRow(createWifiToggleRow(mContext, isWifiEnabled));
+ maxListSize--;
+ if (!isWifiEnabled) {
+ log("Wi-Fi is disabled");
+ return listBuilder.build();
+ }
+ List<WifiSliceItem> wifiList = (worker != null) ? worker.getResults() : null;
+ if (wifiList == null || wifiList.size() <= 0) {
+ log("Wi-Fi list is empty");
+ return listBuilder.build();
}
- // Third section: Add the connected Wi-Fi item to Wi-Fi list if the Ethernet is connected.
- if (connectedWifiItem != null && !isConnectedWifiAddedTop) {
+ // Fourth section: Add the connected Wi-Fi item.
+ final WifiSliceItem connectedWifiItem = mHelper.getConnectedWifiItem(wifiList);
+ if (connectedWifiItem != null) {
log("get Wi-Fi item which is connected");
listBuilder.addRow(getWifiSliceItemRow(connectedWifiItem));
maxListSize--;
}
- // Fourth section: Add the Wi-Fi items which are not connected.
- if (wifiList != null && wifiList.size() > 0) {
- log("get Wi-Fi items which are not connected. Wi-Fi items : " + wifiList.size());
-
- final List<WifiSliceItem> disconnectedWifiList = wifiList.stream()
- .filter(wifiSliceItem -> wifiSliceItem.getConnectedState()
- != WifiEntry.CONNECTED_STATE_CONNECTED)
- .limit(maxListSize - 1)
- .collect(Collectors.toList());
- for (WifiSliceItem item : disconnectedWifiList) {
- listBuilder.addRow(getWifiSliceItemRow(item));
- }
- listBuilder.addRow(getSeeAllRow());
+ // Fifth section: Add the Wi-Fi items which are not connected.
+ log("get Wi-Fi items which are not connected. Wi-Fi items : " + wifiList.size());
+ final List<WifiSliceItem> disconnectedWifiList = wifiList.stream()
+ .filter(item -> item.getConnectedState() != WifiEntry.CONNECTED_STATE_CONNECTED)
+ .limit(maxListSize - 1)
+ .collect(Collectors.toList());
+ for (WifiSliceItem item : disconnectedWifiList) {
+ listBuilder.addRow(getWifiSliceItemRow(item));
}
+
+ // Sixth section: Add the See All item.
+ log("add See-All");
+ listBuilder.addRow(getSeeAllRow());
+
return listBuilder.build();
}
@@ -269,6 +268,26 @@
.setSubtitle(mContext.getText(R.string.to_switch_networks_disconnect_ethernet));
}
+ /**
+ * @return a {@link ListBuilder.RowBuilder} of the Wi-Fi toggle.
+ */
+ protected ListBuilder.RowBuilder createWifiToggleRow(Context context, boolean isWifiEnabled) {
+ final Intent intent = new Intent(WIFI_SLICE_URI.toString())
+ .setData(WIFI_SLICE_URI)
+ .setClass(context, SliceBroadcastReceiver.class)
+ .putExtra(EXTRA_TOGGLE_STATE, !isWifiEnabled)
+ // The FLAG_RECEIVER_FOREGROUND flag is necessary to avoid the intent delay of
+ // the first sending after the device restarts
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+ final SliceAction toggleSliceAction = SliceAction.createToggle(pendingIntent,
+ null /* actionTitle */, isWifiEnabled);
+ return new ListBuilder.RowBuilder()
+ .setTitle(context.getString(R.string.wifi_settings))
+ .setPrimaryAction(toggleSliceAction);
+ }
+
protected ListBuilder.RowBuilder getSeeAllRow() {
final CharSequence title = mContext.getText(R.string.previous_connected_see_all);
final IconCompat icon = getSeeAllIcon();
@@ -295,31 +314,6 @@
}
@Override
- protected ListBuilder.RowBuilder getWifiSliceItemRow(WifiSliceItem wifiSliceItem) {
- final CharSequence title = wifiSliceItem.getTitle();
- final IconCompat levelIcon = getWifiSliceItemLevelIcon(wifiSliceItem);
- final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
- .setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
- .setTitle(title)
- .setSubtitle(wifiSliceItem.getSummary())
- .setContentDescription(wifiSliceItem.getContentDescription());
-
- final IconCompat endIcon;
- if (wifiSliceItem.hasInternetAccess()) {
- rowBuilder.setPrimaryAction(SliceAction.create(getBroadcastIntent(mContext),
- levelIcon, ListBuilder.ICON_IMAGE, ACTION_TITLE_CONNECT_TO_CARRIER));
- endIcon = IconCompat.createWithResource(mContext, R.drawable.ic_settings_close);
- } else {
- rowBuilder.setPrimaryAction(getWifiEntryAction(wifiSliceItem, levelIcon, title));
- endIcon = getEndIcon(wifiSliceItem);
- }
- if (endIcon != null) {
- rowBuilder.addEndItem(endIcon, ListBuilder.ICON_IMAGE);
- }
- return rowBuilder;
- }
-
- @Override
protected IconCompat getWifiSliceItemLevelIcon(WifiSliceItem wifiSliceItem) {
if (wifiSliceItem.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED
&& getInternetType() != InternetUpdater.INTERNET_WIFI) {
diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java
index 2d23f1f..8c7347b 100644
--- a/src/com/android/settings/network/SubscriptionsPreferenceController.java
+++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java
@@ -29,6 +29,7 @@
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
import android.net.wifi.WifiManager;
+import android.os.UserManager;
import android.provider.Settings;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
@@ -38,6 +39,7 @@
import android.telephony.TelephonyManager;
import android.text.Html;
import android.util.ArraySet;
+import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.collection.ArrayMap;
@@ -55,7 +57,7 @@
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.network.telephony.SignalStrengthListener;
import com.android.settings.network.telephony.TelephonyDisplayInfoListener;
-import com.android.settings.widget.GearPreference;
+import com.android.settings.widget.MutableGearPreference;
import com.android.settings.wifi.WifiPickerTrackerHelper;
import com.android.settingslib.SignalIcon.MobileIconGroup;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -115,7 +117,7 @@
// Map of subscription id to Preference
private Map<Integer, Preference> mSubscriptionPreferences;
private int mStartOrder;
- private GearPreference mSubsGearPref;
+ private MutableGearPreference mSubsGearPref;
private Config mConfig = null;
private SubsPrefCtrlInjector mSubsPrefCtrlInjector;
private TelephonyDisplayInfo mTelephonyDisplayInfo =
@@ -196,6 +198,7 @@
mSignalStrengthListener.pause();
mTelephonyDisplayInfoListener.pause();
unRegisterReceiver();
+ resetProviderPreferenceSummary();
}
@Override
@@ -238,15 +241,20 @@
}
if (mSubsGearPref == null) {
mPreferenceGroup.removeAll();
- mSubsGearPref = new GearPreference(mContext, null);
+ mSubsGearPref = new MutableGearPreference(mContext, null);
mSubsGearPref.setOnPreferenceClickListener(preference -> {
connectCarrierNetwork();
return true;
});
+
mSubsGearPref.setOnGearClickListener(p ->
startMobileNetworkActivity(mContext, subInfo.getSubscriptionId()));
}
+ if (!(mContext.getSystemService(UserManager.class)).isAdminUser()) {
+ mSubsGearPref.setGearEnabled(false);
+ }
+
mSubsGearPref.setTitle(SubscriptionUtil.getUniqueSubscriptionDisplayName(
subInfo, mContext));
mSubsGearPref.setOrder(mStartOrder);
@@ -275,6 +283,7 @@
String result = mSubsPrefCtrlInjector.getNetworkType(
mContext, mConfig, mTelephonyDisplayInfo, subId, isActiveCarrierNetwork);
if (mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext) || isActiveCarrierNetwork) {
+ Log.i(TAG, "Active cellular network or active carrier network.");
result = mContext.getString(R.string.preference_summary_default_combination,
mContext.getString(R.string.mobile_data_connection_active), result);
} else if (!isDataInService) {
@@ -316,6 +325,13 @@
return icon;
}
+ private void resetProviderPreferenceSummary() {
+ if (mSubsGearPref == null) {
+ return;
+ }
+ mSubsGearPref.setSummary("");
+ }
+
private void updateForBase() {
final Map<Integer, Preference> existingPrefs = mSubscriptionPreferences;
mSubscriptionPreferences = new ArrayMap<>();
diff --git a/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java b/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java
index d1c9f7b..4f64399 100644
--- a/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java
+++ b/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java
@@ -31,6 +31,7 @@
import com.android.settings.R;
import com.android.settings.network.SubscriptionUtil;
+import com.android.settings.network.ims.WifiCallingQueryImsState;
import java.util.List;
import java.util.Objects;
@@ -147,16 +148,20 @@
}
private boolean hasBackupCallingFeature(int subscriptionId) {
- PersistableBundle carrierConfig = getCarrierConfigForSubId(subscriptionId);
- Boolean featureEnableStatus = null;
- if (carrierConfig != null) {
- featureEnableStatus = carrierConfig.getBoolean(
- CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, false);
+ return isCrossSimEnabledByPlatform(mContext, subscriptionId);
+ }
+
+ protected boolean isCrossSimEnabledByPlatform(Context context, int subscriptionId) {
+ // TODO : Change into API which created for accessing
+ // com.android.ims.ImsManager#isCrossSimEnabledByPlatform()
+ if ((new WifiCallingQueryImsState(context, subscriptionId)).isWifiCallingSupported()) {
+ PersistableBundle bundle = getCarrierConfigForSubId(subscriptionId);
+ return (bundle != null) && bundle.getBoolean(
+ CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL,
+ false /*default*/);
}
- // TODO: remove log after fixing b/182326102
- Log.d(LOG_TAG, "config " + CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL
- + "=" + featureEnableStatus + " for subId=" + subscriptionId);
- return (featureEnableStatus != null) && featureEnableStatus.booleanValue();
+ Log.d(LOG_TAG, "Not supported by framework. subId = " + subscriptionId);
+ return false;
}
private ImsMmTelManager getImsMmTelManager(int subId) {
diff --git a/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java b/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java
index 3423ad8..b4ab2a0 100644
--- a/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java
+++ b/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java
@@ -47,6 +47,7 @@
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -86,7 +87,8 @@
}
private void setSubscriptionInfoList(Context context) {
- mSubInfoListForWfc = SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager);
+ mSubInfoListForWfc = new ArrayList<>(
+ SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager));
if (mSubInfoListForWfc != null) {
mSubInfoListForWfc.removeIf(info -> {
final int subId = info.getSubscriptionId();
diff --git a/src/com/android/settings/network/telephony/NetworkProviderWorker.java b/src/com/android/settings/network/telephony/NetworkProviderWorker.java
index 369218b..d4f0551 100644
--- a/src/com/android/settings/network/telephony/NetworkProviderWorker.java
+++ b/src/com/android/settings/network/telephony/NetworkProviderWorker.java
@@ -54,7 +54,7 @@
DataConnectivityListener.Client, InternetUpdater.InternetChangeListener,
SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
private static final String TAG = "NetworkProviderWorker";
- private static final int PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT = 5;
+ private static final int PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT = 6;
private DataContentObserver mMobileDataObserver;
private SignalStrengthListener mSignalStrengthListener;
private SubscriptionsChangeListener mSubscriptionsListener;
diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
index 0064e6c..146b575 100644
--- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
+++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
@@ -30,12 +30,14 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.SidecarFragment;
+import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.network.EnableMultiSimSidecar;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.network.SwitchToEuiccSubscriptionSidecar;
import com.android.settings.network.SwitchToRemovableSlotSidecar;
import com.android.settings.network.UiccSlotUtil;
import com.android.settings.sim.SimActivationNotifier;
+import com.android.settingslib.transition.SettingsTransitionHelper;
import com.google.common.collect.ImmutableList;
@@ -68,6 +70,9 @@
Intent intent = new Intent(context, ToggleSubscriptionDialogActivity.class);
intent.putExtra(ARG_SUB_ID, subId);
intent.putExtra(ARG_enable, enable);
+ // suppress page transition as this is a dialog
+ intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
+ SettingsTransitionHelper.TransitionType.TRANSITION_NONE);
return intent;
}
diff --git a/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java b/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java
index 5b2cdb9..d715ce4 100644
--- a/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java
+++ b/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java
@@ -141,9 +141,9 @@
int order = 100;
boolean hasClearable = false;
for (ConversationChannel conversation : conversations) {
- if (conversation.getParentNotificationChannel().getImportance() == IMPORTANCE_NONE
- || (conversation.getParentNotificationChannelGroup() != null
- && conversation.getParentNotificationChannelGroup().isBlocked())) {
+ if (conversation.getNotificationChannel().getImportance() == IMPORTANCE_NONE
+ || (conversation.getNotificationChannelGroup() != null
+ && conversation.getNotificationChannelGroup().isBlocked())) {
continue;
}
RecentConversationPreference pref =
@@ -179,12 +179,12 @@
pref.setSummary(getSummary(conversation));
pref.setIcon(mBackend.getConversationDrawable(mContext, conversation.getShortcutInfo(),
pkg, uid, false));
- pref.setKey(conversation.getParentNotificationChannel().getId()
+ pref.setKey(conversation.getNotificationChannel().getId()
+ ":" + conversationId);
pref.setOnPreferenceClickListener(preference -> {
mBackend.createConversationNotificationChannel(
pkg, uid,
- conversation.getParentNotificationChannel(),
+ conversation.getNotificationChannel(),
conversationId);
getSubSettingLauncher(conversation, pref.getTitle()).launch();
return true;
@@ -194,11 +194,11 @@
}
CharSequence getSummary(ConversationChannel conversation) {
- return conversation.getParentNotificationChannelGroup() == null
- ? conversation.getParentNotificationChannel().getName()
+ return conversation.getNotificationChannelGroup() == null
+ ? conversation.getNotificationChannel().getName()
: mContext.getString(R.string.notification_conversation_summary,
- conversation.getParentNotificationChannel().getName(),
- conversation.getParentNotificationChannelGroup().getName());
+ conversation.getNotificationChannel().getName(),
+ conversation.getNotificationChannelGroup().getName());
}
CharSequence getTitle(ConversationChannel conversation) {
@@ -213,7 +213,7 @@
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME,
conversation.getShortcutInfo().getPackage());
channelArgs.putString(Settings.EXTRA_CHANNEL_ID,
- conversation.getParentNotificationChannel().getId());
+ conversation.getNotificationChannel().getId());
channelArgs.putString(Settings.EXTRA_CONVERSATION_ID,
conversation.getShortcutInfo().getId());
@@ -235,8 +235,8 @@
o2.getShortcutInfo().getLabel());
if (labelComparison == 0) {
- return o1.getParentNotificationChannel().getId().compareTo(
- o2.getParentNotificationChannel().getId());
+ return o1.getNotificationChannel().getId().compareTo(
+ o2.getNotificationChannel().getId());
}
return labelComparison;
diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java
index e6344d8..c735780 100644
--- a/src/com/android/settings/panel/InternetConnectivityPanel.java
+++ b/src/com/android/settings/panel/InternetConnectivityPanel.java
@@ -38,7 +38,6 @@
import android.util.Log;
import androidx.annotation.VisibleForTesting;
-import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
@@ -84,12 +83,13 @@
}
if (TextUtils.equals(intent.getAction(), WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
- showProgressBar();
+ updateProgressBar();
updatePanelTitle();
return;
}
if (TextUtils.equals(intent.getAction(), WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ updateProgressBar();
updatePanelTitle();
}
}
@@ -110,13 +110,40 @@
private int mDefaultDataSubid = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
// Wi-Fi scanning progress bar
+ protected HandlerInjector mHandlerInjector;
protected boolean mIsProgressBarVisible;
- protected final Runnable mHideProgressBarRunnable = () -> {
+ protected boolean mIsScanningSubTitleShownOnce;
+ protected Runnable mHideProgressBarRunnable = () -> {
setProgressBarVisible(false);
};
+ protected Runnable mHideScanningSubTitleRunnable = () -> {
+ mIsScanningSubTitleShownOnce = true;
+ updatePanelTitle();
+ };
+
+ /**
+ * Wrapper for testing compatibility.
+ */
+ @VisibleForTesting
+ static class HandlerInjector {
+ protected final Handler mHandler;
+
+ HandlerInjector(Context context) {
+ mHandler = context.getMainThreadHandler();
+ }
+
+ public void postDelay(Runnable runnable) {
+ mHandler.postDelayed(runnable, 2000 /* delay millis */);
+ }
+
+ public void removeCallbacks(Runnable runnable) {
+ mHandler.removeCallbacks(runnable);
+ }
+ }
private InternetConnectivityPanel(Context context) {
mContext = context.getApplicationContext();
+ mHandlerInjector = new HandlerInjector(context);
mIsProviderModelEnabled = Utils.isProviderModelEnabled(mContext);
mInternetUpdater = new InternetUpdater(context, null /* Lifecycle */, this);
@@ -150,7 +177,7 @@
mTelephonyManager.registerTelephonyCallback(
new HandlerExecutor(new Handler(Looper.getMainLooper())), mTelephonyCallback);
mContext.registerReceiver(mWifiStateReceiver, mWifiStateFilter);
- showProgressBar();
+ updateProgressBar();
updatePanelTitle();
}
@@ -165,7 +192,8 @@
mConnectivityListener.stop();
mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
mContext.unregisterReceiver(mWifiStateReceiver);
- mContext.getMainThreadHandler().removeCallbacks(mHideProgressBarRunnable);
+ mHandlerInjector.removeCallbacks(mHideProgressBarRunnable);
+ mHandlerInjector.removeCallbacks(mHideScanningSubTitleRunnable);
}
/**
@@ -210,23 +238,6 @@
}
@Override
- public boolean isCustomizedButtonUsed() {
- return mIsProviderModelEnabled;
- }
-
- @Override
- public CharSequence getCustomizedButtonTitle() {
- return mContext.getText(
- mInternetUpdater.isWifiEnabled() ? R.string.turn_off_wifi : R.string.turn_on_wifi);
- }
-
- @Override
- public void onClickCustomizedButton(FragmentActivity panelActivity) {
- // Don't finish the panel activity
- mWifiManager.setWifiEnabled(!mInternetUpdater.isWifiEnabled());
- }
-
- @Override
public boolean isProgressBarVisible() {
return mIsProgressBarVisible;
}
@@ -246,6 +257,7 @@
*/
@Override
public void onAirplaneModeChanged(boolean isAirplaneModeOn) {
+ log("onAirplaneModeChanged: isAirplaneModeOn:" + isAirplaneModeOn);
updatePanelTitle();
}
@@ -254,6 +266,7 @@
*/
@Override
public void onWifiEnabledChanged(boolean enabled) {
+ log("onWifiEnabledChanged: enabled:" + enabled);
updatePanelTitle();
}
@@ -305,13 +318,6 @@
return;
}
- if (mIsProgressBarVisible) {
- // When the Wi-Fi scan result callback is received
- // Sub-Title: Searching for networks...
- mSubtitle = SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS;
- return;
- }
-
if (mInternetUpdater.isAirplaneModeOn()) {
return;
}
@@ -319,11 +325,18 @@
final List<ScanResult> wifiList = mWifiManager.getScanResults();
if (wifiList != null && wifiList.size() != 0) {
// When the Wi-Fi scan result is not empty
- // Sub-Title: Select the network you want to use for data
+ // Sub-Title: Tap a network to connect
mSubtitle = SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT;
return;
}
+ if (!mIsScanningSubTitleShownOnce && mIsProgressBarVisible) {
+ // When the Wi-Fi scan result callback is received
+ // Sub-Title: Searching for networks...
+ mSubtitle = SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS;
+ return;
+ }
+
// Sub-Title:
// show non_carrier_network_unavailable
// - while Wi-Fi on + no Wi-Fi item
@@ -353,7 +366,7 @@
mSubtitle = SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE;
}
- protected void showProgressBar() {
+ protected void updateProgressBar() {
if (mWifiManager == null || !mInternetUpdater.isWifiEnabled()) {
setProgressBarVisible(false);
return;
@@ -362,8 +375,9 @@
setProgressBarVisible(true);
List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
if (wifiScanResults != null && wifiScanResults.size() > 0) {
- mContext.getMainThreadHandler().postDelayed(mHideProgressBarRunnable,
- 2000 /* delay millis */);
+ mHandlerInjector.postDelay(mHideProgressBarRunnable);
+ } else if (!mIsScanningSubTitleShownOnce) {
+ mHandlerInjector.postDelay(mHideScanningSubTitleRunnable);
}
}
diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
index 28c4ba1..ca30952 100644
--- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java
+++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
@@ -20,8 +20,6 @@
import android.os.Bundle;
import android.provider.Settings;
-import com.android.settings.Utils;
-
public class PanelFeatureProviderImpl implements PanelFeatureProvider {
@Override
@@ -41,9 +39,6 @@
case Settings.Panel.ACTION_NFC:
return NfcPanel.create(context);
case Settings.Panel.ACTION_WIFI:
- if (Utils.isProviderModelEnabled(context)) {
- return InternetConnectivityPanel.create(context);
- }
return WifiPanel.create(context);
case Settings.Panel.ACTION_VOLUME:
return VolumePanel.create(context);
diff --git a/src/com/android/settings/security/CredentialManagementAppAdapter.java b/src/com/android/settings/security/CredentialManagementAppAdapter.java
index eb379d5..3f4eb2a 100644
--- a/src/com/android/settings/security/CredentialManagementAppAdapter.java
+++ b/src/com/android/settings/security/CredentialManagementAppAdapter.java
@@ -21,6 +21,7 @@
import android.content.pm.PackageManager;
import android.net.Uri;
import android.security.AppUriAuthenticationPolicy;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -85,11 +86,13 @@
ApplicationInfo applicationInfo =
mPackageManager.getApplicationInfo(mCredentialManagerPackage, 0);
mAppIconView.setImageDrawable(mPackageManager.getApplicationIcon(applicationInfo));
- mTitleView.setText(mContext.getString(R.string.request_manage_credentials_title,
+ mTitleView.setText(TextUtils.expandTemplate(
+ mContext.getText(R.string.request_manage_credentials_title),
applicationInfo.loadLabel(mPackageManager)));
} catch (PackageManager.NameNotFoundException e) {
mAppIconView.setImageDrawable(null);
- mTitleView.setText(mContext.getString(R.string.request_manage_credentials_title,
+ mTitleView.setText(TextUtils.expandTemplate(
+ mContext.getText(R.string.request_manage_credentials_title),
mCredentialManagerPackage));
}
}
diff --git a/src/com/android/settings/security/CredentialManagementAppButtonsController.java b/src/com/android/settings/security/CredentialManagementAppButtonsController.java
index fe5e45b..b296f37 100644
--- a/src/com/android/settings/security/CredentialManagementAppButtonsController.java
+++ b/src/com/android/settings/security/CredentialManagementAppButtonsController.java
@@ -80,12 +80,29 @@
private void displayButtons(PreferenceScreen screen) {
if (mHasCredentialManagerPackage) {
((ActionButtonsPreference) screen.findPreference(getPreferenceKey()))
- .setButton1Text(R.string.remove_credential_management_app)
- .setButton1Icon(R.drawable.ic_undo_24)
- .setButton1OnClickListener(view -> removeCredentialManagementApp());
+ .setButton1Text(R.string.uninstall_certs_credential_management_app)
+ .setButton1Icon(R.drawable.ic_upload)
+ .setButton1OnClickListener(view -> uninstallCertificates())
+ .setButton2Text(R.string.remove_credential_management_app)
+ .setButton2Icon(R.drawable.ic_delete)
+ .setButton2OnClickListener(view -> removeCredentialManagementApp());
}
}
+ private void uninstallCertificates() {
+ mExecutor.execute(() -> {
+ try {
+ IKeyChainService service = KeyChain.bind(mContext).getService();
+ for (String existingAlias :
+ service.getCredentialManagementAppPolicy().getAliases()) {
+ service.removeKeyPair(existingAlias);
+ }
+ } catch (InterruptedException | RemoteException e) {
+ Log.e(TAG, "Unable to uninstall certificates");
+ }
+ });
+ }
+
private void removeCredentialManagementApp() {
mExecutor.execute(() -> {
try {
diff --git a/src/com/android/settings/security/CredentialManagementAppHeaderController.java b/src/com/android/settings/security/CredentialManagementAppHeaderController.java
index 7b5ffb2..9361fb9 100644
--- a/src/com/android/settings/security/CredentialManagementAppHeaderController.java
+++ b/src/com/android/settings/security/CredentialManagementAppHeaderController.java
@@ -83,7 +83,6 @@
TextView titleView = headerPref.findViewById(R.id.entity_header_title);
TextView summary1 = headerPref.findViewById(R.id.entity_header_summary);
TextView summary2 = headerPref.findViewById(R.id.entity_header_second_summary);
- summary1.setVisibility(View.GONE);
summary2.setVisibility(View.GONE);
try {
@@ -91,6 +90,7 @@
mPackageManager.getApplicationInfo(mCredentialManagerPackageName, 0);
appIconView.setImageDrawable(mPackageManager.getApplicationIcon(applicationInfo));
titleView.setText(applicationInfo.loadLabel(mPackageManager));
+ summary1.setText(R.string.certificate_management_app_description);
} catch (PackageManager.NameNotFoundException e) {
appIconView.setImageDrawable(null);
titleView.setText(mCredentialManagerPackageName);
diff --git a/src/com/android/settings/security/RequestManageCredentials.java b/src/com/android/settings/security/RequestManageCredentials.java
index eb7a7d8..cda97da 100644
--- a/src/com/android/settings/security/RequestManageCredentials.java
+++ b/src/com/android/settings/security/RequestManageCredentials.java
@@ -21,7 +21,10 @@
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -37,7 +40,9 @@
import android.util.Log;
import android.view.View;
import android.widget.Button;
+import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -83,6 +88,7 @@
private KeyChain.KeyChainConnection mKeyChainConnection;
private boolean mDisplayingButtonPanel = false;
+ private boolean mIsLandscapeMode = false;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -114,6 +120,8 @@
.setStrings(mCredentialManagerPackage)
.write();
setContentView(R.layout.request_manage_credentials);
+ mIsLandscapeMode = getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_LANDSCAPE;
mKeyChainTread = new HandlerThread("KeyChainConnection");
mKeyChainTread.start();
@@ -134,6 +142,9 @@
getNumberOfAuthenticationPolicyUris(mAuthenticationPolicy))
.write();
+ if (mIsLandscapeMode) {
+ loadHeader();
+ }
loadRecyclerView();
loadButtons();
loadExtendedFloatingActionButton();
@@ -193,7 +204,7 @@
CredentialManagementAppAdapter recyclerViewAdapter = new CredentialManagementAppAdapter(
this, mCredentialManagerPackage, mAuthenticationPolicy.getAppAndUriMappings(),
- /* include header= */ true, /* include expander= */ false);
+ /* include header= */ !mIsLandscapeMode, /* include expander= */ false);
mRecyclerView.setAdapter(recyclerViewAdapter);
}
@@ -214,12 +225,33 @@
private void loadExtendedFloatingActionButton() {
mExtendedFab = findViewById(R.id.extended_fab);
mExtendedFab.setOnClickListener(v -> {
- mRecyclerView.scrollToPosition(mAuthenticationPolicy.getAppAndUriMappings().size());
+ final int position = mIsLandscapeMode
+ ? mAuthenticationPolicy.getAppAndUriMappings().size() - 1
+ : mAuthenticationPolicy.getAppAndUriMappings().size();
+ mRecyclerView.scrollToPosition(position);
mExtendedFab.hide();
showButtonPanel();
});
}
+ private void loadHeader() {
+ final ImageView mAppIconView = findViewById(R.id.credential_management_app_icon);
+ final TextView mTitleView = findViewById(R.id.credential_management_app_title);
+ try {
+ ApplicationInfo applicationInfo =
+ getPackageManager().getApplicationInfo(mCredentialManagerPackage, 0);
+ mAppIconView.setImageDrawable(getPackageManager().getApplicationIcon(applicationInfo));
+ mTitleView.setText(TextUtils.expandTemplate(
+ getText(R.string.request_manage_credentials_title),
+ applicationInfo.loadLabel(getPackageManager())));
+ } catch (PackageManager.NameNotFoundException e) {
+ mAppIconView.setImageDrawable(null);
+ mTitleView.setText(TextUtils.expandTemplate(
+ getText(R.string.request_manage_credentials_title),
+ mCredentialManagerPackage));
+ }
+ }
+
private void setOrUpdateCredentialManagementAppAndFinish() {
try {
mKeyChainConnection.getService().setCredentialManagementApp(
diff --git a/src/com/android/settings/widget/CardPreference.java b/src/com/android/settings/widget/CardPreference.java
index 20ea710..c041552 100644
--- a/src/com/android/settings/widget/CardPreference.java
+++ b/src/com/android/settings/widget/CardPreference.java
@@ -29,6 +29,7 @@
* Preference that wrapped by {@link MaterialCardView}, only support to set icon, title and summary
*/
public class CardPreference extends Preference {
+
public CardPreference(Context context) {
this(context, null /* attrs */);
}
diff --git a/src/com/android/settings/widget/GearPreference.java b/src/com/android/settings/widget/GearPreference.java
index 0a30100..82bc1f0 100644
--- a/src/com/android/settings/widget/GearPreference.java
+++ b/src/com/android/settings/widget/GearPreference.java
@@ -29,7 +29,8 @@
* A preference with a Gear on the side
*/
public class GearPreference extends RestrictedPreference implements View.OnClickListener {
-
+ // Default true for gear available even if the preference itself is disabled.
+ protected boolean mGearState = true;
private OnGearClickListener mOnGearClickListener;
public GearPreference(Context context, AttributeSet attrs) {
@@ -41,6 +42,16 @@
notifyChanged();
}
+ /** Sets state of gear button. */
+ public void setGearEnabled(boolean enabled) {
+ mGearState = enabled;
+ }
+
+ /** Gets state of gear button. */
+ public boolean isGearEnabled() {
+ return mGearState;
+ }
+
@Override
protected int getSecondTargetResId() {
return R.layout.preference_widget_gear;
@@ -62,7 +73,8 @@
gear.setVisibility(View.GONE);
gear.setOnClickListener(null);
}
- gear.setEnabled(true); // Make gear available even if the preference itself is disabled.
+ // Make gear available even if the preference itself is disabled.
+ gear.setEnabled(mGearState);
}
@Override
diff --git a/src/com/android/settings/widget/MutableGearPreference.java b/src/com/android/settings/widget/MutableGearPreference.java
new file mode 100644
index 0000000..b0804eb
--- /dev/null
+++ b/src/com/android/settings/widget/MutableGearPreference.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.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+import com.android.settingslib.utils.ColorUtil;
+
+/** A preference with a Gear on the side and mutable Gear color. */
+public class MutableGearPreference extends GearPreference {
+ private static final int VALUE_ENABLED_ALPHA = 255;
+
+ private ImageView mGear;
+ private Context mContext;
+ private int mDisabledAlphaValue;
+
+ public MutableGearPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+ mDisabledAlphaValue = (int) (ColorUtil.getDisabledAlpha(context) * VALUE_ENABLED_ALPHA);
+ }
+
+ @Override
+ public void setGearEnabled(boolean enabled) {
+ if (mGear != null) {
+ mGear.setEnabled(enabled);
+ mGear.setImageAlpha(enabled ? VALUE_ENABLED_ALPHA : mDisabledAlphaValue);
+ }
+ mGearState = enabled;
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ mGear = (ImageView) holder.findViewById(R.id.settings_button);
+ setGearEnabled(mGearState);
+ }
+}
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index ced198b..7bf680d 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -63,6 +63,7 @@
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
+import androidx.recyclerview.widget.RecyclerView;
import com.android.net.module.util.Inet4AddressUtils;
import com.android.settings.R;
@@ -513,6 +514,12 @@
@Override
public void onResume() {
+ // Disable the animation of the EntityHeaderController
+ final RecyclerView recyclerView = mFragment.getListView();
+ if (recyclerView != null) {
+ recyclerView.setItemAnimator(null);
+ }
+
// Ensure mNetwork is set before any callbacks above are delivered, since our
// NetworkCallback only looks at changes to mNetwork.
updateNetworkInfo();
diff --git a/tests/robotests/res/layout/main_clear.xml b/tests/robotests/res/layout/main_clear.xml
new file mode 100644
index 0000000..868d88f
--- /dev/null
+++ b/tests/robotests/res/layout/main_clear.xml
@@ -0,0 +1,136 @@
+<?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.
+-->
+
+<com.google.android.setupdesign.GlifLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/setup_wizard_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:theme="@style/GlifV3Theme.Footer"
+ android:orientation="vertical"
+ android:icon="@drawable/ic_delete_accent"
+ app:sucHeaderText="@string/main_clear_title">
+
+ <ScrollView
+ android:id="@+id/main_clear_scrollview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/reset_main_clear_margin_start"
+ android:layout_marginEnd="@dimen/reset_main_clear_margin_end">
+
+ <LinearLayout
+ android:id="@+id/main_clear_container"
+ style="@style/SudContentFrame"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ style="@style/TextAppearance.SudGlifItemSummary"
+ android:id="@+id/sud_layout_description"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/main_clear_desc"/>
+ <TextView
+ android:id="@+id/also_erases_external"
+ style="@style/TextAppearance.SudGlifItemSummary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:text="@string/main_clear_desc_also_erases_external"/>
+ <TextView
+ android:id="@+id/also_erases_esim"
+ style="@style/TextAppearance.SudGlifItemSummary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:text="@string/main_clear_desc_also_erases_esim"/>
+ <TextView
+ android:id="@+id/accounts_label"
+ style="@style/TextAppearance.SudGlifItemSummary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:text="@string/main_clear_accounts"/>
+ <LinearLayout
+ android:id="@+id/accounts"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:visibility="gone">
+ <!-- Do not add any children here as they will be removed in the MainClear.java
+ code. A list of accounts will be inserted programmatically. -->
+ </LinearLayout>
+ <TextView
+ android:id="@+id/other_users_present"
+ style="@style/TextAppearance.SudGlifItemSummary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:text="@string/main_clear_other_users_present"/>
+ <TextView
+ android:id="@+id/no_cancel_mobile_plan"
+ style="@style/TextAppearance.SudGlifItemSummary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:text="@string/main_clear_desc_no_cancel_mobile_plan"/>
+ <TextView
+ android:id="@+id/erase_external_option_text"
+ style="@style/TextAppearance.SudGlifItemSummary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/main_clear_desc_erase_external_storage"/>
+ <LinearLayout
+ android:id="@+id/erase_external_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:focusable="true"
+ android:clickable="true">
+ <CheckBox
+ android:id="@+id/erase_external"
+ style="@style/SudCheckBox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:focusable="false"
+ android:clickable="false"
+ android:duplicateParentState="true"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:orientation="vertical">
+ <TextView
+ style="@style/TextAppearance.SudGlifItemTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/erase_external_storage"/>
+ <TextView
+ style="@style/TextAppearance.SudGlifItemSummary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/erase_external_storage_description"/>
+ </LinearLayout>
+ </LinearLayout>
+
+ <include layout="@layout/reset_esim_checkbox"/>
+
+ </LinearLayout>
+ </ScrollView>
+</com.google.android.setupdesign.GlifLayout>
diff --git a/tests/robotests/res/layout/main_clear_confirm.xml b/tests/robotests/res/layout/main_clear_confirm.xml
new file mode 100644
index 0000000..341e7bb
--- /dev/null
+++ b/tests/robotests/res/layout/main_clear_confirm.xml
@@ -0,0 +1,40 @@
+<?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.
+-->
+<com.google.android.setupdesign.GlifLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:theme="@style/SudThemeGlifV3.DayNight"
+ android:orientation="vertical"
+ android:id="@+id/setup_wizard_layout"
+ android:icon="@drawable/ic_delete_accent"
+ app:sucHeaderText="@string/main_clear_confirm_title">
+
+ <LinearLayout
+ style="@style/SudContentFrame"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/sud_layout_description"
+ style="@style/SudItemTitle.GlifDescription"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/main_clear_final_desc"/>
+ </LinearLayout>
+</com.google.android.setupdesign.GlifLayout>
diff --git a/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java
index b10a729..8860cfe 100644
--- a/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java
@@ -19,20 +19,25 @@
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.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.Context;
-import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.widget.FooterPreference;
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;
@@ -42,13 +47,18 @@
private Context mContext;
private EnterpriseDisclosurePreferenceController mController;
- private Preference mPreference;
+ private FooterPreference mPreference;
+
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = spy(new EnterpriseDisclosurePreferenceController(mContext, "my_key"));
- mPreference = spy(new Preference(mContext));
+ mPreference = spy(new FooterPreference(mContext));
+ when(mPreferenceScreen.findPreference(anyString())).thenReturn(mPreference);
}
@Test
@@ -68,19 +78,19 @@
}
@Test
- public void updateState_hasDisclosure_shouldSetTitle() {
+ public void displayPreference_hasDisclosure_shouldSetTitle() {
doReturn(TEST_DISCLOSURE).when(mController).getDisclosure();
- mController.updateState(mPreference);
+ mController.displayPreference(mPreferenceScreen);
assertThat(mPreference.getTitle()).isEqualTo(TEST_DISCLOSURE);
}
@Test
- public void updateState_noDisclosure_shouldBeInvisible() {
+ public void displayPreference_noDisclosure_shouldBeInvisible() {
doReturn(null).when(mController).getDisclosure();
- mController.updateState(mPreference);
+ mController.displayPreference(mPreferenceScreen);
verify(mPreference, never()).setTitle(any());
}
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java
index c5ea21f..edd85e4 100644
--- a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java
@@ -20,11 +20,10 @@
import static org.robolectric.Shadows.shadowOf;
-import android.app.AppOpsManager;
import android.content.Context;
+import android.content.PermissionChecker;
import android.content.pm.CrossProfileApps;
import android.content.pm.PackageManager;
-import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
import android.os.UserManager;
@@ -37,19 +36,18 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadows.ShadowPermissionChecker;
@RunWith(RobolectricTestRunner.class)
public class InteractAcrossProfilesDetailsTest {
private static final int PERSONAL_PROFILE_ID = 0;
private static final int WORK_PROFILE_ID = 10;
- private static final int PACKAGE_UID = 0;
private static final String CROSS_PROFILE_PACKAGE_NAME = "crossProfilePackage";
public static final String INTERACT_ACROSS_PROFILES_PERMISSION =
"android.permission.INTERACT_ACROSS_PROFILES";
private final Context mContext = ApplicationProvider.getApplicationContext();
- private final AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
private final PackageManager mPackageManager = mContext.getPackageManager();
private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
private final CrossProfileApps mCrossProfileApps = mContext.getSystemService(
@@ -68,10 +66,10 @@
WORK_PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME));
shadowOf(mCrossProfileApps).addCrossProfilePackage(
CROSS_PROFILE_PACKAGE_NAME);
- String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION);
- shadowOf(mAppOpsManager).setMode(
- appOp, PACKAGE_UID, CROSS_PROFILE_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
- shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo());
+ ShadowPermissionChecker.setResult(
+ CROSS_PROFILE_PACKAGE_NAME,
+ INTERACT_ACROSS_PROFILES_PERMISSION,
+ PermissionChecker.PERMISSION_GRANTED);
assertThat(InteractAcrossProfilesDetails.getPreferenceSummary(
mContext, CROSS_PROFILE_PACKAGE_NAME))
@@ -91,11 +89,10 @@
WORK_PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME));
shadowOf(mCrossProfileApps).addCrossProfilePackage(
CROSS_PROFILE_PACKAGE_NAME);
- String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION);
- shadowOf(mAppOpsManager).setMode(
- appOp, PACKAGE_UID, CROSS_PROFILE_PACKAGE_NAME, AppOpsManager.MODE_IGNORED);
- shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo());
-
+ ShadowPermissionChecker.setResult(
+ CROSS_PROFILE_PACKAGE_NAME,
+ INTERACT_ACROSS_PROFILES_PERMISSION,
+ PermissionChecker.PERMISSION_SOFT_DENIED);
assertThat(InteractAcrossProfilesDetails.getPreferenceSummary(
mContext, CROSS_PROFILE_PACKAGE_NAME))
.isEqualTo(mContext.getString(
@@ -114,11 +111,4 @@
.isEqualTo(mContext.getString(
R.string.interact_across_profiles_summary_not_allowed));
}
-
- private PermissionInfo createCrossProfilesPermissionInfo() {
- PermissionInfo permissionInfo = new PermissionInfo();
- permissionInfo.name = INTERACT_ACROSS_PROFILES_PERMISSION;
- permissionInfo.protectionLevel = PermissionInfo.PROTECTION_FLAG_APPOP;
- return permissionInfo;
- }
}
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java
index bbbcd82..029fb28 100644
--- a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java
@@ -21,7 +21,6 @@
import static org.junit.Assert.assertTrue;
import static org.robolectric.Shadows.shadowOf;
-import android.app.AppOpsManager;
import android.content.Context;
import android.content.PermissionChecker;
import android.content.pm.ApplicationInfo;
@@ -51,7 +50,6 @@
private static final int PERSONAL_PROFILE_ID = 0;
private static final int WORK_PROFILE_ID = 10;
private static final int WORK_UID = UserHandle.PER_USER_RANGE * WORK_PROFILE_ID;
- private static final int PACKAGE_UID = 0;
private static final String PERSONAL_CROSS_PROFILE_PACKAGE = "personalCrossProfilePackage";
private static final String PERSONAL_NON_CROSS_PROFILE_PACKAGE =
@@ -71,7 +69,6 @@
private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
private final CrossProfileApps mCrossProfileApps =
mContext.getSystemService(CrossProfileApps.class);
- private final AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
@Test
public void collectConfigurableApps_fromPersonal_returnsCombinedPackages() {
@@ -84,8 +81,8 @@
PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
shadowOf(mPackageManager).setInstalledPackagesForUserId(
WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES);
- installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
- installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE);
+ installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
+ installCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE);
List<Pair<ApplicationInfo, UserHandle>> apps =
InteractAcrossProfilesSettings.collectConfigurableApps(
@@ -110,8 +107,8 @@
PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
shadowOf(mPackageManager).setInstalledPackagesForUserId(
WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES);
- installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
- installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE);
+ installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
+ installCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE);
List<Pair<ApplicationInfo, UserHandle>> apps =
InteractAcrossProfilesSettings.collectConfigurableApps(
@@ -130,7 +127,7 @@
PERSONAL_PROFILE_ID, "personal-profile"/* name */, 0/* flags */);
shadowOf(mPackageManager).setInstalledPackagesForUserId(
PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
- installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
+ installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
List<Pair<ApplicationInfo, UserHandle>> apps =
InteractAcrossProfilesSettings.collectConfigurableApps(
@@ -150,10 +147,9 @@
PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
shadowOf(mPackageManager).setInstalledPackagesForUserId(
WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES);
- installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
- installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE);
+ installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
+ installCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE);
shadowOf(mCrossProfileApps).addCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
- String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION);
ShadowPermissionChecker.setResult(
PERSONAL_CROSS_PROFILE_PACKAGE,
INTERACT_ACROSS_PROFILES_PERMISSION,
@@ -169,7 +165,7 @@
assertThat(numOfApps).isEqualTo(1);
}
- private void installCrossProfilePackage(int profileId, String packageName) {
+ private void installCrossProfilePackage(String packageName) {
PackageInfo personalPackageInfo = shadowOf(mPackageManager).getInternalMutablePackageInfo(
packageName);
personalPackageInfo.requestedPermissions = new String[]{
diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java
index cc3b20d..068de34 100644
--- a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java
@@ -20,46 +20,65 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
+import android.Manifest;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
import android.os.UserHandle;
import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.ResolveInfoBuilder;
+import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Answers;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowSensorPrivacyManager.class)
public class SmartAutoRotatePreferenceControllerTest {
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Context mContext;
+ private static final String PACKAGE_NAME = "package_name";
@Mock
private PackageManager mPackageManager;
+ @Mock
+ private Resources mResources;
+ private Context mContext;
private ContentResolver mContentResolver;
private SmartAutoRotatePreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ mContext = Mockito.spy(RuntimeEnvironment.application);
FakeFeatureFactory.setupForTest();
mContentResolver = RuntimeEnvironment.application.getContentResolver();
+
when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mContext.getResources()).thenReturn(mResources);
when(mContext.getContentResolver()).thenReturn(mContentResolver);
+
+ doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName();
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission(
+ Manifest.permission.CAMERA, PACKAGE_NAME);
when(mContext.getString(R.string.auto_rotate_option_off))
.thenReturn("Off");
when(mContext.getString(R.string.auto_rotate_option_on))
@@ -68,8 +87,14 @@
.thenReturn("On - Face-based");
disableCameraBasedRotation();
+ final ResolveInfo resolveInfo = new ResolveInfoBuilder(PACKAGE_NAME).build();
+ resolveInfo.serviceInfo = new ServiceInfo();
+ when(mPackageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo);
- mController = new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate");
+ mController = Mockito.spy(
+ new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate"));
+ when(mController.isCameraLocked()).thenReturn(false);
+ when(mController.isPowerSaveMode()).thenReturn(false);
}
@Test
@@ -82,33 +107,37 @@
}
@Test
- public void updatePreference_settingsIsOff_shouldTurnOffToggle() {
+ public void getSummary_settingsIsOff_returnsOff() {
disableAutoRotation();
assertThat(mController.getSummary()).isEqualTo("Off");
}
@Test
- public void updatePreference_settingsIsOn_shouldTurnOnToggle() {
+ public void getSummary_settingsIsOn_returnsOn() {
enableAutoRotation();
assertThat(mController.getSummary()).isEqualTo("On");
}
@Test
- public void updatePreference_settingsIsCameraBased_shouldTurnOnToggle() {
+ public void getSummary_autoRotateOffSmartAutoRotateOn_returnsOff() {
+ enableCameraBasedRotation();
+ disableAutoRotation();
+
+ assertThat(mController.getSummary()).isEqualTo("Off");
+ }
+
+ @Test
+ public void updatePreference_smartAutoRotateOn_returnsFaceBased() {
enableCameraBasedRotation();
enableAutoRotation();
assertThat(mController.getSummary()).isEqualTo("On - Face-based");
-
- disableAutoRotation();
-
- assertThat(mController.getSummary()).isEqualTo("Off");
}
@Test
- public void updatePreference_settingsIsOff_noSmartAuto_shouldTurnOffToggle() {
+ public void getSummary_noSmartAuto_returnsOff() {
disableAutoRotation();
Settings.Secure.putStringForUser(mContentResolver,
CAMERA_AUTOROTATE, null, UserHandle.USER_CURRENT);
@@ -118,7 +147,7 @@
}
@Test
- public void updatePreference_settingsIsOn_noSmartAuto_shouldTurnOnToggle() {
+ public void getSummary_noSmartAuto_returnsOn() {
enableAutoRotation();
Settings.Secure.putStringForUser(mContentResolver,
CAMERA_AUTOROTATE, null, UserHandle.USER_CURRENT);
@@ -127,6 +156,34 @@
}
@Test
+ public void getSummary_noCameraPermission_returnsOn() {
+ enableAutoRotation();
+ enableCameraBasedRotation();
+ doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission(
+ Manifest.permission.CAMERA, PACKAGE_NAME);
+
+ assertThat(mController.getSummary()).isEqualTo("On");
+ }
+
+ @Test
+ public void getSummary_cameraDisabled_returnsOn() {
+ enableAutoRotation();
+ enableCameraBasedRotation();
+ when(mController.isCameraLocked()).thenReturn(true);
+
+ assertThat(mController.getSummary()).isEqualTo("On");
+ }
+
+ @Test
+ public void getSummary_powerSaveEnabled_returnsOn() {
+ enableAutoRotation();
+ enableCameraBasedRotation();
+ when(mController.isPowerSaveMode()).thenReturn(true);
+
+ assertThat(mController.getSummary()).isEqualTo("On");
+ }
+
+ @Test
public void testGetAvailabilityStatus() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(BasePreferenceController
.UNSUPPORTED_ON_DEVICE);
@@ -158,14 +215,14 @@
private void enableAutoRotationPreference() {
when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
- when(mContext.getResources().getBoolean(anyInt())).thenReturn(true);
+ when(mResources.getBoolean(anyInt())).thenReturn(true);
Settings.System.putInt(mContentResolver,
Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0);
}
private void disableAutoRotationPreference() {
when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
- when(mContext.getResources().getBoolean(anyInt())).thenReturn(true);
+ when(mResources.getBoolean(anyInt())).thenReturn(true);
Settings.System.putInt(mContentResolver,
Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 1);
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
index 7894c3f..ef76eee 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
@@ -35,6 +35,7 @@
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.LocaleList;
import android.text.format.DateUtils;
import android.util.Pair;
@@ -100,6 +101,8 @@
mFeatureFactory = FakeFeatureFactory.setupForTest();
mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
mContext = spy(RuntimeEnvironment.application);
+ mContext.getResources().getConfiguration().setLocales(
+ new LocaleList(new Locale("en_US")));
mBatteryChartPreferenceController = createController();
mBatteryChartPreferenceController.mPrefContext = mContext;
mBatteryChartPreferenceController.mAppListPrefGroup = mAppListGroup;
@@ -573,14 +576,12 @@
// Verifies the title in the preference group.
verify(mBatteryChartPreferenceController.mAppListPrefGroup)
.setTitle(captor.capture());
- assertThat(captor.getValue())
- .isEqualTo("App usage for 4 pm - 7 am");
+ assertThat(captor.getValue()).isEqualTo("App usage for 4 - 7");
// Verifies the title in the expandable divider.
captor = ArgumentCaptor.forClass(String.class);
verify(mBatteryChartPreferenceController.mExpandDividerPreference)
.setTitle(captor.capture());
- assertThat(captor.getValue())
- .isEqualTo("System usage for 4 pm - 7 am");
+ assertThat(captor.getValue()).isEqualTo("System usage for 4 - 7");
}
@Test
@@ -716,7 +717,8 @@
private void setUpBatteryHistoryKeys() {
mBatteryChartPreferenceController.mBatteryHistoryKeys =
new long[] {1619196786769L, 0L, 1619247636826L};
- ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0, /*is24HourFormat=*/ false);
+ ConvertUtils.utcToLocalTimeHour(
+ mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
// Simulates the locale in GMT.
ConvertUtils.sSimpleDateFormatForHour
.setTimeZone(TimeZone.getTimeZone("GMT"));
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
index 3f94456..ec77f4c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
@@ -27,6 +27,7 @@
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
+import android.os.LocaleList;
import android.view.accessibility.AccessibilityManager;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -41,6 +42,7 @@
import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Locale;
import java.util.TimeZone;
@RunWith(RobolectricTestRunner.class)
@@ -60,6 +62,8 @@
mFeatureFactory = FakeFeatureFactory.setupForTest();
mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
mContext = spy(RuntimeEnvironment.application);
+ mContext.getResources().getConfiguration().setLocales(
+ new LocaleList(new Locale("en_US")));
mBatteryChartView = new BatteryChartView(mContext);
doReturn(mockAccessibilityManager).when(mContext)
.getSystemService(AccessibilityManager.class);
@@ -234,11 +238,11 @@
final long timestamp = 1619196786769L;
ConvertUtils.sSimpleDateFormatForHour = null;
// Invokes the method first to create the SimpleDateFormat.
- ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0, /*is24HourFormat=*/ false);
+ ConvertUtils.utcToLocalTimeHour(
+ mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
ConvertUtils.sSimpleDateFormatForHour
.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
- final String[] expectedTimestamps =
- new String[] {"9 am", "5 pm", "1 am", "9 am"};
+ final String[] expectedTimestamps = new String[] {"00", "06", "12", "18", "00"};
mBatteryChartView.setLatestTimestamp(timestamp);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
index e0f8ba7..96f0ec7 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
@@ -93,7 +93,7 @@
when(consumer.getUid()).thenReturn(APP_UID);
when(consumer.getPackageWithHighestDrain()).thenReturn(highDrainPackage);
return new BatteryEntry(mMockContext, mockHandler, mockUserManager,
- consumer, false, packages, packageName);
+ consumer, false, APP_UID, packages, packageName);
}
private BatteryEntry createAggregateBatteryEntry(int powerComponentId) {
@@ -108,7 +108,7 @@
UserBatteryConsumer consumer = mock(UserBatteryConsumer.class);
when(consumer.getUserId()).thenReturn(userId);
return new BatteryEntry(mMockContext, mockHandler, mockUserManager,
- consumer, false, null, null);
+ consumer, false, 0, null, null);
}
@Test
@@ -169,12 +169,12 @@
@Test
public void getTimeInForegroundMs_app() {
- final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
- mockUserManager, mUidBatteryConsumer, false, null, null);
-
when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND))
.thenReturn(100L);
+ final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
+ mockUserManager, mUidBatteryConsumer, false, 0, null, null);
+
assertThat(entry.getTimeInForegroundMs()).isEqualTo(100L);
}
@@ -188,12 +188,12 @@
@Test
public void getTimeInBackgroundMs_app() {
- final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
- mockUserManager, mUidBatteryConsumer, false, null, null);
-
when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
.thenReturn(100L);
+ final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
+ mockUserManager, mUidBatteryConsumer, false, 0, null, null);
+
assertThat(entry.getTimeInBackgroundMs()).isEqualTo(100L);
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
index efabe44..0b1a1e3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
@@ -24,11 +24,13 @@
import android.content.Context;
import android.os.BatteryManager;
import android.os.BatteryUsageStats;
+import android.os.LocaleList;
import android.os.UserHandle;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -315,6 +317,8 @@
.isEqualTo(entry.mConsumePower * ratio);
}
+ @Ignore
+ @Test
public void testUtcToLocalTime_returnExpectedResult() {
ConvertUtils.sZoneId = null;
ConvertUtils.sLocale = null;
@@ -322,48 +326,78 @@
final String expectedZoneId = "America/Los_Angeles";
ConvertUtils.sSimpleDateFormat = null;
// Invokes the method first to create the SimpleDateFormat.
- ConvertUtils.utcToLocalTime(/*timestamp=*/ 0);
+ ConvertUtils.utcToLocalTime(mContext, /*timestamp=*/ 0);
ConvertUtils.sSimpleDateFormat
.setTimeZone(TimeZone.getTimeZone(expectedZoneId));
+ mContext.getResources().getConfiguration().setLocales(
+ new LocaleList(new Locale("en_US")));
- assertThat(ConvertUtils.utcToLocalTime(timestamp))
- .isEqualTo("Apr 23,2021 09:53:06");
+ assertThat(ConvertUtils.utcToLocalTime(mContext, timestamp))
+ .isEqualTo("Apr 24,2021 00:53:06");
assertThat(ConvertUtils.sZoneId).isNotEqualTo(expectedZoneId);
- assertThat(ConvertUtils.sLocale).isEqualTo(Locale.getDefault());
+ assertThat(ConvertUtils.sLocale).isEqualTo(new Locale("en_US"));
}
+ @Ignore
+ @Test
public void testUtcToLocalTimeHour_12HourFormat_returnExpectedResult() {
ConvertUtils.sZoneIdForHour = null;
ConvertUtils.sLocaleForHour = null;
- final long timestamp = 1619196786769L;
+ final long timestamp = 1619000086769L;
final String expectedZoneId = "America/Los_Angeles";
ConvertUtils.sSimpleDateFormatForHour = null;
// Invokes the method first to create the SimpleDateFormat.
- ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0, /*is24HourFormat=*/ false);
+ ConvertUtils.utcToLocalTimeHour(
+ mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
ConvertUtils.sSimpleDateFormatForHour
.setTimeZone(TimeZone.getTimeZone(expectedZoneId));
+ mContext.getResources().getConfiguration().setLocales(
+ new LocaleList(new Locale("en_US")));
assertThat(ConvertUtils.utcToLocalTimeHour(
- timestamp, /*is24HourFormat=*/ false)).isEqualTo("9 am");
+ mContext, timestamp, /*is24HourFormat=*/ false)).isEqualTo("6");
assertThat(ConvertUtils.sZoneIdForHour).isNotEqualTo(expectedZoneId);
- assertThat(ConvertUtils.sLocaleForHour).isEqualTo(Locale.getDefault());
+ assertThat(ConvertUtils.sLocaleForHour).isEqualTo(new Locale("en_US"));
}
+ @Ignore
+ @Test
public void testUtcToLocalTimeHour_24HourFormat_returnExpectedResult() {
ConvertUtils.sZoneIdForHour = null;
ConvertUtils.sLocaleForHour = null;
- final long timestamp = 1619196786769L;
+ final long timestamp = 1619000086769L;
final String expectedZoneId = "America/Los_Angeles";
ConvertUtils.sSimpleDateFormatForHour = null;
// Invokes the method first to create the SimpleDateFormat.
- ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0, /*is24HourFormat=*/ true);
+ ConvertUtils.utcToLocalTimeHour(
+ mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
ConvertUtils.sSimpleDateFormatForHour
.setTimeZone(TimeZone.getTimeZone(expectedZoneId));
+ mContext.getResources().getConfiguration().setLocales(
+ new LocaleList(new Locale("en_US")));
assertThat(ConvertUtils.utcToLocalTimeHour(
- timestamp, /*is24HourFormat=*/ true)).isEqualTo("09");
+ mContext, timestamp, /*is24HourFormat=*/ true)).isEqualTo("18");
assertThat(ConvertUtils.sZoneIdForHour).isNotEqualTo(expectedZoneId);
- assertThat(ConvertUtils.sLocaleForHour).isEqualTo(Locale.getDefault());
+ assertThat(ConvertUtils.sLocaleForHour).isEqualTo(new Locale("en_US"));
+ }
+
+ @Test
+ public void getLocale_nullContext_returnDefaultLocale() {
+ assertThat(ConvertUtils.getLocale(/*context=*/ null))
+ .isEqualTo(Locale.getDefault());
+ }
+
+ @Test
+ public void getLocale_nullLocaleList_returnDefaultLocale() {
+ mContext.getResources().getConfiguration().setLocales(null);
+ assertThat(ConvertUtils.getLocale(mContext)).isEqualTo(Locale.getDefault());
+ }
+
+ @Test
+ public void getLocale_emptyLocaleList_returnDefaultLocale() {
+ mContext.getResources().getConfiguration().setLocales(new LocaleList());
+ assertThat(ConvertUtils.getLocale(mContext)).isEqualTo(Locale.getDefault());
}
private static BatteryHistEntry createBatteryHistEntry(
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedActionPullDownPrefControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedActionPullDownPrefControllerTest.java
new file mode 100644
index 0000000..60398de
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedActionPullDownPrefControllerTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.gestures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class OneHandedActionPullDownPrefControllerTest {
+
+ private static final String KEY = "gesture_one_handed_action_pull_screen_down";
+
+ private Context mContext;
+ private OneHandedSettingsUtils mUtils;
+ private OneHandedActionPullDownPrefController mController;
+ private RadioButtonPreference mPreference;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mUtils = new OneHandedSettingsUtils(mContext);
+ mController = new OneHandedActionPullDownPrefController(mContext, KEY);
+ mPreference = new RadioButtonPreference(mContext);
+ OneHandedSettingsUtils.setUserId(UserHandle.myUserId());
+ }
+
+ @Test
+ public void updateState_showNotificationEnabled_shouldUnchecked() {
+ OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, true);
+
+ mController.updateState(mPreference);
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void updateState_showNotificationDisabled_shouldChecked() {
+ OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, false);
+
+ mController.updateState(mPreference);
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void getAvailabilityStatus_setOneHandedModeDisabled_shouldDisabled() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+ OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
+ mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ public void getAvailabilityStatus_setNavi3ButtonMode_shouldDisabled() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+ OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+ mUtils.setNavigationBarMode(mContext, "0" /* 3 button */);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ public void getAvailabilityStatus_setNaviGesturalMode_shouldEnabled() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+ OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+ mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_unsetSupportOneHandedModeProperty_shouldDisabled() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
+ OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+ mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefControllerTest.java
new file mode 100644
index 0000000..b56a4f7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefControllerTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.gestures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class OneHandedActionShowNotificationPrefControllerTest {
+
+ private static final String KEY = "gesture_one_handed_action_show_notification";
+
+ private Context mContext;
+ private OneHandedSettingsUtils mUtils;
+ private OneHandedActionShowNotificationPrefController mController;
+ private RadioButtonPreference mPreference;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mUtils = new OneHandedSettingsUtils(mContext);
+ mController = new OneHandedActionShowNotificationPrefController(mContext, KEY);
+ mPreference = new RadioButtonPreference(mContext);
+ OneHandedSettingsUtils.setUserId(UserHandle.myUserId());
+ }
+
+ @Test
+ public void updateState_setGesturalMode_shouldEnabled() {
+ OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+ mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+ mController.updateState(mPreference);
+ assertThat(mPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void updateState_ShowNotificationEnabled_shouldChecked() {
+ OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, true);
+
+ mController.updateState(mPreference);
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void updateState_showNotificationDisabled_shouldUnchecked() {
+ OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, false);
+
+ mController.updateState(mPreference);
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void getAvailabilityStatus_setOneHandedModeDisabled_shouldDisabled() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+ OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
+ mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ public void getAvailabilityStatus_setNavi3ButtonMode_shouldDisabled() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+ OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+ mUtils.setNavigationBarMode(mContext, "0" /* 3 button */);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ public void getAvailabilityStatus_unsetSupportOneHandedModeProperty_shouldDisabled() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
+ OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+ mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java
index e5b8688..d0f6485 100644
--- a/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java
@@ -21,7 +21,6 @@
import android.content.Context;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
@@ -48,20 +47,8 @@
}
@Test
- 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(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
- setNavigationBarMode(mContext, "2" /* fully gestural */);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
@@ -70,16 +57,6 @@
@Test
public void getAvailabilityStatus_unsetSupportOneHandedModeProperty_shouldUnsupported() {
SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
- setNavigationBarMode(mContext, "2" /* fully gestural */);
-
- assertThat(mController.getAvailabilityStatus())
- .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
- }
-
- @Test
- public void getAvailabilityStatus_set3ButtonModeProperty_shouldUnsupported() {
- SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
- setNavigationBarMode(mContext, "0" /* 3-button */);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
@@ -100,18 +77,4 @@
assertThat(mController.getSummary())
.isEqualTo(mContext.getText(R.string.switch_off_text));
}
-
- /**
- * Set NavigationBar mode flag to Settings provider.
- * @param context App context
- * @param value Navigation bar mode:
- * 0 = 3 button
- * 1 = 2 button
- * 2 = fully gestural
- * @return true if the value was set, false on database errors.
- */
- private boolean setNavigationBarMode(Context context, String value) {
- return Settings.Secure.putStringForUser(context.getContentResolver(),
- Settings.Secure.NAVIGATION_MODE, value, UserHandle.myUserId());
- }
}
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceControllerTest.java
new file mode 100644
index 0000000..40cf795
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceControllerTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.gestures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+
+import com.android.settings.core.BasePreferenceController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class OneHandedMainSwitchPreferenceControllerTest {
+
+ private static final String KEY = "gesture_one_handed_mode_enabled_main_switch";
+
+ private Context mContext;
+ private OneHandedSettingsUtils mUtils;
+ private OneHandedMainSwitchPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mUtils = new OneHandedSettingsUtils(mContext);
+ mController = new OneHandedMainSwitchPreferenceController(mContext, KEY);
+ OneHandedSettingsUtils.setUserId(UserHandle.myUserId());
+ }
+
+ @Test
+ public void setChecked_setBoolean_checkIsTrueOrFalse() {
+ mController.setChecked(false);
+ assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isFalse();
+
+ mController.setChecked(true);
+ assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isTrue();
+ }
+
+ @Test
+ public void getAvailabilityStatus_setSupportOneHandedModeProperty_shouldAvailable() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+ mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_unsetSupportOneHandedModeProperty_shouldDisabled() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
+ mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ public void getAvailabilityStatus_set3ButtonMode_shouldDisabled() {
+ SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+ mUtils.setNavigationBarMode(mContext, "0" /* 3-button mode */);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedTimeoutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedTimeoutPreferenceControllerTest.java
deleted file mode 100644
index d278945..0000000
--- a/tests/robotests/src/com/android/settings/gestures/OneHandedTimeoutPreferenceControllerTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.UserHandle;
-
-import androidx.preference.ListPreference;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class OneHandedTimeoutPreferenceControllerTest {
-
- private static final String KEY = "gesture_one_handed_timeout";
-
- private Context mContext;
- private OneHandedTimeoutPreferenceController mController;
- private ListPreference mPreference;
-
- @Before
- public void setUp() {
- mContext = RuntimeEnvironment.application;
- mController = new OneHandedTimeoutPreferenceController(mContext, KEY);
- mPreference = new ListPreference(mContext);
- mPreference.setKey(KEY);
- OneHandedSettingsUtils.setUserId(UserHandle.myUserId());
- }
-
- @Test
- public void getAvailabilityStatus_enabledOneHanded_shouldAvailable() {
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
-
- assertThat(mController.getAvailabilityStatus())
- .isEqualTo(BasePreferenceController.AVAILABLE);
- }
-
- @Test
- public void getAvailabilityStatus_disableOneHanded_shouldUnavailable() {
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
-
- assertThat(mController.getAvailabilityStatus())
- .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
- }
-
- @Test
- public void updateState_enableOneHanded_switchShouldEnabled() {
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isEnabled()).isTrue();
- }
-
- @Test
- public void updateState_disableOneHanded_switchShouldDisabled() {
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isEnabled()).isFalse();
- }
-
- @Test
- public void getSummary_setTimeoutNever_shouldReturnNeverSummary() {
- final String[] timeoutTitles = mContext.getResources().getStringArray(
- R.array.one_handed_timeout_title);
-
- OneHandedSettingsUtils.setTimeoutValue(mContext,
- OneHandedSettingsUtils.OneHandedTimeout.NEVER.getValue());
-
- assertThat(mController.getSummary()).isEqualTo(
- timeoutTitles[OneHandedSettingsUtils.OneHandedTimeout.NEVER.ordinal()]);
- }
-
- @Test
- public void getSummary_setTimeoutShort_shouldReturnShortSummary() {
- final String[] timeoutTitles = mContext.getResources().getStringArray(
- R.array.one_handed_timeout_title);
-
- OneHandedSettingsUtils.setTimeoutValue(mContext,
- OneHandedSettingsUtils.OneHandedTimeout.SHORT.getValue());
-
- assertThat(mController.getSummary()).isEqualTo(String.format(
- mContext.getResources().getString(R.string.screen_timeout_summary),
- timeoutTitles[OneHandedSettingsUtils.OneHandedTimeout.SHORT.ordinal()]));
- }
-}
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceControllerTest.java
deleted file mode 100644
index 8f50006..0000000
--- a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceControllerTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.provider.Settings;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-
-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;
-
-@RunWith(RobolectricTestRunner.class)
-public class SwipeBottomToNotificationPreferenceControllerTest {
-
- private static final String KEY = "gesture_swipe_bottom_to_notification";
-
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Context mContext;
-
- private SwipeBottomToNotificationPreferenceController mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mController = new SwipeBottomToNotificationPreferenceController(mContext, KEY);
- }
-
- @Test
- public void setChecked_toggledOn_enablesSwipeBottomToNotification() {
- mController.setChecked(true);
-
- assertThat(OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext)).isTrue();
- assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isFalse();
- }
-
- @Test
- public void setChecked_toggledOff_disablesSwipeBottomToNotification() {
- mController.setChecked(false);
-
- assertThat(OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext)).isFalse();
- }
-
- @Test
- public void getAvailabilityStatus_oneHandedUnsupported_returnsUnsupport() {
- SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
- setNavigationBarMode(mContext, "2" /* fully gestural */);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(
- BasePreferenceController.UNSUPPORTED_ON_DEVICE);
- }
-
- @Test
- public void getAvailabilityStatus_oneHandedSupported_returnsAvailable() {
- SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
- setNavigationBarMode(mContext, "2" /* fully gestural */);
-
- assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
- }
-
- @Test
- public void getAvailabilityStatus_set3ButtonModeProperty_returnsUnsupport() {
- SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
- setNavigationBarMode(mContext, "0" /* 3-button */);
-
- assertThat(mController.getAvailabilityStatus())
- .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
- }
-
- @Test
- public void getSummary_gestureEnabled_returnsOnSummary() {
- mController.setChecked(true);
-
- assertThat(mController.getSummary()).isEqualTo(
- mContext.getText(R.string.gesture_setting_on));
- }
-
- @Test
- public void getSummary_gestureDisabled_returnsOffSummary() {
- mController.setChecked(false);
-
- assertThat(mController.getSummary()).isEqualTo(
- mContext.getText(R.string.gesture_setting_off));
- }
-
- @Test
- public void isChecked_getDefaultConfig_returnFalse() {
- SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
- Settings.Secure.resetToDefaults(mContext.getContentResolver(),
- Settings.Secure.ONE_HANDED_MODE_ENABLED);
-
- assertThat(mController.isChecked()).isFalse();
- }
-
- /**
- * Set NavigationBar mode flag to Settings provider.
- * @param context App context
- * @param value Navigation bar mode:
- * 0 = 3 button
- * 1 = 2 button
- * 2 = fully gestural
- * @return true if the value was set, false on database errors.
- */
- private boolean setNavigationBarMode(Context context, String value) {
- return Settings.Secure.putStringForUser(context.getContentResolver(),
- Settings.Secure.NAVIGATION_MODE, value, UserHandle.myUserId());
- }
-}
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationSettingsTest.java
deleted file mode 100644
index a3c8a1e..0000000
--- a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationSettingsTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.SystemProperties;
-import android.provider.SearchIndexableResource;
-
-import com.android.settings.R;
-
-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.util.ReflectionHelpers;
-
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class SwipeBottomToNotificationSettingsTest {
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Context mContext;
-
- private SwipeBottomToNotificationSettings mSettings = new SwipeBottomToNotificationSettings();
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- }
-
- @Test
- public void getPreferenceScreenResId_shouldReturnsXml() {
- assertThat(mSettings.getPreferenceScreenResId())
- .isEqualTo(R.xml.swipe_bottom_to_notification_settings);
- }
-
- @Test
- public void searchIndexProvider_shouldIndexResource() {
- final List<SearchIndexableResource> indexRes =
- SwipeBottomToNotificationSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
- mContext, true /* enabled */);
-
- assertThat(indexRes.get(0).xmlResId).isEqualTo(mSettings.getPreferenceScreenResId());
- }
-
- @Test
- 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).isFalse();
- }
-
- @Test
- public void isPageSearchEnabled_oneHandedDisabled_shouldReturnTrue() {
- SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, 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();
- }
-
- @Test
- public void isPageSearchEnabled_oneHandedEnabled_shouldReturnFalse() {
- SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
-
- final Object obj = ReflectionHelpers.callInstanceMethod(
- SwipeBottomToNotificationSettings.SEARCH_INDEX_DATA_PROVIDER, "isPageSearchEnabled",
- ReflectionHelpers.ClassParameter.from(Context.class, mContext));
-
- final boolean isEnabled = (Boolean) obj;
- assertThat(isEnabled).isFalse();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java
index 0370781..1a7a63c 100644
--- a/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java
@@ -67,8 +67,6 @@
@Mock
private PreferenceCategory mCategoryPrimary;
@Mock
- private PreferenceCategory mCategoryManaged;
- @Mock
private PreferenceScreen mScreen;
@Mock
private AppSettingsInjector mSettingsInjector;
@@ -115,31 +113,6 @@
}
@Test
- public void updateState_shouldRemoveAllAndAddInjectedSettings() {
- final List<Preference> preferences = new ArrayList<>();
- final Map<Integer, List<Preference>> map = new ArrayMap<>();
- final Preference pref1 = new Preference(mContext);
- pref1.setTitle("Title1");
- final Preference pref2 = new Preference(mContext);
- pref2.setTitle("Title2");
- preferences.add(pref1);
- preferences.add(pref2);
- map.put(UserHandle.myUserId(), preferences);
- doReturn(map)
- .when(mSettingsInjector).getInjectedSettings(any(Context.class), anyInt());
- when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
- ShadowUserManager.getShadow().setProfileIdsWithDisabled(new int[]{UserHandle.myUserId()});
-
- mController.displayPreference(mScreen);
-
- mController.updateState(mCategoryPrimary);
-
- verify(mCategoryPrimary).removeAll();
- verify(mCategoryPrimary).addPreference(pref1);
- verify(mCategoryPrimary).addPreference(pref2);
- }
-
- @Test
public void workProfileDisallowShareLocationOn_getParentUserLocationServicesOnly() {
final int fakeWorkProfileId = 123;
ShadowUserManager.getShadow().setProfileIdsWithDisabled(
@@ -158,7 +131,6 @@
when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
mController.displayPreference(mScreen);
- mController.updateState(mCategoryPrimary);
verify(mSettingsInjector).getInjectedSettings(
any(Context.class), eq(UserHandle.myUserId()));
}
@@ -178,7 +150,6 @@
enforcingUsers);
mController.displayPreference(mScreen);
- mController.updateState(mCategoryPrimary);
verify(mSettingsInjector).getInjectedSettings(
any(Context.class), eq(UserHandle.USER_CURRENT));
}
@@ -216,7 +187,6 @@
when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
mController.displayPreference(mScreen);
- mController.updateState(mCategoryPrimary);
assertThat(pref.isEnabled()).isFalse();
assertThat(pref.isDisabledByAdmin()).isTrue();
diff --git a/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java
index 15bc598..f0ae7ab 100644
--- a/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java
@@ -160,9 +160,9 @@
true);
assertThat(mController.getSummary(ccw).toString()).contains(
- ccw.getParentNotificationChannelGroup().getName());
+ ccw.getNotificationChannelGroup().getName());
assertThat(mController.getSummary(ccw).toString()).contains(
- ccw.getParentNotificationChannel().getName());
+ ccw.getNotificationChannel().getName());
}
@Test
@@ -175,7 +175,7 @@
true);
assertThat(mController.getSummary(ccw).toString()).isEqualTo(
- ccw.getParentNotificationChannel().getName());
+ ccw.getNotificationChannel().getName());
}
@Test
@@ -207,7 +207,7 @@
ccw.getShortcutInfo().getPackage());
assertThat(extras.getInt(AppInfoBase.ARG_PACKAGE_UID)).isEqualTo(ccw.getUid());
assertThat(extras.getString(Settings.EXTRA_CHANNEL_ID)).isEqualTo(
- ccw.getParentNotificationChannel().getId());
+ ccw.getNotificationChannel().getId());
assertThat(extras.getString(Settings.EXTRA_CONVERSATION_ID)).isEqualTo(
ccw.getShortcutInfo().getId());
}
@@ -230,7 +230,7 @@
// expected since it tries to launch an activity
}
verify(mBackend).createConversationNotificationChannel(
- si.getPackage(), ccw.getUid(), ccw.getParentNotificationChannel(), si.getId());
+ si.getPackage(), ccw.getUid(), ccw.getNotificationChannel(), si.getId());
}
@Test
diff --git a/tests/robotests/src/com/android/settings/widget/CardPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/CardPreferenceTest.java
index 6d4a6bb..85ab609 100644
--- a/tests/robotests/src/com/android/settings/widget/CardPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/CardPreferenceTest.java
@@ -45,5 +45,4 @@
public void getLayoutResource() {
assertThat(mCardPreference.getLayoutResource()).isEqualTo(R.layout.card_preference_layout);
}
-
}
diff --git a/tests/unit/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceControllerTest.java b/tests/unit/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceControllerTest.java
deleted file mode 100644
index 980ca6e..0000000
--- a/tests/unit/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceControllerTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.UserHandle;
-
-import androidx.preference.SwitchPreference;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.core.TogglePreferenceController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class OneHandedAppTapsExitPreferenceControllerTest {
-
- private static final String KEY = "gesture_app_taps_to_exit";
-
- private Context mContext;
- private SwitchPreference mSwitchPreference;
- private OneHandedAppTapsExitPreferenceController mController;
-
- @Before
- public void setUp() {
- mContext = ApplicationProvider.getApplicationContext();
- mController = new OneHandedAppTapsExitPreferenceController(mContext, KEY);
- mSwitchPreference = new SwitchPreference(mContext);
- mSwitchPreference.setKey(KEY);
- OneHandedSettingsUtils.setUserId(UserHandle.myUserId());
- }
-
- @Test
- public void setChecked_setBoolean_checkIsTrueOrFalse() {
- mController.setChecked(false);
- assertThat(mController.isChecked()).isFalse();
-
- mController.setChecked(true);
- assertThat(mController.isChecked()).isTrue();
- }
-
- @Test
- public void getAvailabilityStatus_enabledOneHanded_shouldAvailable() {
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
-
- assertThat(mController.getAvailabilityStatus())
- .isEqualTo(TogglePreferenceController.AVAILABLE);
- }
-
- @Test
- public void getAvailabilityStatus_disabledOneHanded_shouldUnavailable() {
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
-
- assertThat(mController.getAvailabilityStatus())
- .isEqualTo(TogglePreferenceController.DISABLED_DEPENDENT_SETTING);
- }
-
- @Test
- public void updateState_enableOneHanded_switchShouldEnabled() {
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
-
- mController.updateState(mSwitchPreference);
-
- assertThat(mSwitchPreference.isEnabled()).isTrue();
- }
-
- @Test
- public void updateState_disableOneHanded_switchShouldDisabled() {
- OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
-
- mController.updateState(mSwitchPreference);
-
- assertThat(mSwitchPreference.isEnabled()).isFalse();
- }
-}
diff --git a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
index a96e7cf..85129f8 100644
--- a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
+++ b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
@@ -16,8 +16,6 @@
package com.android.settings.network;
-import static com.android.settings.network.ProviderModelSlice.ACTION_TITLE_CONNECT_TO_CARRIER;
-
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -42,6 +40,8 @@
import android.telephony.TelephonyManager;
import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
import androidx.slice.SliceProvider;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
@@ -100,8 +100,6 @@
ListBuilder.RowBuilder mMockCarrierRowBuild;
@Mock
WifiPickerTracker mWifiPickerTracker;
- @Mock
- WifiSliceItem mWifiSliceItem;
private FakeFeatureFactory mFeatureFactory;
@@ -122,7 +120,7 @@
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
-
+ when(mWifiManager.isWifiEnabled()).thenReturn(true);
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
@@ -182,7 +180,24 @@
@Test
@UiThreadTest
- public void getSlice_haveTwoWifiAndOneCarrier_getCarrierAndTwoWiFiAndSeeAll() {
+ public void getSlice_airplaneModeIsOn_oneWifiToggle() {
+ mWifiList.clear();
+ mMockNetworkProviderWorker.updateSelfResults(null);
+ mockHelperCondition(true, false, false, null);
+
+ final Slice slice = mMockProviderModelSlice.getSlice();
+
+ assertThat(slice).isNotNull();
+ verify(mListBuilder, times(1)).addRow(any(ListBuilder.RowBuilder.class));
+ final SliceItem sliceTitle =
+ SliceMetadata.from(mContext, slice).getListContent().getHeader().getTitleItem();
+ assertThat(sliceTitle.getText()).isEqualTo(
+ ResourcesUtils.getResourcesString(mContext, "wifi_settings"));
+ }
+
+ @Test
+ @UiThreadTest
+ public void getSlice_haveTwoWifiAndOneCarrier_getFiveRow() {
mWifiList.clear();
mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
WifiEntry.CONNECTED_STATE_CONNECTED, "wifi1_key", true);
@@ -197,13 +212,13 @@
assertThat(slice).isNotNull();
verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
- verify(mListBuilder, times(4)).addRow(any(ListBuilder.RowBuilder.class));
+ verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
}
@Test
@UiThreadTest
- public void getSlice_haveOneConnectedWifiAndTwoDisconnectedWifiAndNoCarrier_getFourRow() {
+ public void getSlice_haveOneConnectedWifiAndTwoDisconnectedWifiAndNoCarrier_getFiveRow() {
mWifiList.clear();
mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
WifiEntry.CONNECTED_STATE_CONNECTED, "wifi1_key", true);
@@ -220,13 +235,13 @@
final Slice slice = mMockProviderModelSlice.getSlice();
assertThat(slice).isNotNull();
- verify(mListBuilder, times(4)).addRow(any(ListBuilder.RowBuilder.class));
+ verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
}
@Test
@UiThreadTest
- public void getSlice_haveTwoDisconnectedWifiAndNoCarrier_getThreeRow() {
+ public void getSlice_haveTwoDisconnectedWifiAndNoCarrier_getFourRow() {
mWifiList.clear();
mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
WifiEntry.CONNECTED_STATE_DISCONNECTED, "wifi1_key", true);
@@ -240,13 +255,13 @@
final Slice slice = mMockProviderModelSlice.getSlice();
assertThat(slice).isNotNull();
- verify(mListBuilder, times(3)).addRow(any(ListBuilder.RowBuilder.class));
+ verify(mListBuilder, times(4)).addRow(any(ListBuilder.RowBuilder.class));
assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
}
@Test
@UiThreadTest
- public void getSlice_haveEthernetAndCarrierAndTwoDisconnectedWifi_getFiveRow() {
+ public void getSlice_haveEthernetAndCarrierAndTwoDisconnectedWifi_getSixRow() {
mWifiList.clear();
mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
WifiEntry.CONNECTED_STATE_DISCONNECTED, "wifi1_key", true);
@@ -264,13 +279,13 @@
assertThat(slice).isNotNull();
assertThat(mMockProviderModelSlice.hasCreateEthernetRow()).isTrue();
verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
- verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
+ verify(mListBuilder, times(6)).addRow(any(ListBuilder.RowBuilder.class));
assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
}
@Test
@UiThreadTest
- public void getSlice_haveEthernetAndCarrierAndConnectedWifiAndDisconnectedWifi_getFiveRow() {
+ public void getSlice_haveEthernetAndCarrierAndConnectedWifiAndDisconnectedWifi_getSixRow() {
mWifiList.clear();
mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
WifiEntry.CONNECTED_STATE_CONNECTED, "wifi1_key", true);
@@ -288,7 +303,7 @@
assertThat(slice).isNotNull();
assertThat(mMockProviderModelSlice.hasCreateEthernetRow()).isTrue();
verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
- verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
+ verify(mListBuilder, times(6)).addRow(any(ListBuilder.RowBuilder.class));
assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
}
@@ -380,6 +395,11 @@
return super.getSeeAllRow();
}
+ @Override
+ public ListBuilder.RowBuilder getWifiSliceItemRow(WifiSliceItem wifiSliceItem) {
+ return super.getWifiSliceItemRow(wifiSliceItem);
+ }
+
public boolean hasCreateEthernetRow() {
return mHasCreateEthernetRow;
}
@@ -420,29 +440,4 @@
verify(mMockNetworkProviderWorker, never()).connectCarrierNetwork();
}
-
- @Test
- public void getWifiSliceItemRow_wifiNoInternetAccess_actionConnectToWifiSsid() {
- when(mWifiSliceItem.getKey()).thenReturn("wifi_key");
- when(mWifiSliceItem.getTitle()).thenReturn("wifi_ssid");
- when(mWifiSliceItem.hasInternetAccess()).thenReturn(false);
-
- ListBuilder.RowBuilder rowBuilder =
- mMockProviderModelSlice.getWifiSliceItemRow(mWifiSliceItem);
-
- assertThat(rowBuilder.getPrimaryAction().getTitle())
- .isEqualTo("wifi_ssid");
- }
-
- @Test
- public void getWifiSliceItemRow_wifiHasInternetAccess_actionConnectToCarrier() {
- when(mWifiSliceItem.getTitle()).thenReturn("wifi_ssid");
- when(mWifiSliceItem.hasInternetAccess()).thenReturn(true);
-
- ListBuilder.RowBuilder rowBuilder =
- mMockProviderModelSlice.getWifiSliceItemRow(mWifiSliceItem);
-
- assertThat(rowBuilder.getPrimaryAction().getTitle())
- .isEqualTo(ACTION_TITLE_CONNECT_TO_CARRIER);
- }
}
diff --git a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
index 0ef44ee..fc18ce7 100644
--- a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
@@ -40,6 +40,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.os.Looper;
+import android.os.UserManager;
import android.provider.Settings;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
@@ -82,6 +83,8 @@
private static final String KEY = "preference_group";
@Mock
+ private UserManager mUserManager;
+ @Mock
private SubscriptionManager mSubscriptionManager;
@Mock
private ConnectivityManager mConnectivityManager;
@@ -121,10 +124,12 @@
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork);
when(mConnectivityManager.getNetworkCapabilities(mActiveNetwork))
.thenReturn(mNetworkCapabilities);
+ when(mUserManager.isAdminUser()).thenReturn(true);
when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
mPreferenceManager = new PreferenceManager(mContext);
diff --git a/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java b/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java
index e475e6f..9ad4a37 100644
--- a/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java
+++ b/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java
@@ -18,12 +18,9 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -32,9 +29,7 @@
import android.net.Uri;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
-import android.os.Handler;
-import androidx.fragment.app.FragmentActivity;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -82,8 +77,6 @@
@Rule
public final MockitoRule mMocks = MockitoJUnit.rule();
@Mock
- Handler mMainThreadHandler;
- @Mock
PanelContentCallback mPanelContentCallback;
@Mock
InternetUpdater mInternetUpdater;
@@ -91,17 +84,34 @@
private WifiManager mWifiManager;
@Mock
private ProviderModelSliceHelper mProviderModelSliceHelper;
- @Mock
- private FragmentActivity mPanelActivity;
private Context mContext;
+ private FakeHandlerInjector mFakeHandlerInjector;
private InternetConnectivityPanel mPanel;
+ private class FakeHandlerInjector extends InternetConnectivityPanel.HandlerInjector {
+
+ private Runnable mRunnable;
+
+ FakeHandlerInjector(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void postDelay(Runnable runnable) {
+ mRunnable = runnable;
+ }
+
+ public Runnable getRunnable() {
+ return mRunnable;
+ }
+ }
+
@Before
public void setUp() {
mContext = spy(ApplicationProvider.getApplicationContext());
+ mFakeHandlerInjector = new FakeHandlerInjector(mContext);
when(mContext.getApplicationContext()).thenReturn(mContext);
- when(mContext.getMainThreadHandler()).thenReturn(mMainThreadHandler);
when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
mPanel = InternetConnectivityPanel.create(mContext);
@@ -109,6 +119,7 @@
mPanel.mIsProviderModelEnabled = true;
mPanel.mInternetUpdater = mInternetUpdater;
mPanel.mProviderModelSliceHelper = mProviderModelSliceHelper;
+ mPanel.mHandlerInjector = mFakeHandlerInjector;
}
@Test
@@ -204,20 +215,6 @@
}
@Test
- public void getCustomizedButtonTitle_wifiOff_turnOnWifi() {
- doReturn(false).when(mInternetUpdater).isWifiEnabled();
-
- assertThat(mPanel.getCustomizedButtonTitle()).isEqualTo(BUTTON_TURN_ON_WIFI);
- }
-
- @Test
- public void getCustomizedButtonTitle_wifiOn_turnOffWifi() {
- doReturn(true).when(mInternetUpdater).isWifiEnabled();
-
- assertThat(mPanel.getCustomizedButtonTitle()).isEqualTo(BUTTON_TURN_OFF_WIFI);
- }
-
- @Test
public void getSlices_providerModelDisabled_containsNecessarySlices() {
mPanel.mIsProviderModelEnabled = false;
List<Uri> uris = mPanel.getSlices();
@@ -241,31 +238,6 @@
}
@Test
- public void onClickCustomizedButton_wifiOn_setWifiOff() {
- doReturn(true).when(mInternetUpdater).isWifiEnabled();
-
- mPanel.onClickCustomizedButton(mPanelActivity);
-
- verify(mWifiManager).setWifiEnabled(false);
- }
-
- @Test
- public void onClickCustomizedButton_wifiOff_setWifiOn() {
- doReturn(false).when(mInternetUpdater).isWifiEnabled();
-
- mPanel.onClickCustomizedButton(mPanelActivity);
-
- verify(mWifiManager).setWifiEnabled(true);
- }
-
- @Test
- public void onClickCustomizedButton_shouldNotFinishActivity() {
- mPanel.onClickCustomizedButton(mPanelActivity);
-
- verify(mPanelActivity, never()).finish();
- }
-
- @Test
public void updatePanelTitle_onHeaderChanged() {
clearInvocations(mPanelContentCallback);
@@ -295,36 +267,41 @@
}
@Test
- public void showProgressBar_wifiDisabled_hideProgress() {
+ public void updateProgressBar_wifiDisabled_hideProgress() {
mPanel.mIsProgressBarVisible = true;
doReturn(false).when(mInternetUpdater).isWifiEnabled();
clearInvocations(mPanelContentCallback);
- mPanel.showProgressBar();
+ mPanel.updateProgressBar();
assertThat(mPanel.isProgressBarVisible()).isFalse();
verify(mPanelContentCallback).onProgressBarVisibleChanged();
}
@Test
- public void showProgressBar_noWifiScanResults_showProgressForever() {
+ public void updateProgressBar_noWifiScanResults_showProgressForever() {
+ mPanel.mIsScanningSubTitleShownOnce = false;
mPanel.mIsProgressBarVisible = false;
doReturn(true).when(mInternetUpdater).isWifiEnabled();
List<ScanResult> noWifiScanResults = new ArrayList<>();
doReturn(noWifiScanResults).when(mWifiManager).getScanResults();
clearInvocations(mPanelContentCallback);
- mPanel.showProgressBar();
+ mPanel.updateProgressBar();
- assertThat(mPanel.isProgressBarVisible()).isTrue();
+ assertThat(mPanel.mIsProgressBarVisible).isTrue();
verify(mPanelContentCallback).onProgressBarVisibleChanged();
verify(mPanelContentCallback).onHeaderChanged();
- verify(mMainThreadHandler, never())
- .postDelayed(any() /* mHideProgressBarRunnable */, anyLong());
+
+ assertThat(mFakeHandlerInjector.getRunnable())
+ .isEqualTo(mPanel.mHideScanningSubTitleRunnable);
+ mFakeHandlerInjector.getRunnable().run();
+ assertThat(mPanel.mIsScanningSubTitleShownOnce).isTrue();
+ assertThat(mPanel.mIsProgressBarVisible).isTrue();
}
@Test
- public void showProgressBar_hasWifiScanResults_showProgressDelayedHide() {
+ public void updateProgressBar_hasWifiScanResults_showProgressDelayedHide() {
mPanel.mIsProgressBarVisible = false;
doReturn(true).when(mInternetUpdater).isWifiEnabled();
List<ScanResult> hasWifiScanResults = mock(ArrayList.class);
@@ -332,11 +309,15 @@
doReturn(hasWifiScanResults).when(mWifiManager).getScanResults();
clearInvocations(mPanelContentCallback);
- mPanel.showProgressBar();
+ mPanel.updateProgressBar();
assertThat(mPanel.isProgressBarVisible()).isTrue();
verify(mPanelContentCallback).onProgressBarVisibleChanged();
- verify(mMainThreadHandler).postDelayed(any() /* mHideProgressBarRunnable */, anyLong());
+
+ assertThat(mFakeHandlerInjector.getRunnable())
+ .isEqualTo(mPanel.mHideProgressBarRunnable);
+ mFakeHandlerInjector.getRunnable().run();
+ assertThat(mPanel.mIsProgressBarVisible).isFalse();
}
@Test
diff --git a/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java b/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java
index 2199023..3b61a73 100644
--- a/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java
+++ b/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java
@@ -27,10 +27,7 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.android.settings.testutils.FeatureFlagUtilsRule;
-
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,9 +36,6 @@
private static final String TEST_PACKAGENAME = "com.test.packagename";
- @Rule
- public final FeatureFlagUtilsRule mFeatureFlagUtilsRule = new FeatureFlagUtilsRule();
-
private Context mContext;
private PanelFeatureProviderImpl mProvider;
private Bundle mBundle;
@@ -71,24 +65,4 @@
assertThat(panel).isInstanceOf(VolumePanel.class);
}
-
- @Test
- public void getPanel_wifi_returnsWifiPanelWhenProviderModelDisable() {
- mFeatureFlagUtilsRule.setProviderModelEnabled(false);
- mBundle.putString(KEY_PANEL_TYPE_ARGUMENT, Settings.Panel.ACTION_WIFI);
-
- final PanelContent panel = mProvider.getPanel(mContext, mBundle);
-
- assertThat(panel).isInstanceOf(WifiPanel.class);
- }
-
- @Test
- public void getPanel_wifi_returnsInternetConnectivityPanelWhenProviderModelDisable() {
- mFeatureFlagUtilsRule.setProviderModelEnabled(true);
- mBundle.putString(KEY_PANEL_TYPE_ARGUMENT, Settings.Panel.ACTION_WIFI);
-
- final PanelContent panel = mProvider.getPanel(mContext, mBundle);
-
- assertThat(panel).isInstanceOf(InternetConnectivityPanel.class);
- }
}
diff --git a/tests/unit/src/com/android/settings/testutils/FeatureFlagUtilsRule.java b/tests/unit/src/com/android/settings/testutils/FeatureFlagUtilsRule.java
deleted file mode 100644
index 910073e..0000000
--- a/tests/unit/src/com/android/settings/testutils/FeatureFlagUtilsRule.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.testutils;
-
-import android.content.Context;
-import android.util.FeatureFlagUtils;
-
-import androidx.test.core.app.ApplicationProvider;
-
-import org.junit.rules.ExternalResource;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A test rule that is used to automatically recover the FeatureFlagUtils resource after testing.
- *
- * Example:
- * <pre class="code"><code class="java">
- * public class ExampleTest {
- *
- * @Rule
- * public final FeatureFlagUtilsRule mFeatureFlagUtilsRule = new FeatureFlagUtilsRule();
- *
- * }
- * </code></pre>
- */
-public class FeatureFlagUtilsRule extends ExternalResource {
-
- private Context mContext;
- private Map<String, Boolean> mBackupFeatureFlags = new HashMap<String, Boolean>();
-
- @Override
- protected void before() throws Throwable {
- mContext = ApplicationProvider.getApplicationContext();
- }
-
- @Override
- protected void after() {
- mBackupFeatureFlags.forEach((k, v) -> FeatureFlagUtils.setEnabled(mContext, k, v));
- }
-
- public void setEnabled(String feature, boolean enabled) {
- if (enabled == FeatureFlagUtils.isEnabled(mContext, feature)) {
- return;
- }
- mBackupFeatureFlags.putIfAbsent(feature, !enabled);
- FeatureFlagUtils.setEnabled(mContext, feature, enabled);
- }
-
- public void setProviderModelEnabled(boolean enabled) {
- setEnabled(FeatureFlagUtils.SETTINGS_PROVIDER_MODEL, enabled);
- }
-}
diff --git a/tests/unit/src/com/android/settings/widget/GearPreferenceTest.java b/tests/unit/src/com/android/settings/widget/GearPreferenceTest.java
new file mode 100644
index 0000000..a47eade
--- /dev/null
+++ b/tests/unit/src/com/android/settings/widget/GearPreferenceTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.preference.PreferenceViewHolder;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.testutils.ResourcesUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Unittest for GearPreference */
+@RunWith(AndroidJUnit4.class)
+public class GearPreferenceTest {
+ @Mock
+ private GearPreference.OnGearClickListener mOnGearClickListener;
+
+ private Context mContext = ApplicationProvider.getApplicationContext();
+ private GearPreference mGearPreference;
+ private PreferenceViewHolder mViewHolder;
+ private View mGearView;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mGearPreference =
+ new GearPreference(mContext, null);
+ int layoutId = ResourcesUtils.getResourcesId(mContext, "layout", "preference_widget_gear");
+ PreferenceViewHolder holder =
+ PreferenceViewHolder.createInstanceForTests(
+ LayoutInflater.from(ApplicationProvider.getApplicationContext())
+ .inflate(layoutId, null));
+ mViewHolder = spy(holder);
+ mGearView = new View(mContext, null);
+ int gearId = ResourcesUtils.getResourcesId(mContext, "id", "settings_button");
+ when(mViewHolder.findViewById(gearId)).thenReturn(mGearView);
+ }
+
+ @Test
+ public void onBindViewHolder_gearIsVisible() {
+ mGearPreference.setOnGearClickListener(mOnGearClickListener);
+
+ mGearPreference.onBindViewHolder(mViewHolder);
+
+ assertThat(mGearView.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_gearIsGone() {
+ mGearPreference.setOnGearClickListener(null);
+
+ mGearPreference.onBindViewHolder(mViewHolder);
+
+ assertThat(mGearView.getVisibility()).isEqualTo(View.GONE);
+ }
+}
diff --git a/tests/unit/src/com/android/settings/widget/MutableGearPreferenceTest.java b/tests/unit/src/com/android/settings/widget/MutableGearPreferenceTest.java
new file mode 100644
index 0000000..44b1d38
--- /dev/null
+++ b/tests/unit/src/com/android/settings/widget/MutableGearPreferenceTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.widget;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.widget.ImageView;
+
+import androidx.preference.PreferenceViewHolder;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.testutils.ResourcesUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Unittest for MutableGearPreference */
+@RunWith(AndroidJUnit4.class)
+public class MutableGearPreferenceTest {
+ @Mock
+ private MutableGearPreference.OnGearClickListener mOnGearClickListener;
+
+ private Context mContext = ApplicationProvider.getApplicationContext();
+ private MutableGearPreference mMutableGearPreference;
+ private PreferenceViewHolder mViewHolder;
+ private ImageView mGearView;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mMutableGearPreference =
+ new MutableGearPreference(mContext, null);
+ int layoutId =
+ ResourcesUtils.getResourcesId(mContext, "layout", "preference_widget_gear");
+ PreferenceViewHolder holder =
+ PreferenceViewHolder.createInstanceForTests(
+ LayoutInflater.from(ApplicationProvider.getApplicationContext())
+ .inflate(layoutId, null));
+ mViewHolder = spy(holder);
+ mGearView = spy(new ImageView(mContext, null));
+ int gearId = ResourcesUtils.getResourcesId(mContext, "id", "settings_button");
+ when(mViewHolder.findViewById(gearId)).thenReturn(mGearView);
+ }
+
+ @Test
+ public void onBindViewHolder_gearChangeAlpha() {
+ mMutableGearPreference.setGearEnabled(false);
+ mMutableGearPreference.setOnGearClickListener(mOnGearClickListener);
+
+ mMutableGearPreference.onBindViewHolder(mViewHolder);
+
+ verify(mGearView).setImageAlpha(anyInt());
+ }
+
+ private static int getDisabledAlphaValue(Context context) {
+ TypedValue value = new TypedValue();
+ context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true);
+ return (int) (value.getFloat() * 255);
+ }
+}