[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: d21e27606f -s ours
am skip reason: contains skip directive
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/ThemePicker/+/28210205
Change-Id: Ic181e5ac3632316283c1f08551c165d49136c39d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 8676f26..58e6413 100644
--- a/Android.bp
+++ b/Android.bp
@@ -93,7 +93,6 @@
name: "ThemePicker_defaults",
static_libs: [
"ThemePickerLib",
- "ThemePickerOverridesLib",
"hilt_android",
],
@@ -115,6 +114,14 @@
system_ext_specific: true,
}
+java_defaults {
+ name: "ThemePicker_defaults_with_overrides",
+ defaults: ["ThemePicker_defaults"],
+ static_libs: [
+ "ThemePickerOverridesLib",
+ ],
+}
+
prebuilt_etc {
name: "android.software.theme_picker.xml",
system_ext_specific: true,
@@ -128,7 +135,7 @@
android_app {
name: "ThemePicker",
package_name: "com.android.wallpaper",
- defaults: ["ThemePicker_defaults"],
+ defaults: ["ThemePicker_defaults_with_overrides"],
platform_apis: true,
manifest: "AndroidManifest.xml",
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index a165f4b..2c4355f 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,6 +1,13 @@
+[Builtin Hooks]
+ktfmt = true
+
+[Builtin Hooks Options]
+ktfmt = --kotlinlang-style --include-dirs=src,src_override,tests
+
[Hook Scripts]
checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
-ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check -i ${REPO_ROOT}/packages/apps/ThemePicker/ktfmt_includes.txt ${PREUPLOAD_FILES}
-
flag_hook = ${REPO_ROOT}/frameworks/base/packages/SystemUI/flag_check.py --msg=${PREUPLOAD_COMMIT_MESSAGE} --files=${PREUPLOAD_FILES} --project=${REPO_PATH}
+
+[Tool Paths]
+ktfmt = ${REPO_ROOT}/external/ktfmt/ktfmt.sh
diff --git a/ktfmt_includes.txt b/ktfmt_includes.txt
deleted file mode 100644
index 0708ab2..0000000
--- a/ktfmt_includes.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-+src/
-+src_override/
-+tests/
--src/com/android/customization/module/SysUiStatsLogger.kt
diff --git a/res/drawable-night/ic_contrast_high.xml b/res/drawable-night/ic_contrast_high.xml
new file mode 100644
index 0000000..3134ab8
--- /dev/null
+++ b/res/drawable-night/ic_contrast_high.xml
@@ -0,0 +1,28 @@
+<!--
+ ~ Copyright (C) 2024 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="48dp"
+ android:height="48dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/system_accent1_200"
+ android:pathData="M12,4C7,4 2.73,7.11 1,11.5C2.73,15.89 7,19 12,19s9.27,-3.11 11,-7.5C21.27,7.11 17,4 12,4zM12,16c-2.48,0 -4.5,-2.02 -4.5,-4.5S9.52,7 12,7s4.5,2.02 4.5,4.5S14.48,16 12,16z"/>
+ <path
+ android:fillColor="@android:color/system_accent1_50"
+ android:pathData="M12,11.5m-2.7,0a2.7,2.7 0,1 1,5.4 0a2.7,2.7 0,1 1,-5.4 0"/>
+</vector>
diff --git a/res/drawable-night/ic_contrast_medium.xml b/res/drawable-night/ic_contrast_medium.xml
new file mode 100644
index 0000000..3928306
--- /dev/null
+++ b/res/drawable-night/ic_contrast_medium.xml
@@ -0,0 +1,28 @@
+<!--
+ ~ Copyright (C) 2024 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="48dp"
+ android:height="48dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/system_accent1_400"
+ android:pathData="M12,4C7,4 2.73,7.11 1,11.5C2.73,15.89 7,19 12,19s9.27,-3.11 11,-7.5C21.27,7.11 17,4 12,4zM12,16c-2.48,0 -4.5,-2.02 -4.5,-4.5S9.52,7 12,7s4.5,2.02 4.5,4.5S14.48,16 12,16z"/>
+ <path
+ android:fillColor="@android:color/system_accent1_100"
+ android:pathData="M12,11.5m-2.7,0a2.7,2.7 0,1 1,5.4 0a2.7,2.7 0,1 1,-5.4 0"/>
+</vector>
diff --git a/res/drawable-night/ic_contrast_standard.xml b/res/drawable-night/ic_contrast_standard.xml
new file mode 100644
index 0000000..39e6137
--- /dev/null
+++ b/res/drawable-night/ic_contrast_standard.xml
@@ -0,0 +1,28 @@
+<!--
+ ~ Copyright (C) 2024 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="48dp"
+ android:height="48dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/system_accent1_700"
+ android:pathData="M12,4C7,4 2.73,7.11 1,11.5C2.73,15.89 7,19 12,19s9.27,-3.11 11,-7.5C21.27,7.11 17,4 12,4zM12,16c-2.48,0 -4.5,-2.02 -4.5,-4.5S9.52,7 12,7s4.5,2.02 4.5,4.5S14.48,16 12,16z"/>
+ <path
+ android:fillColor="@android:color/system_accent1_200"
+ android:pathData="M12,11.5m-2.7,0a2.7,2.7 0,1 1,5.4 0a2.7,2.7 0,1 1,-5.4 0"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/check_circle_grey_large.xml b/res/drawable/check_circle_grey_large.xml
deleted file mode 100644
index f22c910..0000000
--- a/res/drawable/check_circle_grey_large.xml
+++ /dev/null
@@ -1,31 +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.
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item>
- <shape android:shape="oval">
- <size android:width="@dimen/center_check_size"
- android:height="@dimen/center_check_size" />
- <solid android:color="@color/color_accent_primary_variant" />
- </shape>
- </item>
- <item>
- <inset android:drawable="@drawable/ic_check_24dp"
- android:insetTop="@dimen/center_check_padding"
- android:insetRight="@dimen/center_check_padding"
- android:insetBottom="@dimen/center_check_padding"
- android:insetLeft="@dimen/center_check_padding"/>
- </item>
-</layer-list>
diff --git a/res/drawable/customization_option_entry_icon_background.xml b/res/drawable/customization_option_entry_icon_background.xml
new file mode 100644
index 0000000..b92fa0e
--- /dev/null
+++ b/res/drawable/customization_option_entry_icon_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright (C) 2024 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/picker_section_icon_background" />
+ <corners android:radius="18dp" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/ic_colors.xml b/res/drawable/ic_colors.xml
new file mode 100644
index 0000000..31bf4d9
--- /dev/null
+++ b/res/drawable/ic_colors.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 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="960"
+ android:viewportHeight="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M346,820L100,574Q90,564 85,552Q80,540 80,527Q80,514 85,502Q90,490 100,480L330,251L224,145L286,80L686,480Q696,490 700.5,502Q705,514 705,527Q705,540 700.5,552Q696,564 686,574L440,820Q430,830 418,835Q406,840 393,840Q380,840 368,835Q356,830 346,820ZM393,314L179,528Q179,528 179,528Q179,528 179,528L607,528Q607,528 607,528Q607,528 607,528L393,314ZM792,840Q756,840 731,814.5Q706,789 706,752Q706,725 719.5,701Q733,677 750,654L792,600L836,654Q852,677 866,701Q880,725 880,752Q880,789 854,814.5Q828,840 792,840Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_contrast_high.xml b/res/drawable/ic_contrast_high.xml
new file mode 100644
index 0000000..147efb0
--- /dev/null
+++ b/res/drawable/ic_contrast_high.xml
@@ -0,0 +1,28 @@
+<!--
+ ~ Copyright (C) 2024 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="48dp"
+ android:height="48dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/system_accent1_700"
+ android:pathData="M12,4C7,4 2.73,7.11 1,11.5C2.73,15.89 7,19 12,19s9.27,-3.11 11,-7.5C21.27,7.11 17,4 12,4zM12,16c-2.48,0 -4.5,-2.02 -4.5,-4.5S9.52,7 12,7s4.5,2.02 4.5,4.5S14.48,16 12,16z"/>
+ <path
+ android:fillColor="@android:color/system_accent1_900"
+ android:pathData="M12,11.5m-2.7,0a2.7,2.7 0,1 1,5.4 0a2.7,2.7 0,1 1,-5.4 0"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_contrast_medium.xml b/res/drawable/ic_contrast_medium.xml
new file mode 100644
index 0000000..e839e0b
--- /dev/null
+++ b/res/drawable/ic_contrast_medium.xml
@@ -0,0 +1,28 @@
+<!--
+ ~ Copyright (C) 2024 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="48dp"
+ android:height="48dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/system_accent1_500"
+ android:pathData="M12,4C7,4 2.73,7.11 1,11.5C2.73,15.89 7,19 12,19s9.27,-3.11 11,-7.5C21.27,7.11 17,4 12,4zM12,16c-2.48,0 -4.5,-2.02 -4.5,-4.5S9.52,7 12,7s4.5,2.02 4.5,4.5S14.48,16 12,16z"/>
+ <path
+ android:fillColor="@android:color/system_accent1_700"
+ android:pathData="M12,11.5m-2.7,0a2.7,2.7 0,1 1,5.4 0a2.7,2.7 0,1 1,-5.4 0"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_contrast_standard.xml b/res/drawable/ic_contrast_standard.xml
new file mode 100644
index 0000000..75516d8
--- /dev/null
+++ b/res/drawable/ic_contrast_standard.xml
@@ -0,0 +1,28 @@
+<!--
+ ~ Copyright (C) 2024 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="48dp"
+ android:height="48dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/system_accent1_100"
+ android:pathData="M12,4C7,4 2.73,7.11 1,11.5C2.73,15.89 7,19 12,19s9.27,-3.11 11,-7.5C21.27,7.11 17,4 12,4zM12,16c-2.48,0 -4.5,-2.02 -4.5,-4.5S9.52,7 12,7s4.5,2.02 4.5,4.5S14.48,16 12,16z"/>
+ <path
+ android:fillColor="@android:color/system_accent1_600"
+ android:pathData="M12,11.5m-2.7,0a2.7,2.7 0,1 1,5.4 0a2.7,2.7 0,1 1,-5.4 0"/>
+</vector>
\ No newline at end of file
diff --git a/res/layout/color_contrast_section_view.xml b/res/layout/color_contrast_section_view.xml
new file mode 100644
index 0000000..ee6bd5b
--- /dev/null
+++ b/res/layout/color_contrast_section_view.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.customization.picker.settings.ui.view.ColorContrastSectionView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:background="?selectableItemBackground"
+ android:clickable="true"
+ android:paddingVertical="@dimen/option_section_vertical_padding"
+ android:paddingHorizontal="@dimen/section_horizontal_padding"
+ android:orientation="horizontal">
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:layout_gravity="center">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/color_contrast_section_title"
+ style="@style/SectionTitleTextStyle" />
+
+ <TextView
+ android:id="@+id/color_contrast_section_description"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/SectionSubtitleTextStyle"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="@dimen/option_tile_width"
+ android:layout_height="@dimen/option_tile_width"
+ android:orientation="horizontal"
+ android:background="@drawable/picker_section_icon_background"
+ android:importantForAccessibility="noHideDescendants"
+ android:gravity="center"
+ android:divider="@drawable/horizontal_divider_14dp"
+ android:layout_gravity="center"
+ android:showDividers="middle">
+
+ <ImageView
+ android:id="@+id/icon_1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone" />
+ </LinearLayout>
+
+</com.android.customization.picker.settings.ui.view.ColorContrastSectionView>
\ No newline at end of file
diff --git a/res/layout/color_option_overflow_no_background.xml b/res/layout/color_option_overflow_no_background.xml
index abb9c6b..7a37536 100644
--- a/res/layout/color_option_overflow_no_background.xml
+++ b/res/layout/color_option_overflow_no_background.xml
@@ -24,7 +24,10 @@
android:layout_gravity="center"
android:clipChildren="false"
android:gravity="center"
- android:padding="@dimen/option_tile_grid_tile_padding_min"
+ android:paddingStart="@dimen/option_tile_grid_tile_padding_min"
+ android:paddingEnd="@dimen/option_tile_grid_tile_padding_min"
+ android:paddingTop="@dimen/option_tile_grid_icon_padding_min"
+ android:paddingBottom="@dimen/option_tile_grid_icon_padding_min"
android:layout_weight="1"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintWidth_max="@dimen/component_color_chip_small_diameter_default">
diff --git a/res/layout/customization_option_entry_app_grid.xml b/res/layout/customization_option_entry_app_grid.xml
new file mode 100644
index 0000000..c31b2a2
--- /dev/null
+++ b/res/layout/customization_option_entry_app_grid.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+ 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="wrap_content"
+ android:paddingHorizontal="@dimen/customization_option_entry_horizontal_padding"
+ android:paddingVertical="@dimen/customization_option_entry_vertical_padding"
+ android:clickable="true">
+
+ <TextView
+ android:id="@+id/option_entry_app_grid_title"
+ style="@style/CustomizationOptionEntryTitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/grid_title"
+ android:layout_marginEnd="@dimen/customization_option_entry_text_margin_end"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/option_entry_app_grid_icon"
+ app:layout_constraintBottom_toTopOf="@+id/option_entry_app_grid_description"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_chainStyle="packed" />
+
+ <TextView
+ android:id="@+id/option_entry_app_grid_description"
+ style="@style/CustomizationOptionEntrySubtitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/customization_option_entry_text_margin_end"
+ android:text="4x4"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/option_entry_app_grid_icon"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/option_entry_app_grid_title" />
+
+ <FrameLayout
+ android:id="@+id/option_entry_app_grid_icon"
+ android:layout_width="@dimen/customization_option_entry_icon_size"
+ android:layout_height="@dimen/customization_option_entry_icon_size"
+ android:orientation="horizontal"
+ android:background="@drawable/customization_option_entry_icon_background"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/customization_option_entry_app_shape.xml b/res/layout/customization_option_entry_app_shape.xml
new file mode 100644
index 0000000..965b0a1
--- /dev/null
+++ b/res/layout/customization_option_entry_app_shape.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+ 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="wrap_content"
+ android:paddingHorizontal="@dimen/customization_option_entry_horizontal_padding"
+ android:paddingVertical="@dimen/customization_option_entry_vertical_padding"
+ android:clickable="true">
+
+ <TextView
+ style="@style/CustomizationOptionEntryTitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/preview_name_shape"
+ android:layout_marginEnd="@dimen/customization_option_entry_text_margin_end"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/option_entry_app_shape_icon"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_chainStyle="packed" />
+
+ <FrameLayout
+ android:id="@+id/option_entry_app_shape_icon"
+ android:layout_width="@dimen/customization_option_entry_icon_size"
+ android:layout_height="@dimen/customization_option_entry_icon_size"
+ android:orientation="horizontal"
+ android:background="@drawable/customization_option_entry_icon_background"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/customization_option_entry_clock.xml b/res/layout/customization_option_entry_clock.xml
new file mode 100644
index 0000000..c302965
--- /dev/null
+++ b/res/layout/customization_option_entry_clock.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+ 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="wrap_content"
+ android:paddingHorizontal="@dimen/customization_option_entry_horizontal_padding"
+ android:paddingVertical="@dimen/customization_option_entry_vertical_padding"
+ android:clickable="true">
+
+ <TextView
+ style="@style/CustomizationOptionEntryTitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/clock_title"
+ android:layout_marginEnd="@dimen/customization_option_entry_text_margin_end"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/option_entry_clock_icon"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_chainStyle="packed" />
+
+ <FrameLayout
+ android:id="@+id/option_entry_clock_icon"
+ android:layout_width="@dimen/customization_option_entry_icon_size"
+ android:layout_height="@dimen/customization_option_entry_icon_size"
+ android:orientation="horizontal"
+ android:background="@drawable/customization_option_entry_icon_background"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/customization_option_entry_colors.xml b/res/layout/customization_option_entry_colors.xml
new file mode 100644
index 0000000..3046173
--- /dev/null
+++ b/res/layout/customization_option_entry_colors.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+ 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="wrap_content"
+ android:paddingHorizontal="@dimen/customization_option_entry_horizontal_padding"
+ android:paddingVertical="@dimen/customization_option_entry_vertical_padding"
+ android:clickable="true">
+
+ <TextView
+ style="@style/CustomizationOptionEntryTitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/color_picker_title"
+ android:layout_marginEnd="@dimen/customization_option_entry_text_margin_end"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/option_entry_clock_icon"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_chainStyle="packed" />
+
+ <FrameLayout
+ android:id="@+id/option_entry_clock_icon"
+ android:layout_width="@dimen/customization_option_entry_icon_size"
+ android:layout_height="@dimen/customization_option_entry_icon_size"
+ android:orientation="horizontal"
+ android:background="@drawable/customization_option_entry_icon_background"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/customization_option_entry_keyguard_quick_affordance.xml b/res/layout/customization_option_entry_keyguard_quick_affordance.xml
new file mode 100644
index 0000000..475c8e5
--- /dev/null
+++ b/res/layout/customization_option_entry_keyguard_quick_affordance.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/customization_option_entry_horizontal_padding"
+ android:paddingVertical="@dimen/customization_option_entry_vertical_padding"
+ android:clickable="true">
+
+ <TextView
+ android:id="@+id/option_entry_keyguard_quick_affordance_title"
+ style="@style/CustomizationOptionEntryTitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/keyguard_quick_affordance_title"
+ android:layout_marginEnd="@dimen/customization_option_entry_text_margin_end"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/option_entry_keyguard_quick_affordance_icon"
+ app:layout_constraintBottom_toTopOf="@+id/option_entry_keyguard_quick_affordance_description"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_chainStyle="packed" />
+
+ <TextView
+ android:id="@+id/option_entry_keyguard_quick_affordance_description"
+ style="@style/CustomizationOptionEntrySubtitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/customization_option_entry_text_margin_end"
+ android:text="None"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/option_entry_keyguard_quick_affordance_icon"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/option_entry_keyguard_quick_affordance_title"
+ tools:text="Wallet, Nest" />
+
+ <LinearLayout
+ android:id="@+id/option_entry_keyguard_quick_affordance_icon"
+ android:layout_width="@dimen/customization_option_entry_icon_size"
+ android:layout_height="@dimen/customization_option_entry_icon_size"
+ android:orientation="horizontal"
+ android:background="@drawable/customization_option_entry_icon_background"
+ android:divider="@drawable/horizontal_divider_14dp"
+ android:layout_gravity="center"
+ android:showDividers="middle"
+ android:importantForAccessibility="noHideDescendants"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent">
+
+ <ImageView
+ android:id="@+id/option_entry_keyguard_quick_affordance_icon_1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:tint="@color/system_on_surface" />
+
+ <ImageView
+ android:id="@+id/option_entry_keyguard_quick_affordance_icon_2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:tint="@color/system_on_surface" />
+ </LinearLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/customization_option_entry_more_lock_settings.xml b/res/layout/customization_option_entry_more_lock_settings.xml
new file mode 100644
index 0000000..518af78
--- /dev/null
+++ b/res/layout/customization_option_entry_more_lock_settings.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+ 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="wrap_content"
+ android:paddingHorizontal="@dimen/customization_option_entry_horizontal_padding"
+ android:paddingVertical="@dimen/customization_option_entry_vertical_padding_large"
+ android:clickable="true">
+
+ <TextView
+ android:id="@+id/option_entry_more_lock_settings_title"
+ style="@style/CustomizationOptionEntryTitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/more_settings_section_title"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@+id/option_entry_more_lock_settings_description"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_chainStyle="packed" />
+
+ <TextView
+ android:id="@+id/option_entry_more_lock_settings_description"
+ style="@style/CustomizationOptionEntrySubtitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/more_settings_section_description"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/option_entry_more_lock_settings_title" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/customization_option_entry_show_notifications.xml b/res/layout/customization_option_entry_show_notifications.xml
new file mode 100644
index 0000000..b067131
--- /dev/null
+++ b/res/layout/customization_option_entry_show_notifications.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/customization_option_entry_horizontal_padding"
+ android:paddingVertical="@dimen/customization_option_entry_vertical_padding_large"
+ android:clickable="true">
+
+ <TextView
+ style="@style/CustomizationOptionEntryTitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/show_notifications_on_lock_screen"
+ android:layout_marginEnd="@dimen/customization_option_entry_text_margin_end"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/option_entry_show_notifications_switch"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_chainStyle="packed" />
+
+ <Switch
+ android:id="@+id/option_entry_show_notifications_switch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="false"
+ android:clickable="false"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ style="@style/Switch.SettingsLib"
+ tools:ignore="UseSwitchCompatOrMaterialXml" />
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/res/layout/customization_option_entry_themed_icons.xml b/res/layout/customization_option_entry_themed_icons.xml
new file mode 100644
index 0000000..06461dc
--- /dev/null
+++ b/res/layout/customization_option_entry_themed_icons.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/customization_option_entry_horizontal_padding"
+ android:paddingVertical="@dimen/customization_option_entry_vertical_padding_large"
+ android:clickable="true">
+
+ <TextView
+ android:id="@+id/option_entry_themed_icons_title"
+ style="@style/CustomizationOptionEntryTitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/themed_icon_title"
+ android:layout_marginEnd="@dimen/customization_option_entry_text_margin_end"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/option_entry_themed_icons_switch"
+ app:layout_constraintBottom_toTopOf="@+id/option_entry_themed_icons_description"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_chainStyle="packed" />
+
+ <TextView
+ android:id="@+id/option_entry_themed_icons_description"
+ style="@style/CustomizationOptionEntrySubtitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/customization_option_entry_text_margin_end"
+ android:text="@string/beta_title"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/option_entry_themed_icons_switch"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/option_entry_themed_icons_title" />
+
+ <Switch
+ android:id="@+id/option_entry_themed_icons_switch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="false"
+ android:clickable="false"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ style="@style/Switch.SettingsLib"
+ tools:ignore="UseSwitchCompatOrMaterialXml" />
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/res/layout/floating_sheet_clock.xml b/res/layout/floating_sheet_clock.xml
new file mode 100644
index 0000000..f917d9f
--- /dev/null
+++ b/res/layout/floating_sheet_clock.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 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="200dp"
+ android:background="#00ff00">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Clock customization bottom sheet"
+ android:layout_gravity="center" />
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/floating_sheet_colors.xml b/res/layout/floating_sheet_colors.xml
new file mode 100644
index 0000000..8e6ed64
--- /dev/null
+++ b/res/layout/floating_sheet_colors.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/floating_sheet_horizontal_padding"
+ android:orientation="vertical"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/floating_sheet_content_background"
+ android:paddingVertical="@dimen/floating_sheet_list_vertical_padding"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/color_type_tab_subhead"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:layout_marginHorizontal="20dp"
+ android:gravity="center"
+ android:text="@string/wallpaper_color_subheader"
+ android:textColor="@color/system_on_surface"
+ android:textSize="12sp" />
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/colors_horizontal_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dp"
+ android:clipChildren="false"
+ android:clipToPadding="false" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:gravity="center_vertical"
+ android:layout_marginHorizontal="20dp"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/dark_mode_toggle_title"
+ style="@style/SectionTitleTextStyle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/mode_title" />
+
+ <Switch
+ android:id="@+id/dark_mode_toggle"
+ style="@style/Switch.SettingsLib"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@null"
+ android:clickable="false"
+ android:focusable="false"
+ android:minHeight="0dp" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar
+ android:id="@+id/floating_bar_tabs"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginVertical="@dimen/floating_sheet_tab_toolbar_vertical_margin" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/floating_sheet_shortcut.xml b/res/layout/floating_sheet_shortcut.xml
new file mode 100644
index 0000000..ce4665e
--- /dev/null
+++ b/res/layout/floating_sheet_shortcut.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/floating_sheet_horizontal_padding"
+ android:orientation="vertical"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingVertical="@dimen/floating_sheet_list_vertical_padding"
+ android:background="@drawable/floating_sheet_content_background"
+ android:clipToPadding="false"
+ android:clipChildren="false">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/quick_affordance_horizontal_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"/>
+ </FrameLayout>
+
+ <com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar
+ android:id="@+id/floating_bar_tabs"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginVertical="@dimen/floating_sheet_tab_toolbar_vertical_margin" />
+</LinearLayout>
diff --git a/res/layout/fragment_color_picker.xml b/res/layout/fragment_color_picker.xml
index d33fb1f..7870140 100644
--- a/res/layout/fragment_color_picker.xml
+++ b/res/layout/fragment_color_picker.xml
@@ -44,7 +44,8 @@
android:id="@+id/lock_preview"
layout="@layout/wallpaper_preview_card"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="12dp"/>
<include
android:id="@+id/home_preview"
diff --git a/res/layout/quick_affordance_list_item.xml b/res/layout/quick_affordance_list_item.xml
new file mode 100644
index 0000000..c6b3fd4
--- /dev/null
+++ b/res/layout/quick_affordance_list_item.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="64dp"
+ android:layout_height="wrap_content"
+ android:divider="@drawable/vertical_divider_8dp"
+ android:clipChildren="false"
+ android:showDividers="middle">
+
+ <FrameLayout
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:background="@drawable/option_item_background"
+ android:clipChildren="false">
+
+ <ImageView
+ android:id="@id/selection_border"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/option_item_border"
+ android:alpha="0"
+ android:importantForAccessibility="no" />
+
+ <ImageView
+ android:id="@id/background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/option_item_background"
+ android:importantForAccessibility="no" />
+
+ <ImageView
+ android:id="@id/foreground"
+ android:layout_width="@dimen/keyguard_quick_affordance_icon_size"
+ android:layout_height="@dimen/keyguard_quick_affordance_icon_size"
+ android:layout_gravity="center"
+ android:tint="@color/system_on_surface" />
+ </FrameLayout>
+
+ <TextView
+ android:id="@id/text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textColor="@color/system_on_surface"
+ android:lines="2"
+ android:hyphenationFrequency="normal"
+ android:ellipsize="end" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 75d177a..adaa3b9 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Klaar"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Kortpaaie"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Kortpaaie"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Kleurkontras"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Verstek"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Medium"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Hoog"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Geen"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Wys kennisgewings op die sluitskerm"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index d377f40..a33a13e 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"ተከናውኗል"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"አቋራጮች"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"አቋራጮች"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"የቀለም ንጽጽር"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ነባሪ"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"መካከለኛ"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"ከፍተኛ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>፣ <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"ምንም"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"በማያ ገፅ ቁልፉ ላይ ማሳወቂያዎችን አሳይ"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 627a174..536dc3b 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"تم"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"الاختصارات"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"الاختصارات"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"تباين الألوان"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"تلقائي"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"متوسط"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"عالٍ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"\"<xliff:g id="FIRST">%1$s</xliff:g>\" و\"<xliff:g id="SECOND">%2$s</xliff:g>\""</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"بدون اختصارات"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"إظهار الإشعارات على شاشة القفل"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index ac66386..2d8b529 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"কৰা হ’ল"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"শ্বৰ্টকাট"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"শ্বৰ্টকাট"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"ৰঙৰ কনট্ৰাষ্ট"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ডিফ’ল্ট"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"মধ্যমীয়া"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"উচ্চ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"নাই"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"লক স্ক্ৰীনত জাননী দেখুৱাওক"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 8b04e46..b6d1f55 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Hazırdır"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Qısayollar"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Qısayollar"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Rəng kontrastı"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Defolt"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Orta"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Yüksək"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Heç biri"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Kilid ekranında bildirişləri göstərin"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 423424c..6b6293e 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Gotovo"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Prečice"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Prečice"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Kontrast boja"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Podrazumevano"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Srednje"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Visoko"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ništa"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Prikazuj obaveštenja na zaključanom ekranu"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index dc2321d..6b2b474 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Гатова"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Ярлыкі"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Ярлыкі"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Кантраст колераў"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Стандартна"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Сярэдні"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Высокі"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Няма"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Паказваць апавяшчэнні на экране блакіроўкі"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 0e1fbc7..051cd35 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Готово"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Преки пътища"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Преки пътища"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Цветове: Контраст"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Основно"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Средно"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Високо"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Няма"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Показване на известията на заключения екран"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index f4f4a92..e419aac 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"হয়ে গেছে"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"শর্টকাট"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"শর্টকাট"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"কালার কনট্রাস্ট"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ডিফল্ট"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"মাঝারি"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"বেশি"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"কোনও শর্টকাট নেই"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"লক স্ক্রিনে বিজ্ঞপ্তি দেখুন"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index d836d3c..e25a69a 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Gotovo"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Prečice"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Prečice"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Kontrast boja"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Zadano"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Srednje"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Visoko"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ništa"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Prikaz obavještenja na zaključanom ekranu"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 99c8479..b37ddd8 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Fet"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Dreceres"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Dreceres"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contrast de color"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Predeterminat"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Mitjà"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Alt"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Cap"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Mostra les notificacions a la pantalla de bloqueig"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 215a309..ffe69a4 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Hotovo"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Zkratky"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Zkratky"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Barevný kontrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Výchozí"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Střední"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Vysoký"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Žádné"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Zobrazovat oznámení na obrazovce uzamčení"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 4392fb8..d99847b 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Udfør"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Genveje"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Genveje"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Farvekontrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Standard"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Middel"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Høj"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ingen"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Vis notifikationer på låseskærmen"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 47ea22e..be98c62 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Fertig"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Verknüpfungen"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Verknüpfungen"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Farbkontrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Standard"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Mittel"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Hoch"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Keine"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Benachrichtigungen auf dem Sperrbildschirm einblenden"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 189068f..d9ce549 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Τέλος"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Συντομεύσεις"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Συντομεύσεις"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Χρωματ. αντίθεση"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Προεπιλογή"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Μέτρια"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Υψηλή"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Καμία"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Εμφάνιση ειδοποιήσεων στην οθόνη κλειδώματος"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index c452160..33de28b 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Done"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Shortcuts"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Shortcuts"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Colour contrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Default"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Medium"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"High"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"None"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Show notifications on the lock screen"</string>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 55e0760..b256398 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Done"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Shortcuts"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Shortcuts"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Color contrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Default"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Medium"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"High"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"None"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Show notifications on the lock screen"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index c452160..33de28b 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Done"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Shortcuts"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Shortcuts"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Colour contrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Default"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Medium"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"High"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"None"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Show notifications on the lock screen"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index c452160..33de28b 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Done"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Shortcuts"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Shortcuts"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Colour contrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Default"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Medium"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"High"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"None"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Show notifications on the lock screen"</string>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index b470745..b6f48d3 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Done"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Shortcuts"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Shortcuts"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Color contrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Default"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Medium"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"High"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"None"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Show notifications on the lock screen"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 1ff32ad..318e844 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Listo"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Accesos directos"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Accesos directos"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contr. de color"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Predeterminado"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Medio"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Alto"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ninguno"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Mostrar las notificaciones en la pantalla de bloqueo"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index ced8e8d..ecb4e04 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Hecho"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Accesos directos"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Accesos directos"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contraste de color"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Predeterminado"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Medio"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Alto"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ninguno"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Mostrar notificaciones en la pantalla de bloqueo"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 98784ce..28fefd4 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Valmis"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Otseteed"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Otseteed"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Värvikontrastsus"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Vaikeseade"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Keskmine"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Suur"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Pole"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Kuva märguanded lukustuskuval"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 3700475..8c2b406 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Eginda"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Lasterbideak"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Lasterbideak"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Kolore-kontrastea"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Lehenetsia"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Ertaina"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Handia"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g> eta <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Bat ere ez"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Erakutsi jakinarazpenak pantaila blokeatuan"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index b3f42bc..fa81da6 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"تمام"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"میانبرها"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"میانبرها"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"کنتراست رنگ"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"پیشفرض"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"متوسط"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"زیاد"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>، <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"هیچکدام"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"نمایش اعلانها در صفحه قفل"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 6fc993c..feaadd3 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Valmis"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Pikakuvakkeet"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Pikakuvakkeet"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Värikontrasti"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Oletus"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Keskitaso"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Korkea"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"–"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Näytä ilmoitukset lukitusnäytöllä"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 70df74e..1d2e3e5 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"OK"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Raccourcis"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Raccourcis"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contraste"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Par défaut"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Moyen"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Élevé"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Aucun"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Afficher les notifications sur l\'écran de verrouillage"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 5c5b720..66eaa2e 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"OK"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Raccourcis"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Raccourcis"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contraste des couleurs"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Par défaut"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Moyen"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Élevé"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Aucun"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Afficher les notifications sur l\'écran de verrouillage"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 6b262ff..beeface 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Feito"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Atallos"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Atallos"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contraste de cor"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Predeterminado"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Medio"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Alta"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ningún"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Mostrar notificacións na pantalla de bloqueo"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index e60acbf..e396e91 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"થઈ ગયું"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"શૉર્ટકટ"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"શૉર્ટકટ"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"કલર કૉન્ટ્રાસ્ટ"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ડિફૉલ્ટ"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"મધ્યમ"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"ઉચ્ચ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"એકપણ નહીં"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"લૉક સ્ક્રીન પર નોટિફિકેશન બતાવો"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index f222f45..059eabb 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"हो गया"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"शॉर्टकट"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"शॉर्टकट"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"कलर कंट्रास्ट"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"डिफ़ॉल्ट"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"मीडियम"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"हाई"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"कोई नहीं"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"लॉक स्क्रीन पर सूचनाएं दिखाएं"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 932a7fb..69591f7 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Gotovo"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Prečaci"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Prečaci"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Kontrast boja"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Zadana"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Srednja"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Visoka"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ništa"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Prikaži obavijesti na zaključanom zaslonu"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 81951de..ed4e10c 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Kész"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Gyorsparancsok"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Gyorsparancsok"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Színkontraszt"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Alapértelmezett"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Közepes"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Magas"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Nincs"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Értesítések megjelenítése a lezárási képernyőn"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index de2f488..0d75ee7 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Պատրաստ է"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Դյուրանցումներ"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Դյուրանցումներ"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Գույնի կոնտրաստ"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Կանխադրված"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Միջին"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Բարձր"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ընտրված չէ"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Ցուցադրել ծանուցումները կողպէկրանին"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 7e097b3..04ab409 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Selesai"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Pintasan"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Pintasan"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Kontras warna"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Default"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Sedang"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Tinggi"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Tidak ada"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Tampilkan notifikasi di layar kunci"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index d5c3436..abad9ec 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Lokið"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Flýtileiðir"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Flýtileiðir"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Litaskil"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Sjálfgefið"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Miðlungs"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Mikil"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ekkert"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Sýna tilkynningar á lásskjánum"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 3bc8cb7..6dffc0b 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Fine"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Scorciatoie"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Scorciatoie"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contrasto colore"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Predefinito"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Medio"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Alto"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Nessuna"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Mostra le notifiche sulla schermata di blocco"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 58da8e0..8c5ad6e 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"סיום"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"קיצורי דרך"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"קיצורי דרך"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"ניגודיות של צבעים"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ברירת המחדל"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"בינונית"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"גבוהה"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"אין"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"הצגת ההתראות במסך הנעילה"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 31500ca..4b079b8 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"完了"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"ショートカット"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"ショートカット"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"色のコントラスト"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"デフォルト"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"中"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"高"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>、<xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"なし"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"ロック画面に通知を表示する"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 01997d1..c52a944 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"მზადაა"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"მალსახმობები"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"მალსახმობები"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"ფერთა კონტრასტი"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ნაგულისხმევი"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"საშუალო"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"მაღალი"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"არცერთი"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"შეტყობინებების ჩვენება ჩაკეტილ ეკრანზე"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index fdb21bd..9389d03 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Дайын"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Жылдам пәрмендер"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Жылдам пәрмендер"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Түс контрасы"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Әдепкі"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Орташа"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Жоғары"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ешқандай"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Құлып экранында хабарландыруларды көрсету"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 07375af..19762ef 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"រួចរាល់"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"ផ្លូវកាត់"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"ផ្លូវកាត់"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"កម្រិតរំលេចពណ៌"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"លំនាំដើម"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"មធ្យម"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"ខ្ពស់"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"គ្មាន"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"បង្ហាញការជូនដំណឹងនៅលើអេក្រង់ចាក់សោ"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index fd940a6..70e229f 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"ಮುಗಿದಿದೆ"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"ಶಾರ್ಟ್ಕಟ್ಗಳು"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"ಶಾರ್ಟ್ಕಟ್ಗಳು"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"ಕಲರ್ ಕಾಂಟ್ರಾಸ್ಟ್"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ಡೀಫಾಲ್ಟ್"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"ಮಧ್ಯಮ"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"ಹೆಚ್ಚು"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"ಯಾವುದೂ ಅಲ್ಲ"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸಿ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 6a7643c..3582ae6 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"완료"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"단축키"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"단축키"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"색상 대비"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"기본값"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"중간"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"높음"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"없음"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"잠금 화면에 알림 표시"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 5ff5575..cf57425 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Бүттү"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Ыкчам баскычтар"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Ыкчам баскычтар"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Түс контрасты"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Демейки"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Орточо"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Жогору"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Жок"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Билдирмелерди кулпуланган экранда көрсөтүү"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 00afb8e..b33cebc 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"ແລ້ວໆ"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"ທາງລັດ"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"ທາງລັດ"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"ຄ່າການຕັດກັນຂອງສີ"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ຄ່າເລີ່ມຕົ້ນ"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"ປານກາງ"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"ສູງ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"ບໍ່ມີ"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"ສະແດງການແຈ້ງເຕືອນຢູ່ໜ້າຈໍລັອກ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 41ce8fd..d2a21d7 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Atlikta"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Šaukiniai"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Šaukiniai"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Spalvų kontr."</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Numatytasis"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Vidutinis"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Didelis"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Nėra"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Rodyti pranešimus užrakinimo ekrane"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 53cbbf6..bc8f155 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Gatavs"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Saīsnes"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Saīsnes"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Krāsu kontrasts"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Noklusējums"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Vidējs"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Augsts"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Nav"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Rādīt paziņojumus bloķēšanas ekrānā"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index e3a97db..b3b8ab2 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Готово"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Кратенки"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Кратенки"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Контраст на бои"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Стандарден"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Среден"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Висок"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Нема"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Прикажувај известувања на заклучен екран"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 8a37dd9..685f8f6 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"പൂർത്തിയായി"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"കുറുക്കുവഴികൾ"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"കുറുക്കുവഴികൾ"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"കളർ കോൺട്രാസ്റ്റ്"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ഡിഫോൾട്ട്"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"ഇടത്തരം"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"കൂടുതൽ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"ഒന്നുമില്ല"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"ലോക്ക് സ്ക്രീനിൽ അറിയിപ്പുകൾ കാണിക്കുക"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 4591634..003a69d 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Болсон"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Товчлол"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Товчлол"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Өнгөний ялгарал"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Өгөгдмөл"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Дунд зэрэг"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Өндөр"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Байхгүй"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Түгжээтэй дэлгэц дээр мэдэгдэл харуулах"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 02838e4..8419783 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"पूर्ण झाले"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"शॉर्टकट"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"शॉर्टकट"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"रंग कॉंट्रास्ट"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"डीफॉल्ट"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"मध्यम"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"उच्च"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"काहीही नाही"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"लॉक स्क्रीनवर सूचना दाखवा"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index ef18499..2757dc8 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Selesai"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Pintasan"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Pintasan"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Kontras warna"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Lalai"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Sederhana"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Tinggi"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Tiada"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Tunjukkan pemberitahuan pada skrin kunci"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index cbe4079..bc71e17 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"ပြီးပြီ"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"ဖြတ်လမ်းလင့်ခ်"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"ဖြတ်လမ်းလင့်ခ်"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"အရောင်ခြားနားမှု"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"မူရင်း"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"အသင့်အတင့်"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"များ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>၊ <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"မရှိ"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"အကြောင်းကြားချက်များကို လော့ခ်မျက်နှာပြင်တွင် ပြပါ"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 4062ab5..20023dd 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Ferdig"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Snarveier"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Snarveier"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Fargekontrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Standard"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Middels"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Høy"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ingen"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Vis varsler på låseskjermen"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 8c611cb..9a941cc 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"पूरा भयो"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"सर्टकटहरू"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"सर्टकटहरू"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"कलर कन्ट्रास्ट"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"डिफल्ट"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"मध्यम"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"उच्च"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"कुनै पनि होइन"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"लक स्क्रिनमा सूचनाहरू देखाउनुहोस्"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 93a3461..8c22a35 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Klaar"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Snelkoppelingen"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Snelkoppelingen"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Kleurcontrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Standaard"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Gemiddeld"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Hoog"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Geen"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Meldingen tonen op het vergrendelscherm"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index b64c09e..c9f5ea6 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"ହୋଇଗଲା"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"ସର୍ଟକଟଗୁଡ଼ିକ"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"ସର୍ଟକଟଗୁଡ଼ିକ"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"ରଙ୍ଗ କଣ୍ଟ୍ରାଷ୍ଟ"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ଡିଫଲ୍ଟ"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"ମଧ୍ୟମ"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"ସର୍ବାଧିକ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"କିଛି ନାହିଁ"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"ଲକ ସ୍କ୍ରିନରେ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 4ec5c27..926dce1 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"ਹੋ ਗਿਆ"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"ਸ਼ਾਰਟਕੱਟ"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"ਸ਼ਾਰਟਕੱਟ"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"ਰੰਗ ਦਾ ਕੰਟ੍ਰਾਸਟ"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"ਦਰਮਿਆਨਾ"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"ਵੱਧ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"ਕੋਈ ਨਹੀਂ"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਸੂਚਨਾਵਾਂ ਦਿਖਾਓ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 9565886..d91f026 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Gotowe"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Skróty"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Skróty"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Kontrast kolorów"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Domyślny"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Średni"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Wysoki"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Brak"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Pokazuj powiadomienia na ekranie blokady"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 58b1421..c912c07 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Concluído"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Atalhos"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Atalhos"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contraste de cor"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Predefinição"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Médio"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Alto"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Nenhum"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Mostrar as notificações no ecrã de bloqueio"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index af2b0a3..ed833d5 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Concluído"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Atalhos"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Atalhos"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contraste de cor"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Padrão"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Médio"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Alto"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Nenhum"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Mostrar notificações na tela de bloqueio"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 44d056f..44bd489 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Gata"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Comenzi rapide"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Comenzi rapide"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contrast culori"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Prestabilit"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Mediu"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Ridicat"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Niciunul"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Afișează notificările pe ecranul de blocare"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 3a13423..bc17db7 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"ОК"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Быстрые действия"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Быстрые действия"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Контраст цветов"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"По умолчанию"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Средний"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Высокий"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Нет"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Показывать уведомления на заблокированном экране"</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 6c1033a..35cec6a 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"නිමයි"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"කෙටිමං"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"කෙටිමං"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"වර්ණ අසමානතාව"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"පෙරනිමි"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"මධ්යම"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"ඉහළ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"කිසිවක් නැත"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"අගුළු තිරය මත දැනුම්දීම් පෙන්වන්න"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 271a201..5f26d2f 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Hotovo"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Skratky"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Skratky"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Farebný kontrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Predvolený"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Stredný"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Vysoký"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Žiadne"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Zobrazovať upozornenia na uzamknutej obrazovke"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 61eada7..c8fb3ce 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Končano"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Bližnjice"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Bližnjice"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Barvni kontrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Privzeto"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Srednje"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Visoko"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Brez"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Prikaži obvestila na zaklenjenem zaslonu"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 23c96e3..19677fa 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"U krye"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Shkurtoret"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Shkurtoret"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Kontrasti i ngjyrës"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Parazgjedhja"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Mesatar"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"I lartë"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Asnjë"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Shfaq njoftimet në ekranin e kyçjes"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 8be5c15..4040536 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Готово"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Пречице"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Пречице"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Контраст боја"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Подразумевано"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Средње"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Високо"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Ништа"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Приказуј обавештења на закључаном екрану"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 8cfa9c8..8749e96 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Klar"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Genvägar"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Genvägar"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Färgkontrast"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Standard"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Mellan"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Hög"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Inga"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Visa aviseringar på låsskärmen"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 9c1fb1f..55f75fc 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Nimemaliza"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Njia za mkato"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Njia za mkato"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Utofautishaji wa rangi"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Chaguomsingi"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Wastani"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Juu"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Hamna"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Onyesha arifa kwenye skrini iliyofungwa"</string>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index eaf444f..75609c7 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"சரி"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"ஷார்ட்கட்கள்"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"ஷார்ட்கட்கள்"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"நிற வேறுபாடு"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"இயல்பு"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"நடுத்தரம்"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"அதிகம்"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"ஏதுமில்லை"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"பூட்டுத் திரையில் அறிவிப்புகளைக் காட்டு"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 3d55144..c318952 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"పూర్తయింది"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"షార్ట్కట్లు"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"షార్ట్కట్లు"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"రంగు కాంట్రాస్ట్"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"డిఫాల్ట్"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"మధ్యస్థం"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"ఎక్కువ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"ఏదీ ఎంచుకోలేదు"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"లాక్ స్క్రీన్లో నోటిఫికేషన్లను చూపండి"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index d9eea94..b92fb2d 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"เสร็จสิ้น"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"ทางลัด"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"ทางลัด"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"คอนทราสต์ของสี"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ค่าเริ่มต้น"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"ปานกลาง"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"สูง"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"ไม่มี"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"แสดงการแจ้งเตือนบนหน้าจอล็อก"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index d945c1c..3daa94a 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Tapos na"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Mga Shortcut"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Mga Shortcut"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Contrast ng kulay"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Default"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Katamtaman"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Mataas"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Wala"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Ipakita ang mga notification sa lock screen"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 209cd68..3cfce23 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Bitti"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Kısayollar"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Kısayollar"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Renk kontrastı"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Varsayılan"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Ortam"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Yüksek"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Yok"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Kilit ekranında bildirimleri göster"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index a107312..f44ff5b 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Готово"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Ярлики"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Ярлики"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Контраст кольору"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"За умовчанням"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Середній"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Високий"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Немає"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Показувати сповіщення на заблокованому екрані"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index a241ed0..18eb802 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"ہو گیا"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"شارٹ کٹس"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"شارٹ کٹس"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"رنگ کا کنٹراسٹ"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"ڈیفالٹ"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"متوسط"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"زیادہ"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>، <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"کوئی نہیں"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"مقفل اسکرین پر اطلاعات دکھائیں"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 5bf7e44..1295959 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Tayyor"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Tezkor tugmalar"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Tezkor tugmalar"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Rang kontrasti"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Birlamchi"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Oʻrtacha"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Yuqori"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Hech qanday"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Ekran qulfida bildirishnomalarni chiqarish"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 1e63212..9c4bba6 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Xong"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Lối tắt"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Lối tắt"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Độ tương phản màu"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Mặc định"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Vừa"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Cao"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Không có"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Hiện thông báo trên màn hình khoá"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 3b6d501..3bf17dd 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"完成"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"快捷方式"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"快捷方式"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"色彩对比度"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"默认"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"中"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"高"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>、<xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"无"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"在锁定的屏幕上显示通知"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index bfe881e..59cbd74 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"完成"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"捷徑"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"捷徑"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"色彩對比度"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"預設"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"中"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"高"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>,<xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"無"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"在上鎖畫面顯示通知"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 743f1ec..3143f29 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"完成"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"捷徑"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"捷徑"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"色彩對比"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"預設"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"中"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"高"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>、<xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"無"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"在螢幕鎖定畫面上顯示通知"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 0896e57..d1569db 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -128,6 +128,10 @@
<string name="keyguard_affordance_enablement_dialog_dismiss_button" msgid="629754625264422508">"Kwenziwe"</string>
<string name="keyguard_quick_affordance_title" msgid="4242813186995735584">"Izinqamuleli"</string>
<string name="keyguard_quick_affordance_section_title" msgid="2806304242671717309">"Izinqamuleli"</string>
+ <string name="color_contrast_section_title" msgid="7194809124718896091">"Ukungafani kombala"</string>
+ <string name="color_contrast_default_title" msgid="7954235103549276978">"Okuzenzakalelayo"</string>
+ <string name="color_contrast_medium_title" msgid="8071574793250090215">"Okuphakathi"</string>
+ <string name="color_contrast_high_title" msgid="5554685752479470200">"Okuphezulu"</string>
<string name="keyguard_quick_affordance_two_selected_template" msgid="1757099194522296363">"<xliff:g id="FIRST">%1$s</xliff:g>, <xliff:g id="SECOND">%2$s</xliff:g>"</string>
<string name="keyguard_quick_affordance_none_selected" msgid="8494127020144112003">"Lutho"</string>
<string name="show_notifications_on_lock_screen" msgid="4157744243084646720">"Bonisa izaziso esikrinini sokukhiya"</string>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 2f9daae..a643c0a 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -175,4 +175,8 @@
<!-- Notification item dimensions -->
<dimen name="notification_section_title_padding">8dp</dimen>
+ <!-- Floating sheet dimensions -->
+ <dimen name="floating_sheet_list_vertical_padding">20dp</dimen>
+ <dimen name="floating_sheet_horizontal_padding">16dp</dimen>
+ <dimen name="floating_sheet_tab_toolbar_vertical_margin">8dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d1f6035..271a74c 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -413,6 +413,32 @@
<string name="keyguard_quick_affordance_section_title">Shortcuts</string>
<!--
+ Label for a menu item on a settings screen that helps the user open a new screen where they can
+ configure the lock screen shortcut buttons that appear on the device without unlocking.
+ [CHAR LIMIT=16].
+ -->
+ <string name="color_contrast_section_title">Color contrast</string>
+
+ <!--
+ Label for color contrast settings button with default contrast setting.
+ [CHAR LIMIT=16].
+ -->
+ <string name="color_contrast_default_title">Default</string>
+
+ <!--
+ Label for color contrast settings button with medium contrast setting.
+ [CHAR LIMIT=16].
+ -->
+
+ <string name="color_contrast_medium_title">Medium</string>
+
+ <!--
+ Label for color contrast settings button with maximum contrast setting.
+ [CHAR LIMIT=16].
+ -->
+ <string name="color_contrast_high_title">High</string>
+
+ <!--
Template for text that shows the names of two currently-selected lock screen shortcuts on the
lock screen. For example, it may say "Camera, Wallet", if the first selected shortcut opens the
camera app and the second one opens the tap-to-pay wallet experience.
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c2710f6..fc2fd8a 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -130,6 +130,18 @@
<item name="android:lineHeight">16sp</item>
</style>
+ <style name="CustomizationOptionEntryTitleTextStyle">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ <item name="android:textColor">@color/system_on_surface</item>
+ <item name="android:textSize">20sp</item>
+ </style>
+
+ <style name="CustomizationOptionEntrySubtitleTextStyle">
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ <item name="android:textColor">@color/system_on_surface_variant</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+
<style name="BetaTagTextStyle" parent="SectionTitleTextStyle">
<item name="android:textSize">12sp</item>
<item name="android:lineHeight">15dp</item>
diff --git a/src/com/android/customization/model/color/ColorCustomizationManager.java b/src/com/android/customization/model/color/ColorCustomizationManager.java
index 5bd302b..9acbc4f 100644
--- a/src/com/android/customization/model/color/ColorCustomizationManager.java
+++ b/src/com/android/customization/model/color/ColorCustomizationManager.java
@@ -66,7 +66,6 @@
public class ColorCustomizationManager implements CustomizationManager<ColorOption> {
private static final String TAG = "ColorCustomizationManager";
- private static final ExecutorService sExecutorService = Executors.newSingleThreadExecutor();
private static final Set<String> COLOR_OVERLAY_SETTINGS = new HashSet<>();
static {
@@ -80,8 +79,8 @@
private final ColorOptionsProvider mProvider;
private final OverlayManagerCompat mOverlayManagerCompat;
+ private final ExecutorService mExecutorService;
private final ContentResolver mContentResolver;
- private final ContentObserver mObserver;
private Map<String, String> mCurrentOverlays;
@ColorSource private String mCurrentSource;
@@ -92,22 +91,31 @@
/** Returns the {@link ColorCustomizationManager} instance. */
public static ColorCustomizationManager getInstance(Context context,
OverlayManagerCompat overlayManagerCompat) {
+ return getInstance(context, overlayManagerCompat, Executors.newSingleThreadExecutor());
+ }
+
+ /** Returns the {@link ColorCustomizationManager} instance. */
+ @VisibleForTesting
+ static ColorCustomizationManager getInstance(Context context,
+ OverlayManagerCompat overlayManagerCompat, ExecutorService executorService) {
if (sColorCustomizationManager == null) {
Context appContext = context.getApplicationContext();
sColorCustomizationManager = new ColorCustomizationManager(
new ColorProvider(appContext,
appContext.getString(R.string.themes_stub_package)),
- appContext.getContentResolver(), overlayManagerCompat);
+ appContext.getContentResolver(), overlayManagerCompat,
+ executorService);
}
return sColorCustomizationManager;
}
@VisibleForTesting
ColorCustomizationManager(ColorOptionsProvider provider, ContentResolver contentResolver,
- OverlayManagerCompat overlayManagerCompat) {
+ OverlayManagerCompat overlayManagerCompat, ExecutorService executorService) {
mProvider = provider;
mContentResolver = contentResolver;
- mObserver = new ContentObserver(/* handler= */ null) {
+ mExecutorService = executorService;
+ ContentObserver observer = new ContentObserver(/* handler= */ null) {
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
@@ -122,7 +130,7 @@
}
};
mContentResolver.registerContentObserver(
- Settings.Secure.CONTENT_URI, /* notifyForDescendants= */ true, mObserver);
+ Settings.Secure.CONTENT_URI, /* notifyForDescendants= */ true, observer);
mOverlayManagerCompat = overlayManagerCompat;
}
@@ -137,7 +145,7 @@
}
private void applyOverlays(ColorOption colorOption, Callback callback) {
- sExecutorService.submit(() -> {
+ mExecutorService.submit(() -> {
String currentStoredOverlays = getStoredOverlays();
if (TextUtils.isEmpty(currentStoredOverlays)) {
currentStoredOverlays = "{}";
diff --git a/src/com/android/customization/model/color/ColorProvider.kt b/src/com/android/customization/model/color/ColorProvider.kt
index eb8d8df..2d7037e 100644
--- a/src/com/android/customization/model/color/ColorProvider.kt
+++ b/src/com/android/customization/model/color/ColorProvider.kt
@@ -42,6 +42,7 @@
import com.android.wallpaper.module.InjectorProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -62,6 +63,7 @@
private const val ALPHA_MASK = 0xFF
}
+ private var loaderJob: Job? = null
private val monetEnabled = ColorUtils.isMonetEnabled(context)
// TODO(b/202145216): Use style method to fetch the list of style.
private var styleList =
@@ -105,19 +107,21 @@
this.homeWallpaperColors = homeWallpaperColors
this.lockWallpaperColors = lockWallpaperColors
}
- if (presetColorBundles == null || reload) {
- scope.launch {
+
+ scope.launch {
+ loaderJob?.join()
+ if (presetColorBundles == null || reload) {
try {
- loadPreset()
+ loaderJob = launch { loadPreset() }
} catch (e: Throwable) {
colorsAvailable = false
callback?.onError(e)
return@launch
}
callback?.onOptionsLoaded(buildFinalList())
+ } else {
+ callback?.onOptionsLoaded(buildFinalList())
}
- } else {
- callback?.onOptionsLoaded(buildFinalList())
}
}
@@ -367,6 +371,7 @@
}
presetColorBundles = bundles
+ loaderJob = null
}
private fun buildPreset(
diff --git a/src/com/android/customization/model/color/ThemedWallpaperColorResources.kt b/src/com/android/customization/model/color/ThemedWallpaperColorResources.kt
index 7c89953..c426f9d 100644
--- a/src/com/android/customization/model/color/ThemedWallpaperColorResources.kt
+++ b/src/com/android/customization/model/color/ThemedWallpaperColorResources.kt
@@ -39,11 +39,11 @@
withContext(Dispatchers.IO) {
val wallpaperColorScheme =
ColorScheme(
- wallpaperColors = wallpaperColors,
- darkTheme = false,
- style = fetchThemeStyleFromSetting(),
+ wallpaperColors,
+ false,
+ fetchThemeStyleFromSetting(),
)
- with(wallpaperColorScheme) {
+ with<ColorScheme, Unit>(wallpaperColorScheme) {
addOverlayColor(neutral1, R.color.system_neutral1_10)
addOverlayColor(neutral2, R.color.system_neutral2_10)
addOverlayColor(accent1, R.color.system_accent1_10)
diff --git a/src/com/android/customization/model/grid/GridOptionsManager.java b/src/com/android/customization/model/grid/GridOptionsManager.java
index 09c6c65..413592b 100644
--- a/src/com/android/customization/model/grid/GridOptionsManager.java
+++ b/src/com/android/customization/model/grid/GridOptionsManager.java
@@ -16,7 +16,6 @@
package com.android.customization.model.grid;
import android.content.Context;
-import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
@@ -30,7 +29,6 @@
import com.android.customization.module.logging.ThemesUserEventLogger;
import com.android.wallpaper.R;
import com.android.wallpaper.module.InjectorProvider;
-import com.android.wallpaper.util.PreviewUtils;
import java.util.List;
import java.util.concurrent.ExecutionException;
@@ -125,10 +123,4 @@
public LiveData<Object> getOptionChangeObservable(@Nullable Handler handler) {
return mProvider.getOptionChangeObservable(handler);
}
-
- /** Call through content provider API to render preview */
- public void renderPreview(Bundle bundle, String gridName,
- PreviewUtils.WorkspacePreviewCallback callback) {
- mProvider.renderPreview(gridName, bundle, callback);
- }
}
diff --git a/src/com/android/customization/model/grid/LauncherGridOptionsProvider.java b/src/com/android/customization/model/grid/LauncherGridOptionsProvider.java
index 33ad81d..8350248 100644
--- a/src/com/android/customization/model/grid/LauncherGridOptionsProvider.java
+++ b/src/com/android/customization/model/grid/LauncherGridOptionsProvider.java
@@ -22,9 +22,7 @@
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
-import android.os.Bundle;
import android.os.Handler;
-import android.view.SurfaceView;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@@ -107,19 +105,6 @@
return mOptions;
}
- /**
- * Request rendering of home screen preview via Launcher to Wallpaper using SurfaceView
- * @param name the grid option name
- * @param bundle surface view request bundle generated from
- * {@link com.android.wallpaper.util.SurfaceViewUtils#createSurfaceViewRequest(SurfaceView)}.
- * @param callback To receive the result (will be called on the main thread)
- */
- void renderPreview(String name, Bundle bundle,
- PreviewUtils.WorkspacePreviewCallback callback) {
- bundle.putString("name", name);
- mPreviewUtils.renderPreview(bundle, callback);
- }
-
void updateView() {
mLiveData.postValue(new Object());
}
diff --git a/src/com/android/customization/model/mode/DarkModeSectionController.java b/src/com/android/customization/model/mode/DarkModeSectionController.java
index 3da7ae9..3fd9bc4 100644
--- a/src/com/android/customization/model/mode/DarkModeSectionController.java
+++ b/src/com/android/customization/model/mode/DarkModeSectionController.java
@@ -20,7 +20,6 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.PowerManager.ACTION_POWER_SAVE_MODE_CHANGED;
-import android.app.UiModeManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -43,6 +42,7 @@
import com.android.customization.picker.mode.DarkModeSectionView;
import com.android.themepicker.R;
import com.android.wallpaper.model.CustomizationSectionController;
+import com.android.wallpaper.system.UiModeManagerWrapper;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -61,18 +61,21 @@
private Context mContext;
private DarkModeSectionView mDarkModeSectionView;
private final DarkModeSnapshotRestorer mSnapshotRestorer;
+ private final UiModeManagerWrapper mUiModeManager;
private final ThemesUserEventLogger mThemesUserEventLogger;
public DarkModeSectionController(
Context context,
Lifecycle lifecycle,
DarkModeSnapshotRestorer snapshotRestorer,
+ UiModeManagerWrapper uiModeManager,
ThemesUserEventLogger themesUserEventLogger) {
mContext = context;
mLifecycle = lifecycle;
mPowerManager = context.getSystemService(PowerManager.class);
mLifecycle.addObserver(this);
mSnapshotRestorer = snapshotRestorer;
+ mUiModeManager = uiModeManager;
mThemesUserEventLogger = themesUserEventLogger;
}
@@ -134,13 +137,12 @@
disableToast.show();
return;
}
- UiModeManager uiModeManager = context.getSystemService(UiModeManager.class);
int shortDelay = context.getResources().getInteger(android.R.integer.config_shortAnimTime);
new Handler(Looper.getMainLooper()).postDelayed(
() -> {
mDarkModeSectionView.announceForAccessibility(
context.getString(R.string.mode_changed));
- uiModeManager.setNightModeActivated(viewActivated);
+ mUiModeManager.setNightModeActivated(viewActivated);
mThemesUserEventLogger.logDarkThemeApplied(viewActivated);
mSnapshotRestorer.store(viewActivated);
},
diff --git a/src/com/android/customization/model/mode/DarkModeSnapshotRestorer.kt b/src/com/android/customization/model/mode/DarkModeSnapshotRestorer.kt
index 93bd0bf..69147bf 100644
--- a/src/com/android/customization/model/mode/DarkModeSnapshotRestorer.kt
+++ b/src/com/android/customization/model/mode/DarkModeSnapshotRestorer.kt
@@ -17,13 +17,13 @@
package com.android.customization.model.mode
-import android.app.UiModeManager
import android.content.Context
import android.content.res.Configuration
import androidx.annotation.VisibleForTesting
import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer
import com.android.wallpaper.picker.undo.domain.interactor.SnapshotStore
import com.android.wallpaper.picker.undo.shared.model.RestorableSnapshot
+import com.android.wallpaper.system.UiModeManagerWrapper
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
@@ -37,7 +37,7 @@
constructor(
context: Context,
- manager: UiModeManager,
+ manager: UiModeManagerWrapper,
backgroundDispatcher: CoroutineDispatcher,
) : this(
backgroundDispatcher = backgroundDispatcher,
diff --git a/src/com/android/customization/module/CustomizationInjector.kt b/src/com/android/customization/module/CustomizationInjector.kt
index d761598..2696b97 100644
--- a/src/com/android/customization/module/CustomizationInjector.kt
+++ b/src/com/android/customization/module/CustomizationInjector.kt
@@ -22,7 +22,6 @@
import com.android.customization.picker.clock.ui.view.ClockViewFactory
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
-import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
import com.android.customization.picker.color.ui.viewmodel.ColorPickerViewModel
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
import com.android.systemui.shared.clocks.ClockRegistry
@@ -40,15 +39,7 @@
fun getClockPickerInteractor(context: Context): ClockPickerInteractor
- fun getColorPickerInteractor(
- context: Context,
- wallpaperColorsRepository: WallpaperColorsRepository,
- ): ColorPickerInteractor
-
- fun getColorPickerViewModelFactory(
- context: Context,
- wallpaperColorsRepository: WallpaperColorsRepository,
- ): ColorPickerViewModel.Factory
+ fun getColorPickerViewModelFactory(context: Context): ColorPickerViewModel.Factory
fun getClockCarouselViewModelFactory(
interactor: ClockPickerInteractor,
diff --git a/src/com/android/customization/module/DefaultCustomizationPreferences.kt b/src/com/android/customization/module/DefaultCustomizationPreferences.kt
index 49fd1a9..0ef4a1d 100644
--- a/src/com/android/customization/module/DefaultCustomizationPreferences.kt
+++ b/src/com/android/customization/module/DefaultCustomizationPreferences.kt
@@ -17,8 +17,14 @@
import android.content.Context
import com.android.wallpaper.module.DefaultWallpaperPreferences
+import dagger.hilt.android.qualifiers.ApplicationContext
+import javax.inject.Inject
+import javax.inject.Singleton
-open class DefaultCustomizationPreferences(context: Context) :
+@Singleton
+open class DefaultCustomizationPreferences
+@Inject
+constructor(@ApplicationContext context: Context) :
DefaultWallpaperPreferences(context), CustomizationPreferences {
override fun getSerializedCustomThemes(): String? {
diff --git a/src/com/android/customization/module/DefaultCustomizationSections.java b/src/com/android/customization/module/DefaultCustomizationSections.java
index 8347d03..33cb620 100644
--- a/src/com/android/customization/module/DefaultCustomizationSections.java
+++ b/src/com/android/customization/module/DefaultCustomizationSections.java
@@ -26,11 +26,14 @@
import com.android.customization.picker.preview.ui.section.PreviewWithThemeSectionController;
import com.android.customization.picker.quickaffordance.ui.section.KeyguardQuickAffordanceSectionController;
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel;
+import com.android.customization.picker.settings.ui.section.ColorContrastSectionController;
import com.android.customization.picker.settings.ui.section.MoreSettingsSectionController;
+import com.android.customization.picker.settings.ui.viewmodel.ColorContrastSectionViewModel;
import com.android.wallpaper.config.BaseFlags;
import com.android.wallpaper.model.CustomizationSectionController;
import com.android.wallpaper.model.CustomizationSectionController.CustomizationSectionNavigationController;
import com.android.wallpaper.model.PermissionRequester;
+import com.android.wallpaper.model.Screen;
import com.android.wallpaper.model.WallpaperPreviewNavigator;
import com.android.wallpaper.module.CurrentWallpaperInfoFactory;
import com.android.wallpaper.module.CustomizationSections;
@@ -50,6 +53,8 @@
private final ColorPickerViewModel.Factory mColorPickerViewModelFactory;
private final KeyguardQuickAffordancePickerViewModel.Factory
mKeyguardQuickAffordancePickerViewModelFactory;
+ private final ColorContrastSectionViewModel.Factory
+ mColorContrastSectionViewModelFactory;
private final NotificationSectionViewModel.Factory mNotificationSectionViewModelFactory;
private final BaseFlags mFlags;
private final ClockCarouselViewModel.Factory mClockCarouselViewModelFactory;
@@ -63,6 +68,7 @@
ColorPickerViewModel.Factory colorPickerViewModelFactory,
KeyguardQuickAffordancePickerViewModel.Factory
keyguardQuickAffordancePickerViewModelFactory,
+ ColorContrastSectionViewModel.Factory colorContrastSectionViewModelFactory,
NotificationSectionViewModel.Factory notificationSectionViewModelFactory,
BaseFlags flags,
ClockCarouselViewModel.Factory clockCarouselViewModelFactory,
@@ -82,6 +88,7 @@
mThemedIconInteractor = themedIconInteractor;
mColorPickerInteractor = colorPickerInteractor;
mThemesUserEventLogger = themesUserEventLogger;
+ mColorContrastSectionViewModelFactory = colorContrastSectionViewModelFactory;
}
@Override
@@ -191,6 +198,13 @@
mThemedIconSnapshotRestorer,
mThemesUserEventLogger));
+ // Color contrast section
+ if (mFlags.isColorContrastControlEnabled()) {
+ sectionControllers.add(
+ new ColorContrastSectionController(new ViewModelProvider(activity,
+ mColorContrastSectionViewModelFactory)
+ .get(ColorContrastSectionViewModel.class), lifecycleOwner));
+ }
// App grid section.
sectionControllers.add(
new GridSectionController(
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index a2f7e56..e62235c 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -16,14 +16,12 @@
package com.android.customization.module
import android.app.Activity
-import android.app.UiModeManager
import android.app.WallpaperColors
import android.app.WallpaperManager
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.net.Uri
-import android.text.TextUtils
import androidx.activity.ComponentActivity
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
@@ -48,7 +46,6 @@
import com.android.customization.picker.clock.ui.view.ClockViewFactoryImpl
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
-import com.android.customization.picker.color.data.repository.ColorPickerRepositoryImpl
import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
import com.android.customization.picker.color.domain.interactor.ColorPickerSnapshotRestorer
import com.android.customization.picker.color.ui.viewmodel.ColorPickerViewModel
@@ -58,13 +55,11 @@
import com.android.customization.picker.grid.ui.viewmodel.GridScreenViewModel
import com.android.customization.picker.notifications.domain.interactor.NotificationsSnapshotRestorer
import com.android.customization.picker.notifications.ui.viewmodel.NotificationSectionViewModel
-import com.android.customization.picker.quickaffordance.data.repository.KeyguardQuickAffordancePickerRepository
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordanceSnapshotRestorer
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel
+import com.android.customization.picker.settings.ui.viewmodel.ColorContrastSectionViewModel
import com.android.systemui.shared.clocks.ClockRegistry
-import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
-import com.android.systemui.shared.customization.data.content.CustomizationProviderClientImpl
import com.android.systemui.shared.notifications.data.repository.NotificationSettingsRepository
import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor
import com.android.wallpaper.config.BaseFlags
@@ -97,15 +92,10 @@
) : WallpaperPicker2Injector(mainScope, bgDispatcher), CustomizationInjector {
private var customizationSections: CustomizationSections? = null
private var wallpaperInteractor: WallpaperInteractor? = null
- private var keyguardQuickAffordancePickerInteractor: KeyguardQuickAffordancePickerInteractor? =
- null
private var keyguardQuickAffordancePickerViewModelFactory:
KeyguardQuickAffordancePickerViewModel.Factory? =
null
- private var customizationProviderClient: CustomizationProviderClient? = null
private var fragmentFactory: FragmentFactory? = null
- private var keyguardQuickAffordanceSnapshotRestorer: KeyguardQuickAffordanceSnapshotRestorer? =
- null
private var notificationsSnapshotRestorer: NotificationsSnapshotRestorer? = null
private var clockPickerInteractor: ClockPickerInteractor? = null
private var clockCarouselViewModelFactory: ClockCarouselViewModel.Factory? = null
@@ -113,9 +103,7 @@
private var clockPickerSnapshotRestorer: ClockPickerSnapshotRestorer? = null
private var notificationSettingsInteractor: NotificationSettingsInteractor? = null
private var notificationSectionViewModelFactory: NotificationSectionViewModel.Factory? = null
- private var colorPickerInteractor: ColorPickerInteractor? = null
private var colorPickerViewModelFactory: ColorPickerViewModel.Factory? = null
- private var colorPickerSnapshotRestorer: ColorPickerSnapshotRestorer? = null
private var colorCustomizationManager: ColorCustomizationManager? = null
private var darkModeSnapshotRestorer: DarkModeSnapshotRestorer? = null
private var themedIconSnapshotRestorer: ThemedIconSnapshotRestorer? = null
@@ -125,7 +113,19 @@
private var gridSnapshotRestorer: GridSnapshotRestorer? = null
private var gridScreenViewModelFactory: GridScreenViewModel.Factory? = null
private var clockRegistryProvider: ClockRegistryProvider? = null
+
+ // Injected objects, sorted by type
+ @Inject
+ lateinit var colorContrastSectionViewModelFactory: Lazy<ColorContrastSectionViewModel.Factory>
+ @Inject
+ lateinit var keyguardQuickAffordancePickerInteractor:
+ Lazy<KeyguardQuickAffordancePickerInteractor>
+ @Inject
+ lateinit var keyguardQuickAffordanceSnapshotRestorer:
+ Lazy<KeyguardQuickAffordanceSnapshotRestorer>
@Inject lateinit var themesUserEventLogger: Lazy<ThemesUserEventLogger>
+ @Inject lateinit var colorPickerInteractor: Lazy<ColorPickerInteractor>
+ @Inject lateinit var colorPickerSnapshotRestorer: Lazy<ColorPickerSnapshotRestorer>
override fun getCustomizationSections(activity: ComponentActivity): CustomizationSections {
val appContext = activity.applicationContext
@@ -133,11 +133,9 @@
val resources = activity.resources
return customizationSections
?: DefaultCustomizationSections(
- getColorPickerViewModelFactory(
- context = appContext,
- wallpaperColorsRepository = getWallpaperColorsRepository(),
- ),
+ getColorPickerViewModelFactory(appContext),
getKeyguardQuickAffordancePickerViewModelFactory(appContext),
+ colorContrastSectionViewModelFactory.get(),
getNotificationSectionViewModelFactory(appContext),
getFlags(),
getClockCarouselViewModelFactory(
@@ -148,7 +146,7 @@
clockViewFactory,
getThemedIconSnapshotRestorer(appContext),
getThemedIconInteractor(),
- getColorPickerInteractor(appContext, getWallpaperColorsRepository()),
+ colorPickerInteractor.get(),
getUserEventLogger(),
)
.also { customizationSections = it }
@@ -180,7 +178,7 @@
): Map<Int, SnapshotRestorer> {
return super<WallpaperPicker2Injector>.getSnapshotRestorers(context).toMutableMap().apply {
this[KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER] =
- getKeyguardQuickAffordanceSnapshotRestorer(context)
+ keyguardQuickAffordanceSnapshotRestorer.get()
// TODO(b/285047815): Enable after adding wallpaper id for default static wallpaper
if (getFlags().isWallpaperRestorerEnabled()) {
this[KEY_WALLPAPER_SNAPSHOT_RESTORER] = getWallpaperSnapshotRestorer(context)
@@ -189,8 +187,7 @@
this[KEY_DARK_MODE_SNAPSHOT_RESTORER] = getDarkModeSnapshotRestorer(context)
this[KEY_THEMED_ICON_SNAPSHOT_RESTORER] = getThemedIconSnapshotRestorer(context)
this[KEY_APP_GRID_SNAPSHOT_RESTORER] = getGridSnapshotRestorer(context)
- this[KEY_COLOR_PICKER_SNAPSHOT_RESTORER] =
- getColorPickerSnapshotRestorer(context, getWallpaperColorsRepository())
+ this[KEY_COLOR_PICKER_SNAPSHOT_RESTORER] = colorPickerSnapshotRestorer.get()
this[KEY_CLOCKS_SNAPSHOT_RESTORER] = getClockPickerSnapshotRestorer(context)
}
}
@@ -200,7 +197,7 @@
}
override fun getWallpaperInteractor(context: Context): WallpaperInteractor {
- if (getFlags().isMultiCropEnabled() && getFlags().isMultiCropPreviewUiEnabled()) {
+ if (getFlags().isMultiCropEnabled()) {
return injectedWallpaperInteractor.get()
}
@@ -219,12 +216,6 @@
wallpaperPreferences = getPreferences(context = appContext),
backgroundDispatcher = bgDispatcher,
),
- shouldHandleReload = {
- TextUtils.equals(
- getColorCustomizationManager(appContext).currentColorSource,
- COLOR_SOURCE_PRESET,
- )
- }
)
.also { wallpaperInteractor = it }
}
@@ -232,10 +223,7 @@
override fun getKeyguardQuickAffordancePickerInteractor(
context: Context
): KeyguardQuickAffordancePickerInteractor {
- return keyguardQuickAffordancePickerInteractor
- ?: getKeyguardQuickAffordancePickerInteractorImpl(context).also {
- keyguardQuickAffordancePickerInteractor = it
- }
+ return keyguardQuickAffordancePickerInteractor.get()
}
fun getKeyguardQuickAffordancePickerViewModelFactory(
@@ -252,39 +240,6 @@
.also { keyguardQuickAffordancePickerViewModelFactory = it }
}
- private fun getKeyguardQuickAffordancePickerInteractorImpl(
- context: Context
- ): KeyguardQuickAffordancePickerInteractor {
- val client = getKeyguardQuickAffordancePickerProviderClient(context)
- val appContext = context.applicationContext
- return KeyguardQuickAffordancePickerInteractor(
- KeyguardQuickAffordancePickerRepository(client, getApplicationCoroutineScope()),
- client
- ) {
- getKeyguardQuickAffordanceSnapshotRestorer(appContext)
- }
- }
-
- private fun getKeyguardQuickAffordancePickerProviderClient(
- context: Context
- ): CustomizationProviderClient {
- return customizationProviderClient
- ?: CustomizationProviderClientImpl(context.applicationContext, bgDispatcher).also {
- customizationProviderClient = it
- }
- }
-
- private fun getKeyguardQuickAffordanceSnapshotRestorer(
- context: Context
- ): KeyguardQuickAffordanceSnapshotRestorer {
- return keyguardQuickAffordanceSnapshotRestorer
- ?: KeyguardQuickAffordanceSnapshotRestorer(
- getKeyguardQuickAffordancePickerInteractor(context),
- getKeyguardQuickAffordancePickerProviderClient(context)
- )
- .also { keyguardQuickAffordanceSnapshotRestorer = it }
- }
-
fun getNotificationSectionViewModelFactory(
context: Context,
): NotificationSectionViewModel.Factory {
@@ -408,49 +363,16 @@
return ThemedWallpaperColorResources(wallpaperColors, getSecureSettingsRepository(context))
}
- override fun getColorPickerInteractor(
- context: Context,
- wallpaperColorsRepository: WallpaperColorsRepository,
- ): ColorPickerInteractor {
- val appContext = context.applicationContext
- return colorPickerInteractor
- ?: ColorPickerInteractor(
- repository =
- ColorPickerRepositoryImpl(
- wallpaperColorsRepository,
- getColorCustomizationManager(appContext)
- ),
- snapshotRestorer = {
- getColorPickerSnapshotRestorer(appContext, wallpaperColorsRepository)
- }
- )
- .also { colorPickerInteractor = it }
- }
-
- override fun getColorPickerViewModelFactory(
- context: Context,
- wallpaperColorsRepository: WallpaperColorsRepository,
- ): ColorPickerViewModel.Factory {
+ override fun getColorPickerViewModelFactory(context: Context): ColorPickerViewModel.Factory {
return colorPickerViewModelFactory
?: ColorPickerViewModel.Factory(
context.applicationContext,
- getColorPickerInteractor(context, wallpaperColorsRepository),
+ colorPickerInteractor.get(),
getUserEventLogger(),
)
.also { colorPickerViewModelFactory = it }
}
- private fun getColorPickerSnapshotRestorer(
- context: Context,
- wallpaperColorsRepository: WallpaperColorsRepository,
- ): ColorPickerSnapshotRestorer {
- return colorPickerSnapshotRestorer
- ?: ColorPickerSnapshotRestorer(
- getColorPickerInteractor(context, wallpaperColorsRepository)
- )
- .also { colorPickerSnapshotRestorer = it }
- }
-
private fun getColorCustomizationManager(context: Context): ColorCustomizationManager {
return colorCustomizationManager
?: ColorCustomizationManager.getInstance(context, OverlayManagerCompat(context)).also {
@@ -465,7 +387,7 @@
return darkModeSnapshotRestorer
?: DarkModeSnapshotRestorer(
context = appContext,
- manager = appContext.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager,
+ manager = uiModeManager.get(),
backgroundDispatcher = bgDispatcher,
)
.also { darkModeSnapshotRestorer = it }
@@ -503,10 +425,7 @@
?: ClockSettingsViewModel.Factory(
context.applicationContext,
getClockPickerInteractor(context),
- getColorPickerInteractor(
- context,
- wallpaperColorsRepository,
- ),
+ colorPickerInteractor.get(),
getUserEventLogger(),
) { clockId ->
clockId?.let { clockViewFactory.getController(clockId).config.isReactiveToTone }
diff --git a/src/com/android/customization/picker/clock/ui/binder/CarouselAccessibilityDelegate.kt b/src/com/android/customization/picker/clock/ui/binder/CarouselAccessibilityDelegate.kt
index 1026f19..5d6c3ff 100644
--- a/src/com/android/customization/picker/clock/ui/binder/CarouselAccessibilityDelegate.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/CarouselAccessibilityDelegate.kt
@@ -37,6 +37,11 @@
override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) {
super.onInitializeAccessibilityNodeInfo(host, info)
info.isScrollable = true
+
+ // for some reason this action is needed for the subsequent two action to appear in the
+ // accessibility action menu (this action doesn't show)
+ info.addAction(AccessibilityNodeInfo.ACTION_CLICK) // Standard click action
+
info.addAction(
AccessibilityNodeInfo.AccessibilityAction(
ACTION_SCROLL_FORWARD,
diff --git a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
index e2616c7..7fcfd9c 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
@@ -71,7 +71,7 @@
},
isTwoPaneAndSmallWidth = isTwoPaneAndSmallWidth,
)
- screenPreviewClickView.accessibilityDelegate = carouselAccessibilityDelegate
+ carouselView.accessibilityDelegate = carouselAccessibilityDelegate
screenPreviewClickView.setOnSideClickedListener { isStart ->
if (isStart) carouselView.scrollToPrevious()
else carouselView.scrollToNext()
diff --git a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
index b1bd0ef..7de25e7 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
@@ -47,6 +47,7 @@
import com.android.customization.picker.color.ui.binder.ColorOptionIconBinder
import com.android.customization.picker.common.ui.view.ItemSpacing
import com.android.themepicker.R
+import com.android.wallpaper.config.BaseFlags
import com.android.wallpaper.picker.option.ui.binder.OptionItemBinder
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.mapNotNull
@@ -198,6 +199,9 @@
)
.collect { (clockId, size) ->
clockHostView.removeAllViews()
+ if (BaseFlags.get().isClockReactiveVariantsEnabled()) {
+ clockViewFactory.setReactiveTouchInteractionEnabled(clockId, true)
+ }
val clockView =
when (size) {
ClockSize.DYNAMIC -> clockViewFactory.getLargeView(clockId)
diff --git a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
index b8bd2f3..c2e6717 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -30,7 +30,7 @@
import com.android.customization.picker.clock.ui.binder.ClockSettingsBinder
import com.android.systemui.shared.clocks.shared.model.ClockPreviewConstants
import com.android.themepicker.R
-import com.android.wallpaper.module.CustomizationSections
+import com.android.wallpaper.model.Screen
import com.android.wallpaper.module.InjectorProvider
import com.android.wallpaper.picker.AppbarFragment
import com.android.wallpaper.picker.customization.ui.binder.ScreenPreviewBinder
@@ -113,7 +113,7 @@
}
},
wallpaperInteractor = injector.getWallpaperInteractor(requireContext()),
- screen = CustomizationSections.Screen.LOCK_SCREEN,
+ screen = Screen.LOCK_SCREEN,
),
lifecycleOwner = this,
offsetToStart = displayUtils.isSingleDisplayOrUnfoldedHorizontalHinge(activity),
@@ -144,10 +144,6 @@
return requireContext().getString(R.string.clock_color_and_size_title)
}
- override fun getToolbarColorId(): Int {
- return android.R.color.transparent
- }
-
override fun getToolbarTextColor(): Int {
return ContextCompat.getColor(
requireContext(),
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
index d0a30a4..6cbb0f5 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
@@ -33,6 +33,7 @@
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselItemViewModel
import com.android.systemui.plugins.clocks.ClockController
import com.android.themepicker.R
+import com.android.wallpaper.config.BaseFlags
import com.android.wallpaper.picker.FixedWidthDisplayRatioFrameLayout
import java.lang.Float.max
@@ -408,8 +409,11 @@
?: return
val clockId = clocks[index].clockId
- // Add the clock view to the cloc host view
+ // Add the clock view to the clock host view
clockHostView.removeAllViews()
+ if (BaseFlags.get().isClockReactiveVariantsEnabled()) {
+ clockViewFactory.setReactiveTouchInteractionEnabled(clockId, false)
+ }
val clockView =
when (clockSize) {
ClockSize.DYNAMIC -> clockViewFactory.getLargeView(clockId)
@@ -454,22 +458,16 @@
it.pivotX = it.width / 2F
it.pivotY = it.height / 2F
}
+
+ val controller = clockViewFactory.getController(clockId)
if (isMiddleView) {
clockScaleView.scaleX = 1f
clockScaleView.scaleY = 1f
- clockViewFactory
- .getController(clockId)
- .largeClock
- .animations
- .onPickerCarouselSwiping(1F)
+ controller.largeClock.animations.onPickerCarouselSwiping(1F)
} else {
clockScaleView.scaleX = CLOCK_CAROUSEL_VIEW_SCALE
clockScaleView.scaleY = CLOCK_CAROUSEL_VIEW_SCALE
- clockViewFactory
- .getController(clockId)
- .largeClock
- .animations
- .onPickerCarouselSwiping(0F)
+ controller.largeClock.animations.onPickerCarouselSwiping(0F)
}
}
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt b/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
index 2ab162d..8e5992e 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
@@ -36,6 +36,9 @@
*/
fun getSmallView(clockId: String): View
+ /** Enables or disables the reactive swipe interaction */
+ fun setReactiveTouchInteractionEnabled(clockId: String, enable: Boolean)
+
fun updateColorForAllClocks(@ColorInt seedColor: Int?)
fun updateColor(clockId: String, @ColorInt seedColor: Int?)
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockViewFactoryImpl.kt b/src/com/android/customization/picker/clock/ui/view/ClockViewFactoryImpl.kt
index 0d603f5..dea6777 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockViewFactoryImpl.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockViewFactoryImpl.kt
@@ -30,6 +30,7 @@
import com.android.systemui.plugins.clocks.WeatherData
import com.android.systemui.shared.clocks.ClockRegistry
import com.android.themepicker.R
+import com.android.wallpaper.config.BaseFlags
import com.android.wallpaper.util.TimeUtils.TimeTicker
import java.util.concurrent.ConcurrentHashMap
@@ -81,6 +82,14 @@
return smallClockFrame
}
+ /** Enables or disables the reactive swipe interaction */
+ override fun setReactiveTouchInteractionEnabled(clockId: String, enable: Boolean) {
+ check(BaseFlags.get().isClockReactiveVariantsEnabled()) {
+ "isClockReactiveVariantsEnabled is disabled"
+ }
+ getController(clockId).events.isReactiveTouchInteractionEnabled = enable
+ }
+
private fun createSmallClockFrame(): FrameLayout {
val smallClockFrame = FrameLayout(appContext)
val layoutParams =
diff --git a/src/com/android/customization/picker/color/data/repository/ColorPickerRepositoryImpl.kt b/src/com/android/customization/picker/color/data/repository/ColorPickerRepositoryImpl.kt
index 942a846..f5b4ac5 100644
--- a/src/com/android/customization/picker/color/data/repository/ColorPickerRepositoryImpl.kt
+++ b/src/com/android/customization/picker/color/data/repository/ColorPickerRepositoryImpl.kt
@@ -26,6 +26,8 @@
import com.android.systemui.monet.Style
import com.android.wallpaper.picker.customization.data.repository.WallpaperColorsRepository
import com.android.wallpaper.picker.customization.shared.model.WallpaperColorsModel
+import javax.inject.Inject
+import javax.inject.Singleton
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -36,7 +38,10 @@
// TODO (b/262924623): refactor to remove dependency on ColorCustomizationManager & ColorOption
// TODO (b/268203200): Create test for ColorPickerRepositoryImpl
-class ColorPickerRepositoryImpl(
+@Singleton
+class ColorPickerRepositoryImpl
+@Inject
+constructor(
wallpaperColorsRepository: WallpaperColorsRepository,
private val colorManager: ColorCustomizationManager,
) : ColorPickerRepository {
diff --git a/src/com/android/customization/picker/color/domain/interactor/ColorPickerInteractor.kt b/src/com/android/customization/picker/color/domain/interactor/ColorPickerInteractor.kt
index e7759ce..aebc6c2 100644
--- a/src/com/android/customization/picker/color/domain/interactor/ColorPickerInteractor.kt
+++ b/src/com/android/customization/picker/color/domain/interactor/ColorPickerInteractor.kt
@@ -18,15 +18,19 @@
import com.android.customization.picker.color.data.repository.ColorPickerRepository
import com.android.customization.picker.color.shared.model.ColorOptionModel
-import javax.inject.Provider
+import javax.inject.Inject
+import javax.inject.Singleton
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.onEach
/** Single entry-point for all application state and business logic related to system color. */
-class ColorPickerInteractor(
+@Singleton
+class ColorPickerInteractor
+@Inject
+constructor(
private val repository: ColorPickerRepository,
- private val snapshotRestorer: Provider<ColorPickerSnapshotRestorer>,
+ private val snapshotRestorer: ColorPickerSnapshotRestorer,
) {
val isApplyingSystemColor = repository.isApplyingSystemColor
@@ -51,7 +55,7 @@
// actually updated until the picker restarts. Wait to do so when updated color options
// become available
repository.select(colorOptionModel)
- snapshotRestorer.get().storeSnapshot(colorOptionModel)
+ snapshotRestorer.storeSnapshot(colorOptionModel)
} catch (e: Exception) {
_selectingColorOption.value = null
}
diff --git a/src/com/android/customization/picker/color/domain/interactor/ColorPickerSnapshotRestorer.kt b/src/com/android/customization/picker/color/domain/interactor/ColorPickerSnapshotRestorer.kt
index dce59eb..656663c 100644
--- a/src/com/android/customization/picker/color/domain/interactor/ColorPickerSnapshotRestorer.kt
+++ b/src/com/android/customization/picker/color/domain/interactor/ColorPickerSnapshotRestorer.kt
@@ -18,14 +18,20 @@
package com.android.customization.picker.color.domain.interactor
import android.util.Log
+import com.android.customization.picker.color.data.repository.ColorPickerRepository
import com.android.customization.picker.color.shared.model.ColorOptionModel
import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer
import com.android.wallpaper.picker.undo.domain.interactor.SnapshotStore
import com.android.wallpaper.picker.undo.shared.model.RestorableSnapshot
+import javax.inject.Inject
+import javax.inject.Singleton
/** Handles state restoration for the color picker system. */
-class ColorPickerSnapshotRestorer(
- private val interactor: ColorPickerInteractor,
+@Singleton
+class ColorPickerSnapshotRestorer
+@Inject
+constructor(
+ private val repository: ColorPickerRepository,
) : SnapshotRestorer {
private var snapshotStore: SnapshotStore = SnapshotStore.NOOP
@@ -39,7 +45,7 @@
store: SnapshotStore,
): RestorableSnapshot {
snapshotStore = store
- originalOption = interactor.getCurrentColorOption()
+ originalOption = repository.getCurrentColorOption()
return snapshot(originalOption)
}
@@ -60,7 +66,7 @@
)
}
- interactor.select(optionToRestore)
+ repository.select(optionToRestore)
}
}
diff --git a/src/com/android/customization/picker/color/ui/binder/ColorPickerBinder.kt b/src/com/android/customization/picker/color/ui/binder/ColorPickerBinder.kt
index 7b5b598..05e42c9 100644
--- a/src/com/android/customization/picker/color/ui/binder/ColorPickerBinder.kt
+++ b/src/com/android/customization/picker/color/ui/binder/ColorPickerBinder.kt
@@ -133,9 +133,10 @@
interface Binding {
fun saveInstanceState(savedState: Bundle)
+
fun restoreInstanceState(savedState: Bundle)
}
- private val LAYOUT_MANAGER_SAVED_STATE: String = "layout_manager_state"
+ private const val LAYOUT_MANAGER_SAVED_STATE: String = "layout_manager_state"
private var layoutManagerSavedState: Parcelable? = null
}
diff --git a/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt b/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt
index d6c728e..c5eb76f 100644
--- a/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt
+++ b/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt
@@ -33,7 +33,7 @@
import com.android.customization.module.ThemePickerInjector
import com.android.customization.picker.color.ui.binder.ColorPickerBinder
import com.android.themepicker.R
-import com.android.wallpaper.module.CustomizationSections
+import com.android.wallpaper.model.Screen
import com.android.wallpaper.module.InjectorProvider
import com.android.wallpaper.picker.AppbarFragment
import com.android.wallpaper.picker.customization.data.repository.WallpaperColorsRepository
@@ -85,10 +85,7 @@
viewModel =
ViewModelProvider(
requireActivity(),
- injector.getColorPickerViewModelFactory(
- context = requireContext(),
- wallpaperColorsRepository = wallpaperColorsRepository,
- ),
+ injector.getColorPickerViewModelFactory(requireContext()),
)
.get(),
lifecycleOwner = this,
@@ -126,7 +123,7 @@
loadInitialColors(
wallpaperManager,
wallpaperColorsRepository,
- CustomizationSections.Screen.LOCK_SCREEN
+ Screen.LOCK_SCREEN
)
}
}
@@ -138,7 +135,7 @@
wallpaperColorsRepository.setLockWallpaperColors(colors)
},
wallpaperInteractor = injector.getWallpaperInteractor(requireContext()),
- screen = CustomizationSections.Screen.LOCK_SCREEN,
+ screen = Screen.LOCK_SCREEN,
),
lifecycleOwner = this,
offsetToStart =
@@ -177,7 +174,7 @@
loadInitialColors(
wallpaperManager,
wallpaperColorsRepository,
- CustomizationSections.Screen.HOME_SCREEN
+ Screen.HOME_SCREEN
)
}
}
@@ -189,7 +186,7 @@
wallpaperColorsRepository.setHomeWallpaperColors(colors)
},
wallpaperInteractor = injector.getWallpaperInteractor(requireContext()),
- screen = CustomizationSections.Screen.HOME_SCREEN,
+ screen = Screen.HOME_SCREEN,
),
lifecycleOwner = this,
offsetToStart =
@@ -204,6 +201,7 @@
context,
lifecycle,
injector.getDarkModeSnapshotRestorer(requireContext()),
+ injector.uiModeManager.get(),
injector.getUserEventLogger(),
)
.createView(requireContext())
@@ -221,19 +219,19 @@
private suspend fun loadInitialColors(
wallpaperManager: WallpaperManager,
colorViewModel: WallpaperColorsRepository,
- screen: CustomizationSections.Screen,
+ screen: Screen,
) {
withContext(Dispatchers.IO) {
val colors =
wallpaperManager.getWallpaperColors(
- if (screen == CustomizationSections.Screen.LOCK_SCREEN) {
+ if (screen == Screen.LOCK_SCREEN) {
WallpaperManager.FLAG_LOCK
} else {
WallpaperManager.FLAG_SYSTEM
}
)
withContext(Dispatchers.Main) {
- if (screen == CustomizationSections.Screen.LOCK_SCREEN) {
+ if (screen == Screen.LOCK_SCREEN) {
colorViewModel.setLockWallpaperColors(colors)
} else {
colorViewModel.setHomeWallpaperColors(colors)
@@ -251,10 +249,6 @@
return requireContext().getString(R.string.color_picker_title)
}
- override fun getToolbarColorId(): Int {
- return android.R.color.transparent
- }
-
override fun getToolbarTextColor(): Int {
return ContextCompat.getColor(
requireContext(),
diff --git a/src/com/android/customization/picker/common/ui/view/DoubleRowListItemSpacing.kt b/src/com/android/customization/picker/common/ui/view/DoubleRowListItemSpacing.kt
new file mode 100644
index 0000000..746061c
--- /dev/null
+++ b/src/com/android/customization/picker/common/ui/view/DoubleRowListItemSpacing.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 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.customization.picker.common.ui.view
+
+import android.graphics.Rect
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+
+/** Item spacing used by the RecyclerView with 2 rows. */
+class DoubleRowListItemSpacing(private val rowSpaceDp: Int) : RecyclerView.ItemDecoration() {
+ override fun getItemOffsets(
+ outRect: Rect,
+ view: View,
+ parent: RecyclerView,
+ state: RecyclerView.State,
+ ) {
+ val itemIndex = parent.getChildAdapterPosition(view)
+ val columnIndex = itemIndex / 2
+ val isRtl = parent.layoutManager?.layoutDirection == View.LAYOUT_DIRECTION_RTL
+ val density = parent.context.resources.displayMetrics.density
+
+ val itemCount = parent.adapter?.itemCount ?: 0
+ val columnCount = (itemCount + 1) / 2
+ when {
+ columnCount == 1 -> {
+ outRect.left = EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density)
+ outRect.right = EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density)
+ }
+ columnIndex > 0 && columnIndex < columnCount - 1 -> {
+ outRect.left = COMMON_HORIZONTAL_SPACING_DP.toPx(density)
+ outRect.right = COMMON_HORIZONTAL_SPACING_DP.toPx(density)
+ }
+ columnIndex == 0 -> {
+ outRect.left =
+ if (!isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density)
+ else COMMON_HORIZONTAL_SPACING_DP.toPx(density)
+ outRect.right =
+ if (isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density)
+ else COMMON_HORIZONTAL_SPACING_DP.toPx(density)
+ }
+ columnIndex == columnCount - 1 -> {
+ outRect.right =
+ if (!isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density)
+ else COMMON_HORIZONTAL_SPACING_DP.toPx(density)
+ outRect.left =
+ if (isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density)
+ else COMMON_HORIZONTAL_SPACING_DP.toPx(density)
+ }
+ }
+
+ if (itemIndex % 2 == 0) {
+ outRect.bottom = rowSpaceDp.toPx(density)
+ }
+ }
+
+ private fun Int.toPx(density: Float): Int {
+ return (this * density).toInt()
+ }
+
+ companion object {
+ const val EDGE_ITEM_HORIZONTAL_SPACING_DP = 20
+ const val COMMON_HORIZONTAL_SPACING_DP = 4
+ }
+}
diff --git a/src/com/android/customization/picker/grid/ui/fragment/GridFragment.kt b/src/com/android/customization/picker/grid/ui/fragment/GridFragment.kt
index 74b88db..b48f41a 100644
--- a/src/com/android/customization/picker/grid/ui/fragment/GridFragment.kt
+++ b/src/com/android/customization/picker/grid/ui/fragment/GridFragment.kt
@@ -36,8 +36,8 @@
import com.android.customization.picker.grid.ui.viewmodel.GridScreenViewModel
import com.android.themepicker.R
import com.android.wallpaper.config.BaseFlags
+import com.android.wallpaper.model.Screen
import com.android.wallpaper.module.CurrentWallpaperInfoFactory
-import com.android.wallpaper.module.CustomizationSections
import com.android.wallpaper.module.InjectorProvider
import com.android.wallpaper.picker.AppbarFragment
import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
@@ -149,10 +149,6 @@
return getString(R.string.grid_title)
}
- override fun getToolbarColorId(): Int {
- return android.R.color.transparent
- }
-
override fun getToolbarTextColor(): Int {
return ContextCompat.getColor(
requireContext(),
@@ -196,7 +192,7 @@
}
},
wallpaperInteractor = wallpaperInteractor,
- screen = CustomizationSections.Screen.HOME_SCREEN,
+ screen = Screen.HOME_SCREEN,
),
lifecycleOwner = viewLifecycleOwner,
offsetToStart = false,
diff --git a/src/com/android/customization/picker/notifications/domain/interactor/NotificationsSnapshotRestorer.kt b/src/com/android/customization/picker/notifications/domain/interactor/NotificationsSnapshotRestorer.kt
index 09d2d29..e82d00a 100644
--- a/src/com/android/customization/picker/notifications/domain/interactor/NotificationsSnapshotRestorer.kt
+++ b/src/com/android/customization/picker/notifications/domain/interactor/NotificationsSnapshotRestorer.kt
@@ -40,16 +40,19 @@
store: SnapshotStore,
): RestorableSnapshot {
snapshotStore = store
- backgroundScope.launch {
- interactor.isShowNotificationsOnLockScreenEnabled.collect {
- storeSnapshot(
- NotificationSnapshotModel(isShowNotificationsOnLockScreenEnabled = it)
- )
- }
- }
+ // The initial snapshot should be returned and stored before storing additional snapshots.
return snapshot(
- NotificationSnapshotModel(interactor.isShowNotificationsOnLockScreenEnabled.value)
- )
+ NotificationSnapshotModel(interactor.isShowNotificationsOnLockScreenEnabled().value)
+ )
+ .also {
+ backgroundScope.launch {
+ interactor.isShowNotificationsOnLockScreenEnabled().collect {
+ storeSnapshot(
+ NotificationSnapshotModel(isShowNotificationsOnLockScreenEnabled = it)
+ )
+ }
+ }
+ }
}
override suspend fun restoreToSnapshot(snapshot: RestorableSnapshot) {
diff --git a/src/com/android/customization/picker/notifications/ui/binder/NotificationSectionBinder.kt b/src/com/android/customization/picker/notifications/ui/binder/NotificationSectionBinder.kt
index 8f2727c..baf7bbf 100644
--- a/src/com/android/customization/picker/notifications/ui/binder/NotificationSectionBinder.kt
+++ b/src/com/android/customization/picker/notifications/ui/binder/NotificationSectionBinder.kt
@@ -44,7 +44,7 @@
lifecycleOwner.lifecycleScope.launch {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
- launch { viewModel.isSwitchOn.collect { switch.isChecked = it } }
+ launch { viewModel.isSwitchOn().collect { switch.isChecked = it } }
}
}
}
diff --git a/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModel.kt b/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModel.kt
index 5db7626..022dc9b 100644
--- a/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModel.kt
+++ b/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModel.kt
@@ -35,14 +35,14 @@
) : ViewModel() {
/** Whether the switch should be on. */
- val isSwitchOn: Flow<Boolean> = interactor.isShowNotificationsOnLockScreenEnabled
+ suspend fun isSwitchOn(): Flow<Boolean> = interactor.isShowNotificationsOnLockScreenEnabled()
/** Notifies that the section has been clicked. */
fun onClicked() {
viewModelScope.launch {
interactor.toggleShowNotificationsOnLockscreenEnabled()
logger.logLockScreenNotificationApplied(
- interactor.isShowNotificationsOnLockScreenEnabled.value
+ interactor.isShowNotificationsOnLockScreenEnabled().value
)
}
}
diff --git a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
index c434ce3..e1f8df2 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
@@ -42,9 +42,9 @@
import com.android.themepicker.R
import com.android.wallpaper.model.CustomizationSectionController
import com.android.wallpaper.model.CustomizationSectionController.CustomizationSectionNavigationController
+import com.android.wallpaper.model.Screen
import com.android.wallpaper.model.WallpaperPreviewNavigator
import com.android.wallpaper.module.CurrentWallpaperInfoFactory
-import com.android.wallpaper.module.CustomizationSections
import com.android.wallpaper.picker.customization.data.repository.WallpaperColorsRepository
import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
import com.android.wallpaper.picker.customization.ui.section.ScreenPreviewClickView
@@ -62,7 +62,7 @@
class PreviewWithClockCarouselSectionController(
activity: ComponentActivity,
private val lifecycleOwner: LifecycleOwner,
- private val screen: CustomizationSections.Screen,
+ private val screen: Screen,
wallpaperInfoFactory: CurrentWallpaperInfoFactory,
wallpaperColorsRepository: WallpaperColorsRepository,
displayUtils: DisplayUtils,
@@ -109,7 +109,7 @@
params: CustomizationSectionController.ViewCreationParams,
): ScreenPreviewView {
val view = super.createView(context, params)
- if (screen == CustomizationSections.Screen.LOCK_SCREEN) {
+ if (screen == Screen.LOCK_SCREEN) {
val screenPreviewClickView: ScreenPreviewClickView =
view.requireViewById(com.android.wallpaper.R.id.screen_preview_click_view)
val clockColorAndSizeButtonStub: ViewStub =
diff --git a/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt b/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt
index b3e778b..78e3745 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt
@@ -25,9 +25,9 @@
import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
import com.android.customization.picker.preview.ui.viewmodel.PreviewWithThemeViewModel
import com.android.wallpaper.R
+import com.android.wallpaper.model.Screen
import com.android.wallpaper.model.WallpaperPreviewNavigator
import com.android.wallpaper.module.CurrentWallpaperInfoFactory
-import com.android.wallpaper.module.CustomizationSections
import com.android.wallpaper.picker.customization.data.repository.WallpaperColorsRepository
import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
import com.android.wallpaper.picker.customization.ui.section.ScreenPreviewSectionController
@@ -45,7 +45,7 @@
open class PreviewWithThemeSectionController(
activity: Activity,
lifecycleOwner: LifecycleOwner,
- private val screen: CustomizationSections.Screen,
+ private val screen: Screen,
private val wallpaperInfoFactory: CurrentWallpaperInfoFactory,
private val wallpaperColorsRepository: WallpaperColorsRepository,
displayUtils: DisplayUtils,
diff --git a/src/com/android/customization/picker/preview/ui/viewmodel/PreviewWithThemeViewModel.kt b/src/com/android/customization/picker/preview/ui/viewmodel/PreviewWithThemeViewModel.kt
index 83f986d..7877f11 100644
--- a/src/com/android/customization/picker/preview/ui/viewmodel/PreviewWithThemeViewModel.kt
+++ b/src/com/android/customization/picker/preview/ui/viewmodel/PreviewWithThemeViewModel.kt
@@ -21,8 +21,8 @@
import android.os.Bundle
import com.android.customization.model.themedicon.domain.interactor.ThemedIconInteractor
import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
+import com.android.wallpaper.model.Screen
import com.android.wallpaper.model.WallpaperInfo
-import com.android.wallpaper.module.CustomizationSections
import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
import com.android.wallpaper.picker.customization.ui.viewmodel.ScreenPreviewViewModel
import com.android.wallpaper.util.PreviewUtils
@@ -38,7 +38,7 @@
wallpaperInteractor: WallpaperInteractor,
private val themedIconInteractor: ThemedIconInteractor? = null,
colorPickerInteractor: ColorPickerInteractor? = null,
- screen: CustomizationSections.Screen,
+ screen: Screen,
) :
ScreenPreviewViewModel(
previewUtils,
@@ -59,6 +59,5 @@
colorIsLoading ->
wallpaperIsLoading || colorIsLoading
}
- }
- ?: wallpaperIsLoading
+ } ?: wallpaperIsLoading
}
diff --git a/src/com/android/customization/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepository.kt b/src/com/android/customization/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepository.kt
index 6bfe348..ff5f828 100644
--- a/src/com/android/customization/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepository.kt
+++ b/src/com/android/customization/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepository.kt
@@ -20,7 +20,10 @@
import com.android.customization.picker.quickaffordance.shared.model.KeyguardQuickAffordancePickerAffordanceModel as AffordanceModel
import com.android.customization.picker.quickaffordance.shared.model.KeyguardQuickAffordancePickerSelectionModel as SelectionModel
import com.android.customization.picker.quickaffordance.shared.model.KeyguardQuickAffordancePickerSlotModel as SlotModel
-import com.android.systemui.shared.customization.data.content.CustomizationProviderClient as Client
+import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
+import com.android.wallpaper.picker.di.modules.MainDispatcher
+import javax.inject.Inject
+import javax.inject.Singleton
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -31,10 +34,10 @@
* Abstracts access to application state related to functionality for selecting, picking, or setting
* lock screen quick affordances.
*/
-class KeyguardQuickAffordancePickerRepository(
- private val client: Client,
- private val scope: CoroutineScope
-) {
+@Singleton
+class KeyguardQuickAffordancePickerRepository
+@Inject
+constructor(client: CustomizationProviderClient, @MainDispatcher mainScope: CoroutineScope) {
/** List of slots available on the device. */
val slots: Flow<List<SlotModel>> =
client.observeSlots().map { slots -> slots.map { slot -> slot.toModel() } }
@@ -44,23 +47,23 @@
client
.observeAffordances()
.map { affordances -> affordances.map { affordance -> affordance.toModel() } }
- .shareIn(scope, replay = 1, started = SharingStarted.Lazily)
+ .shareIn(mainScope, replay = 1, started = SharingStarted.Lazily)
/** List of slot-affordance pairs, modeling what the user has currently chosen for each slot. */
val selections: Flow<List<SelectionModel>> =
client
.observeSelections()
.map { selections -> selections.map { selection -> selection.toModel() } }
- .shareIn(scope, replay = 1, started = SharingStarted.Lazily)
+ .shareIn(mainScope, replay = 1, started = SharingStarted.Lazily)
- private fun Client.Slot.toModel(): SlotModel {
+ private fun CustomizationProviderClient.Slot.toModel(): SlotModel {
return SlotModel(
id = id,
maxSelectedQuickAffordances = capacity,
)
}
- private fun Client.Affordance.toModel(): AffordanceModel {
+ private fun CustomizationProviderClient.Affordance.toModel(): AffordanceModel {
return AffordanceModel(
id = id,
name = name,
@@ -73,7 +76,7 @@
)
}
- private fun Client.Selection.toModel(): SelectionModel {
+ private fun CustomizationProviderClient.Selection.toModel(): SelectionModel {
return SelectionModel(
slotId = slotId,
affordanceId = affordanceId,
diff --git a/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractor.kt b/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractor.kt
index 3eca624..b17b939 100644
--- a/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractor.kt
+++ b/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractor.kt
@@ -23,18 +23,22 @@
import com.android.customization.picker.quickaffordance.shared.model.KeyguardQuickAffordancePickerAffordanceModel as AffordanceModel
import com.android.customization.picker.quickaffordance.shared.model.KeyguardQuickAffordancePickerSelectionModel as SelectionModel
import com.android.customization.picker.quickaffordance.shared.model.KeyguardQuickAffordancePickerSlotModel as SlotModel
-import com.android.systemui.shared.customization.data.content.CustomizationProviderClient as Client
-import javax.inject.Provider
+import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
+import javax.inject.Inject
+import javax.inject.Singleton
import kotlinx.coroutines.flow.Flow
/**
* Single entry-point for all application state and business logic related to quick affordances on
* the lock screen.
*/
-class KeyguardQuickAffordancePickerInteractor(
- private val repository: KeyguardQuickAffordancePickerRepository,
- private val client: Client,
- private val snapshotRestorer: Provider<KeyguardQuickAffordanceSnapshotRestorer>,
+@Singleton
+class KeyguardQuickAffordancePickerInteractor
+@Inject
+constructor(
+ repository: KeyguardQuickAffordancePickerRepository,
+ private val client: CustomizationProviderClient,
+ private val snapshotRestorer: KeyguardQuickAffordanceSnapshotRestorer,
) {
/** List of slots available on the device. */
val slots: Flow<List<SlotModel>> = repository.slots
@@ -60,7 +64,7 @@
affordanceId = affordanceId,
)
- snapshotRestorer.get().storeSnapshot()
+ snapshotRestorer.storeSnapshot()
}
/** Unselects all affordances from the slot with the given ID. */
@@ -69,7 +73,7 @@
slotId = slotId,
)
- snapshotRestorer.get().storeSnapshot()
+ snapshotRestorer.storeSnapshot()
}
/** Unselects all affordances from all slots. */
diff --git a/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordanceSnapshotRestorer.kt b/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordanceSnapshotRestorer.kt
index fee0cb5..f467989 100644
--- a/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordanceSnapshotRestorer.kt
+++ b/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordanceSnapshotRestorer.kt
@@ -21,10 +21,14 @@
import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer
import com.android.wallpaper.picker.undo.domain.interactor.SnapshotStore
import com.android.wallpaper.picker.undo.shared.model.RestorableSnapshot
+import javax.inject.Inject
+import javax.inject.Singleton
/** Handles state restoration for the quick affordances system. */
-class KeyguardQuickAffordanceSnapshotRestorer(
- private val interactor: KeyguardQuickAffordancePickerInteractor,
+@Singleton
+class KeyguardQuickAffordanceSnapshotRestorer
+@Inject
+constructor(
private val client: CustomizationProviderClient,
) : SnapshotRestorer {
@@ -43,7 +47,7 @@
override suspend fun restoreToSnapshot(snapshot: RestorableSnapshot) {
// reset all current selections
- interactor.unselectAll()
+ client.querySlots().forEach { client.deleteAllSelections(it.id) }
val allSelections = checkNotNull(snapshot.args[KEY_SELECTIONS])
if (allSelections.isEmpty()) return
@@ -55,9 +59,9 @@
}
selections.forEach { (slotId, affordanceId) ->
- interactor.select(
- slotId,
- affordanceId,
+ client.insertSelection(
+ slotId = slotId,
+ affordanceId = affordanceId,
)
}
}
diff --git a/src/com/android/customization/picker/quickaffordance/ui/fragment/KeyguardQuickAffordancePickerFragment.kt b/src/com/android/customization/picker/quickaffordance/ui/fragment/KeyguardQuickAffordancePickerFragment.kt
index fd79ca5..8b1c44a 100644
--- a/src/com/android/customization/picker/quickaffordance/ui/fragment/KeyguardQuickAffordancePickerFragment.kt
+++ b/src/com/android/customization/picker/quickaffordance/ui/fragment/KeyguardQuickAffordancePickerFragment.kt
@@ -92,10 +92,6 @@
return requireContext().getString(R.string.keyguard_quick_affordance_title)
}
- override fun getToolbarColorId(): Int {
- return android.R.color.transparent
- }
-
override fun getToolbarTextColor(): Int {
return ContextCompat.getColor(
requireContext(),
diff --git a/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt b/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
index 97afb7a..da1040e 100644
--- a/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
+++ b/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
@@ -31,8 +31,8 @@
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants
import com.android.themepicker.R
+import com.android.wallpaper.model.Screen
import com.android.wallpaper.module.CurrentWallpaperInfoFactory
-import com.android.wallpaper.module.CustomizationSections
import com.android.wallpaper.picker.common.button.ui.viewmodel.ButtonStyle
import com.android.wallpaper.picker.common.button.ui.viewmodel.ButtonViewModel
import com.android.wallpaper.picker.common.dialog.ui.viewmodel.DialogViewModel
@@ -102,7 +102,7 @@
}
},
wallpaperInteractor = wallpaperInteractor,
- screen = CustomizationSections.Screen.LOCK_SCREEN,
+ screen = Screen.LOCK_SCREEN,
)
/** A locally-selected slot, if the user ever switched from the original one. */
@@ -307,7 +307,8 @@
KeyguardQuickAffordanceSummaryViewModel(
description = toDescriptionText(context, slots),
- icon1 = icon1
+ icon1 =
+ icon1
?: if (icon2 == null) {
Icon.Resource(
res = R.drawable.link_off,
diff --git a/src/com/android/customization/picker/settings/data/repository/ColorContrastSectionRepository.kt b/src/com/android/customization/picker/settings/data/repository/ColorContrastSectionRepository.kt
new file mode 100644
index 0000000..85cf307
--- /dev/null
+++ b/src/com/android/customization/picker/settings/data/repository/ColorContrastSectionRepository.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 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.customization.picker.settings.data.repository
+
+import android.app.UiModeManager
+import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
+import com.android.wallpaper.system.UiModeManagerWrapper
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Singleton
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.asExecutor
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+
+@Singleton
+class ColorContrastSectionRepository
+@Inject
+constructor(
+ uiModeManager: UiModeManagerWrapper,
+ @BackgroundDispatcher bgDispatcher: CoroutineDispatcher,
+) {
+ var contrast: Flow<Float> = callbackFlow {
+ val executor: Executor = bgDispatcher.asExecutor()
+ val listener =
+ UiModeManager.ContrastChangeListener { contrast ->
+ // Emit the new contrast value whenever it changes
+ trySend(contrast)
+ }
+
+ // Emit the current contrast value immediately
+ uiModeManager.getContrast()?.let { currentContrast -> trySend(currentContrast) }
+
+ uiModeManager.addContrastChangeListener(executor, listener)
+
+ awaitClose {
+ // Unregister the listener when the flow collection is cancelled or no longer in use
+ uiModeManager.removeContrastChangeListener(listener)
+ }
+ }
+}
diff --git a/src/com/android/customization/picker/settings/domain/interactor/ColorContrastSectionInteractor.kt b/src/com/android/customization/picker/settings/domain/interactor/ColorContrastSectionInteractor.kt
new file mode 100644
index 0000000..003d4d0
--- /dev/null
+++ b/src/com/android/customization/picker/settings/domain/interactor/ColorContrastSectionInteractor.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.customization.picker.settings.domain.interactor
+
+import com.android.customization.picker.settings.data.repository.ColorContrastSectionRepository
+import javax.inject.Inject
+import javax.inject.Singleton
+import kotlinx.coroutines.flow.Flow
+
+@Singleton
+class ColorContrastSectionInteractor
+@Inject
+constructor(colorContrastSectionRepository: ColorContrastSectionRepository) {
+ val contrast: Flow<Float> = colorContrastSectionRepository.contrast
+}
diff --git a/src/com/android/customization/picker/settings/ui/binder/ColorContrastSectionViewBinder.kt b/src/com/android/customization/picker/settings/ui/binder/ColorContrastSectionViewBinder.kt
new file mode 100644
index 0000000..e3d2427
--- /dev/null
+++ b/src/com/android/customization/picker/settings/ui/binder/ColorContrastSectionViewBinder.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 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.customization.picker.settings.ui.binder
+
+import android.view.View
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.core.view.isVisible
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import com.android.customization.picker.settings.ui.viewmodel.ColorContrastSectionViewModel
+import com.android.themepicker.R
+import com.android.wallpaper.picker.common.icon.ui.viewbinder.IconViewBinder
+import com.android.wallpaper.picker.common.text.ui.viewbinder.TextViewBinder
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.launch
+
+object ColorContrastSectionViewBinder {
+ fun bind(
+ view: View,
+ viewModel: ColorContrastSectionViewModel,
+ lifecycleOwner: LifecycleOwner,
+ onClicked: () -> Unit,
+ ) {
+ view.setOnClickListener { onClicked() }
+
+ val descriptionView: TextView =
+ view.requireViewById(R.id.color_contrast_section_description)
+ val icon: ImageView = view.requireViewById(R.id.icon_1)
+
+ lifecycleOwner.lifecycleScope.launch {
+ viewModel.summary
+ .flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED)
+ .collectLatest { summary ->
+ TextViewBinder.bind(
+ view = descriptionView,
+ viewModel = summary.description,
+ )
+ if (summary.icon != null) {
+ IconViewBinder.bind(
+ view = icon,
+ viewModel = summary.icon,
+ )
+ }
+ icon.isVisible = summary.icon != null
+ }
+ }
+ }
+}
diff --git a/src/com/android/customization/picker/settings/ui/section/ColorContrastSectionController.kt b/src/com/android/customization/picker/settings/ui/section/ColorContrastSectionController.kt
new file mode 100644
index 0000000..cd5f65d
--- /dev/null
+++ b/src/com/android/customization/picker/settings/ui/section/ColorContrastSectionController.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 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.customization.picker.settings.ui.section
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Intent
+import android.provider.Settings
+import android.view.LayoutInflater
+import androidx.lifecycle.LifecycleOwner
+import com.android.customization.picker.settings.ui.binder.ColorContrastSectionViewBinder
+import com.android.customization.picker.settings.ui.view.ColorContrastSectionView
+import com.android.customization.picker.settings.ui.viewmodel.ColorContrastSectionViewModel
+import com.android.themepicker.R
+import com.android.wallpaper.model.CustomizationSectionController
+
+class ColorContrastSectionController(
+ private val viewModel: ColorContrastSectionViewModel,
+ private val lifecycleOwner: LifecycleOwner,
+) : CustomizationSectionController<ColorContrastSectionView> {
+
+ // TODO (b/330381229): Check for whether the color contrast activity intent
+ // resolves to something or not before marking the feature as available
+ override fun isAvailable(context: Context): Boolean {
+ return true
+ }
+
+ @SuppressLint("InflateParams") // We're okay not providing a parent view.
+ override fun createView(context: Context): ColorContrastSectionView {
+ val view =
+ LayoutInflater.from(context)
+ .inflate(
+ R.layout.color_contrast_section_view,
+ null,
+ ) as ColorContrastSectionView
+ ColorContrastSectionViewBinder.bind(
+ view = view,
+ lifecycleOwner = lifecycleOwner,
+ viewModel = viewModel
+ ) {
+ context.startActivity(Intent(Settings.ACTION_ACCESSIBILITY_COLOR_CONTRAST_SETTINGS))
+ }
+ return view
+ }
+}
diff --git a/src/com/android/customization/picker/settings/ui/view/ColorContrastSectionView.kt b/src/com/android/customization/picker/settings/ui/view/ColorContrastSectionView.kt
new file mode 100644
index 0000000..6aa603b
--- /dev/null
+++ b/src/com/android/customization/picker/settings/ui/view/ColorContrastSectionView.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 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.customization.picker.settings.ui.view
+
+import android.content.Context
+import android.util.AttributeSet
+import com.android.wallpaper.picker.SectionView
+
+class ColorContrastSectionView(
+ context: Context,
+ attrs: AttributeSet?,
+) :
+ SectionView(
+ context,
+ attrs,
+ )
diff --git a/src/com/android/customization/picker/settings/ui/viewmodel/ColorContrastSectionDataViewModel.kt b/src/com/android/customization/picker/settings/ui/viewmodel/ColorContrastSectionDataViewModel.kt
new file mode 100644
index 0000000..871dc43
--- /dev/null
+++ b/src/com/android/customization/picker/settings/ui/viewmodel/ColorContrastSectionDataViewModel.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 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.customization.picker.settings.ui.viewmodel
+
+import com.android.wallpaper.picker.common.icon.ui.viewmodel.Icon
+import com.android.wallpaper.picker.common.text.ui.viewmodel.Text
+
+data class ColorContrastSectionDataViewModel(
+ val description: Text,
+ val icon: Icon?,
+)
diff --git a/src/com/android/customization/picker/settings/ui/viewmodel/ColorContrastSectionViewModel.kt b/src/com/android/customization/picker/settings/ui/viewmodel/ColorContrastSectionViewModel.kt
new file mode 100644
index 0000000..ecbe9d1
--- /dev/null
+++ b/src/com/android/customization/picker/settings/ui/viewmodel/ColorContrastSectionViewModel.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2024 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.customization.picker.settings.ui.viewmodel
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.android.customization.picker.settings.domain.interactor.ColorContrastSectionInteractor
+import com.android.themepicker.R
+import com.android.wallpaper.picker.common.icon.ui.viewmodel.Icon
+import com.android.wallpaper.picker.common.text.ui.viewmodel.Text
+import javax.inject.Inject
+import javax.inject.Singleton
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+class ColorContrastSectionViewModel
+private constructor(
+ colorContrastSectionInteractor: ColorContrastSectionInteractor,
+) : ViewModel() {
+
+ val summary: Flow<ColorContrastSectionDataViewModel> =
+ colorContrastSectionInteractor.contrast.map { contrastValue ->
+ when (contrastValue) {
+ ContrastValue.STANDARD.value ->
+ ColorContrastSectionDataViewModel(
+ Text.Resource(R.string.color_contrast_default_title),
+ Icon.Resource(
+ res = R.drawable.ic_contrast_standard,
+ contentDescription = null,
+ )
+ )
+ ContrastValue.MEDIUM.value ->
+ ColorContrastSectionDataViewModel(
+ Text.Resource(R.string.color_contrast_medium_title),
+ Icon.Resource(
+ res = R.drawable.ic_contrast_medium,
+ contentDescription = null,
+ )
+ )
+ ContrastValue.HIGH.value ->
+ ColorContrastSectionDataViewModel(
+ Text.Resource(R.string.color_contrast_high_title),
+ Icon.Resource(
+ res = R.drawable.ic_contrast_high,
+ contentDescription = null,
+ )
+ )
+ else -> {
+ println("Invalid contrast value: $contrastValue")
+ throw IllegalArgumentException("Invalid contrast value")
+ }
+ }
+ }
+
+ enum class ContrastValue(val value: Float) {
+ STANDARD(0f),
+ MEDIUM(0.5f),
+ HIGH(1f)
+ }
+
+ @Singleton
+ class Factory
+ @Inject
+ constructor(
+ private val colorContrastSectionInteractor: ColorContrastSectionInteractor,
+ ) : ViewModelProvider.Factory {
+ override fun <T : ViewModel> create(modelClass: Class<T>): T {
+ @Suppress("UNCHECKED_CAST")
+ return ColorContrastSectionViewModel(
+ colorContrastSectionInteractor = colorContrastSectionInteractor,
+ )
+ as T
+ }
+ }
+}
diff --git a/src/com/android/wallpaper/customization/ui/binder/ColorsFloatingSheetBinder.kt b/src/com/android/wallpaper/customization/ui/binder/ColorsFloatingSheetBinder.kt
new file mode 100644
index 0000000..82f5291
--- /dev/null
+++ b/src/com/android/wallpaper/customization/ui/binder/ColorsFloatingSheetBinder.kt
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.customization.ui.binder
+
+import android.content.Context
+import android.content.res.Configuration.UI_MODE_NIGHT_MASK
+import android.content.res.Configuration.UI_MODE_NIGHT_YES
+import android.view.View
+import android.widget.TextView
+import androidx.core.content.res.ResourcesCompat
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.android.customization.picker.color.shared.model.ColorType
+import com.android.customization.picker.color.ui.binder.ColorOptionIconBinder
+import com.android.customization.picker.color.ui.view.ColorOptionIconView
+import com.android.customization.picker.color.ui.viewmodel.ColorOptionIconViewModel
+import com.android.customization.picker.color.ui.viewmodel.ColorTypeTabViewModel
+import com.android.customization.picker.common.ui.view.DoubleRowListItemSpacing
+import com.android.themepicker.R
+import com.android.wallpaper.customization.ui.viewmodel.ColorPickerViewModel2
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar.Tab.PRIMARY
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar.Tab.SECONDARY
+import com.android.wallpaper.picker.option.ui.adapter.OptionItemAdapter
+import kotlinx.coroutines.launch
+
+object ColorsFloatingSheetBinder {
+
+ fun bind(
+ view: View,
+ viewModel: ColorPickerViewModel2,
+ lifecycleOwner: LifecycleOwner,
+ ) {
+ val subhead = view.requireViewById<TextView>(R.id.color_type_tab_subhead)
+
+ val colorsAdapter =
+ createOptionItemAdapter(view.resources.configuration.uiMode, lifecycleOwner)
+ val colorsList =
+ view.requireViewById<RecyclerView>(R.id.colors_horizontal_list).also {
+ it.initColorsList(view.context.applicationContext, colorsAdapter)
+ }
+
+ val tabs = view.requireViewById<FloatingTabToolbar>(R.id.floating_bar_tabs)
+
+ lifecycleOwner.lifecycleScope.launch {
+ lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+ launch {
+ viewModel.colorTypeTabs.collect { colorTypes ->
+ colorTypes.forEach { (colorType, tabViewModel) ->
+ bindTab(tabs, colorType, tabViewModel)
+ }
+ colorTypes
+ .filterValues { it.isSelected }
+ .keys
+ .firstOrNull()
+ ?.let {
+ when (it) {
+ ColorType.WALLPAPER_COLOR -> tabs.setTabSelected(PRIMARY)
+ ColorType.PRESET_COLOR -> tabs.setTabSelected(SECONDARY)
+ }
+ }
+ }
+ }
+
+ launch { viewModel.colorTypeTabSubheader.collect { subhead.text = it } }
+
+ launch {
+ viewModel.colorOptions.collect { colorOptions ->
+ colorsAdapter.setItems(colorOptions) {
+ var indexToFocus = colorOptions.indexOfFirst { it.isSelected.value }
+ indexToFocus = if (indexToFocus < 0) 0 else indexToFocus
+ (colorsList.layoutManager as LinearLayoutManager)
+ .scrollToPositionWithOffset(indexToFocus, 0)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun createOptionItemAdapter(
+ uiMode: Int,
+ lifecycleOwner: LifecycleOwner
+ ): OptionItemAdapter<ColorOptionIconViewModel> =
+ OptionItemAdapter(
+ layoutResourceId = R.layout.color_option,
+ lifecycleOwner = lifecycleOwner,
+ bindIcon = { foregroundView: View, colorIcon: ColorOptionIconViewModel ->
+ val colorOptionIconView = foregroundView as? ColorOptionIconView
+ val night = uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES
+ colorOptionIconView?.let { ColorOptionIconBinder.bind(it, colorIcon, night) }
+ }
+ )
+
+ private fun RecyclerView.initColorsList(
+ context: Context,
+ adapter: OptionItemAdapter<ColorOptionIconViewModel>,
+ ) {
+ apply {
+ this.adapter = adapter
+ layoutManager =
+ GridLayoutManager(
+ context,
+ 2,
+ GridLayoutManager.HORIZONTAL,
+ false,
+ )
+ addItemDecoration(DoubleRowListItemSpacing(4))
+ }
+ }
+
+ private fun bindTab(
+ tabs: FloatingTabToolbar,
+ colorType: ColorType,
+ viewModel: ColorTypeTabViewModel
+ ) {
+ val tab =
+ when (colorType) {
+ ColorType.WALLPAPER_COLOR -> PRIMARY
+ ColorType.PRESET_COLOR -> SECONDARY
+ }
+ val iconDrawable =
+ ResourcesCompat.getDrawable(
+ tabs.resources,
+ when (colorType) {
+ ColorType.WALLPAPER_COLOR ->
+ com.android.wallpaper.R.drawable.ic_baseline_wallpaper_24
+ ColorType.PRESET_COLOR -> R.drawable.ic_colors
+ },
+ null,
+ )
+ when (colorType) {
+ ColorType.WALLPAPER_COLOR -> tabs.primaryIcon.setImageDrawable(iconDrawable)
+ ColorType.PRESET_COLOR -> tabs.secondaryIcon.setImageDrawable(iconDrawable)
+ }
+ tabs.setTabText(tab, viewModel.name)
+ tabs.setOnTabClick(tab, viewModel.onClick)
+ }
+}
diff --git a/src/com/android/wallpaper/customization/ui/binder/ShortcutFloatingSheetBinder.kt b/src/com/android/wallpaper/customization/ui/binder/ShortcutFloatingSheetBinder.kt
new file mode 100644
index 0000000..6fc1b7f
--- /dev/null
+++ b/src/com/android/wallpaper/customization/ui/binder/ShortcutFloatingSheetBinder.kt
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.customization.ui.binder
+
+import android.app.Dialog
+import android.content.Context
+import android.view.View
+import android.widget.ImageView
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.android.customization.picker.common.ui.view.DoubleRowListItemSpacing
+import com.android.themepicker.R
+import com.android.wallpaper.customization.ui.viewmodel.KeyguardQuickAffordancePickerViewModel2
+import com.android.wallpaper.picker.common.dialog.ui.viewbinder.DialogViewBinder
+import com.android.wallpaper.picker.common.dialog.ui.viewmodel.DialogViewModel
+import com.android.wallpaper.picker.common.icon.ui.viewbinder.IconViewBinder
+import com.android.wallpaper.picker.common.icon.ui.viewmodel.Icon
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar.Tab
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar.Tab.PRIMARY
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar.Tab.SECONDARY
+import com.android.wallpaper.picker.option.ui.adapter.OptionItemAdapter
+import com.android.wallpaper.picker.option.ui.viewmodel.OptionItemViewModel
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.collectIndexed
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+
+@OptIn(ExperimentalCoroutinesApi::class)
+object ShortcutFloatingSheetBinder {
+
+ fun bind(
+ view: View,
+ viewModel: KeyguardQuickAffordancePickerViewModel2,
+ lifecycleOwner: LifecycleOwner,
+ ) {
+ val quickAffordanceAdapter = createOptionItemAdapter(lifecycleOwner)
+ val quickAffordanceList =
+ view.requireViewById<RecyclerView>(R.id.quick_affordance_horizontal_list).also {
+ it.initQuickAffordanceList(view.context.applicationContext, quickAffordanceAdapter)
+ }
+
+ val tabs = view.requireViewById<FloatingTabToolbar>(R.id.floating_bar_tabs)
+
+ var dialog: Dialog? = null
+
+ lifecycleOwner.lifecycleScope.launch {
+ lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+ launch {
+ viewModel.slots
+ .map { slotById -> slotById.values }
+ .collect { slots ->
+ val list = slots.toList()
+ list.mapIndexed { index, slot ->
+ val tab = if (index == 0) PRIMARY else SECONDARY
+ tabs.setSelectedAffordances(tab, slot.selectedQuickAffordances)
+ tabs.setTabText(tab, slot.name)
+ tabs.setOnTabClick(tab, slot.onClicked)
+ }
+ list
+ .indexOfFirst { it.isSelected }
+ .let {
+ if (it == 0) {
+ tabs.setTabSelected(PRIMARY)
+ } else if (it == 1) {
+ tabs.setTabSelected(SECONDARY)
+ }
+ }
+ }
+ }
+
+ launch {
+ viewModel.quickAffordances.collect { affordances ->
+ quickAffordanceAdapter.setItems(affordances)
+ }
+ }
+
+ launch {
+ viewModel.quickAffordances
+ .flatMapLatest { affordances ->
+ combine(affordances.map { affordance -> affordance.isSelected }) {
+ selectedFlags ->
+ selectedFlags.indexOfFirst { it }
+ }
+ }
+ .collectIndexed { index, selectedPosition ->
+ // Scroll the view to show the first selected affordance.
+ if (selectedPosition != -1) {
+ // We use "post" because we need to give the adapter item a pass to
+ // update the view.
+ quickAffordanceList.post {
+ if (index == 0) {
+ // don't animate on initial collection
+ quickAffordanceList.scrollToPosition(selectedPosition)
+ } else {
+ quickAffordanceList.smoothScrollToPosition(selectedPosition)
+ }
+ }
+ }
+ }
+ }
+
+ launch {
+ viewModel.dialog.distinctUntilChanged().collect { dialogRequest ->
+ dialog?.dismiss()
+ dialog =
+ if (dialogRequest != null) {
+ showDialog(
+ context = view.context,
+ request = dialogRequest,
+ onDismissed = viewModel::onDialogDismissed
+ )
+ } else {
+ null
+ }
+ }
+ }
+
+ launch {
+ viewModel.activityStartRequests.collect { intent ->
+ if (intent != null) {
+ view.context.startActivity(intent)
+ viewModel.onActivityStarted()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun showDialog(
+ context: Context,
+ request: DialogViewModel,
+ onDismissed: () -> Unit,
+ ): Dialog {
+ return DialogViewBinder.show(
+ context = context,
+ viewModel = request,
+ onDismissed = onDismissed,
+ )
+ }
+
+ private fun createOptionItemAdapter(lifecycleOwner: LifecycleOwner): OptionItemAdapter<Icon> =
+ OptionItemAdapter(
+ layoutResourceId = R.layout.quick_affordance_list_item,
+ lifecycleOwner = lifecycleOwner,
+ bindIcon = { foregroundView: View, gridIcon: Icon ->
+ val imageView = foregroundView as? ImageView
+ imageView?.let { IconViewBinder.bind(imageView, gridIcon) }
+ },
+ )
+
+ private fun RecyclerView.initQuickAffordanceList(
+ context: Context,
+ adapter: OptionItemAdapter<Icon>
+ ) {
+ apply {
+ this.adapter = adapter
+ layoutManager =
+ GridLayoutManager(
+ context,
+ 2,
+ GridLayoutManager.HORIZONTAL,
+ false,
+ )
+ addItemDecoration(DoubleRowListItemSpacing(12))
+ }
+ }
+
+ private fun FloatingTabToolbar.setSelectedAffordances(
+ tab: Tab,
+ selectedQuickAffordances: List<OptionItemViewModel<Icon>>,
+ ) {
+ val icon =
+ selectedQuickAffordances.firstOrNull()?.payload
+ ?: Icon.Resource(res = R.drawable.link_off, contentDescription = null)
+ IconViewBinder.bind(
+ if (tab == PRIMARY) {
+ this.primaryIcon
+ } else {
+ this.secondaryIcon
+ },
+ icon,
+ )
+ }
+}
diff --git a/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt b/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt
new file mode 100644
index 0000000..250c3d1
--- /dev/null
+++ b/src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.customization.ui.binder
+
+import android.view.View
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil.ThemePickerHomeCustomizationOption
+import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil.ThemePickerLockCustomizationOption
+import com.android.wallpaper.customization.ui.viewmodel.ThemePickerCustomizationOptionsViewModel
+import com.android.wallpaper.picker.customization.ui.binder.CustomizationOptionsBinder
+import com.android.wallpaper.picker.customization.ui.binder.DefaultCustomizationOptionsBinder
+import com.android.wallpaper.picker.customization.ui.util.CustomizationOptionUtil.CustomizationOption
+import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationOptionsViewModel
+import javax.inject.Inject
+import javax.inject.Singleton
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@Singleton
+class ThemePickerCustomizationOptionsBinder
+@Inject
+constructor(private val defaultCustomizationOptionsBinder: DefaultCustomizationOptionsBinder) :
+ CustomizationOptionsBinder {
+
+ override fun bind(
+ view: View,
+ lockScreenCustomizationOptionEntries: List<Pair<CustomizationOption, View>>,
+ homeScreenCustomizationOptionEntries: List<Pair<CustomizationOption, View>>,
+ viewModel: CustomizationOptionsViewModel,
+ lifecycleOwner: LifecycleOwner
+ ) {
+ defaultCustomizationOptionsBinder.bind(
+ view,
+ lockScreenCustomizationOptionEntries,
+ homeScreenCustomizationOptionEntries,
+ viewModel,
+ lifecycleOwner
+ )
+
+ val optionClock =
+ lockScreenCustomizationOptionEntries
+ .find { it.first == ThemePickerLockCustomizationOption.CLOCK }
+ ?.second
+ val optionShortcut =
+ lockScreenCustomizationOptionEntries
+ .find { it.first == ThemePickerLockCustomizationOption.SHORTCUTS }
+ ?.second
+ val optionColors =
+ homeScreenCustomizationOptionEntries
+ .find { it.first == ThemePickerHomeCustomizationOption.COLORS }
+ ?.second
+ viewModel as ThemePickerCustomizationOptionsViewModel
+
+ lifecycleOwner.lifecycleScope.launch {
+ lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+ launch {
+ viewModel.onCustomizeClockClicked.collect {
+ optionClock?.setOnClickListener { _ -> it?.invoke() }
+ }
+ }
+
+ launch {
+ viewModel.onCustomizeShortcutClicked.collect {
+ optionShortcut?.setOnClickListener { _ -> it?.invoke() }
+ }
+ }
+
+ launch {
+ viewModel.onCustomizeColorsClicked.collect {
+ optionColors?.setOnClickListener { _ -> it?.invoke() }
+ }
+ }
+ }
+ }
+
+ ShortcutFloatingSheetBinder.bind(
+ view,
+ viewModel.keyguardQuickAffordancePickerViewModel2,
+ lifecycleOwner,
+ )
+
+ ColorsFloatingSheetBinder.bind(
+ view,
+ viewModel.colorPickerViewModel2,
+ lifecycleOwner,
+ )
+ }
+}
diff --git a/src/com/android/wallpaper/customization/ui/util/ThemePickerCustomizationOptionUtil.kt b/src/com/android/wallpaper/customization/ui/util/ThemePickerCustomizationOptionUtil.kt
new file mode 100644
index 0000000..5e7f568
--- /dev/null
+++ b/src/com/android/wallpaper/customization/ui/util/ThemePickerCustomizationOptionUtil.kt
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.customization.ui.util
+
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import com.android.themepicker.R
+import com.android.wallpaper.model.Screen
+import com.android.wallpaper.model.Screen.HOME_SCREEN
+import com.android.wallpaper.model.Screen.LOCK_SCREEN
+import com.android.wallpaper.picker.customization.ui.util.CustomizationOptionUtil
+import com.android.wallpaper.picker.customization.ui.util.DefaultCustomizationOptionUtil
+import dagger.hilt.android.scopes.ActivityScoped
+import javax.inject.Inject
+
+@ActivityScoped
+class ThemePickerCustomizationOptionUtil
+@Inject
+constructor(private val defaultCustomizationOptionUtil: DefaultCustomizationOptionUtil) :
+ CustomizationOptionUtil {
+
+ enum class ThemePickerLockCustomizationOption : CustomizationOptionUtil.CustomizationOption {
+ CLOCK,
+ SHORTCUTS,
+ SHOW_NOTIFICATIONS,
+ MORE_LOCK_SCREEN_SETTINGS,
+ }
+
+ enum class ThemePickerHomeCustomizationOption : CustomizationOptionUtil.CustomizationOption {
+ COLORS,
+ APP_GRID,
+ APP_SHAPE,
+ THEMED_ICONS,
+ }
+
+ override fun getOptionEntries(
+ screen: Screen,
+ optionContainer: LinearLayout,
+ layoutInflater: LayoutInflater,
+ ): List<Pair<CustomizationOptionUtil.CustomizationOption, View>> {
+ val defaultOptionEntries =
+ defaultCustomizationOptionUtil.getOptionEntries(
+ screen,
+ optionContainer,
+ layoutInflater,
+ )
+ return when (screen) {
+ LOCK_SCREEN ->
+ buildList {
+ addAll(defaultOptionEntries)
+ add(
+ ThemePickerLockCustomizationOption.CLOCK to
+ layoutInflater.inflate(
+ R.layout.customization_option_entry_clock,
+ optionContainer,
+ false,
+ )
+ )
+ add(
+ ThemePickerLockCustomizationOption.SHORTCUTS to
+ layoutInflater.inflate(
+ R.layout.customization_option_entry_keyguard_quick_affordance,
+ optionContainer,
+ false
+ )
+ )
+ add(
+ ThemePickerLockCustomizationOption.SHOW_NOTIFICATIONS to
+ layoutInflater.inflate(
+ R.layout.customization_option_entry_show_notifications,
+ optionContainer,
+ false,
+ )
+ )
+ add(
+ ThemePickerLockCustomizationOption.MORE_LOCK_SCREEN_SETTINGS to
+ layoutInflater.inflate(
+ R.layout.customization_option_entry_more_lock_settings,
+ optionContainer,
+ false,
+ )
+ )
+ }
+ HOME_SCREEN ->
+ buildList {
+ addAll(defaultOptionEntries)
+ add(
+ ThemePickerHomeCustomizationOption.COLORS to
+ layoutInflater.inflate(
+ R.layout.customization_option_entry_colors,
+ optionContainer,
+ false,
+ )
+ )
+ add(
+ ThemePickerHomeCustomizationOption.APP_GRID to
+ layoutInflater.inflate(
+ R.layout.customization_option_entry_app_grid,
+ optionContainer,
+ false,
+ )
+ )
+ add(
+ ThemePickerHomeCustomizationOption.APP_SHAPE to
+ layoutInflater.inflate(
+ R.layout.customization_option_entry_app_shape,
+ optionContainer,
+ false,
+ )
+ )
+ add(
+ ThemePickerHomeCustomizationOption.THEMED_ICONS to
+ layoutInflater.inflate(
+ R.layout.customization_option_entry_themed_icons,
+ optionContainer,
+ false,
+ )
+ )
+ }
+ }
+ }
+
+ override fun initFloatingSheet(
+ bottomSheetContainer: FrameLayout,
+ layoutInflater: LayoutInflater
+ ): Map<CustomizationOptionUtil.CustomizationOption, View> {
+ val map =
+ defaultCustomizationOptionUtil.initFloatingSheet(bottomSheetContainer, layoutInflater)
+ return buildMap {
+ putAll(map)
+ put(
+ ThemePickerLockCustomizationOption.CLOCK,
+ inflateFloatingSheet(
+ ThemePickerLockCustomizationOption.CLOCK,
+ bottomSheetContainer,
+ layoutInflater,
+ )
+ .also { bottomSheetContainer.addView(it) }
+ )
+ put(
+ ThemePickerLockCustomizationOption.SHORTCUTS,
+ inflateFloatingSheet(
+ ThemePickerLockCustomizationOption.SHORTCUTS,
+ bottomSheetContainer,
+ layoutInflater,
+ )
+ .also { bottomSheetContainer.addView(it) }
+ )
+ put(
+ ThemePickerHomeCustomizationOption.COLORS,
+ inflateFloatingSheet(
+ ThemePickerHomeCustomizationOption.COLORS,
+ bottomSheetContainer,
+ layoutInflater,
+ )
+ .also { bottomSheetContainer.addView(it) }
+ )
+ }
+ }
+
+ private fun inflateFloatingSheet(
+ option: CustomizationOptionUtil.CustomizationOption,
+ bottomSheetContainer: FrameLayout,
+ layoutInflater: LayoutInflater,
+ ): View =
+ when (option) {
+ ThemePickerLockCustomizationOption.CLOCK -> R.layout.floating_sheet_clock
+ ThemePickerLockCustomizationOption.SHORTCUTS -> R.layout.floating_sheet_shortcut
+ ThemePickerHomeCustomizationOption.COLORS -> R.layout.floating_sheet_colors
+ else ->
+ throw IllegalStateException(
+ "Customization option $option does not have a bottom sheet view"
+ )
+ }.let { layoutInflater.inflate(it, bottomSheetContainer, false) }
+}
diff --git a/src/com/android/wallpaper/customization/ui/viewmodel/ColorPickerViewModel2.kt b/src/com/android/wallpaper/customization/ui/viewmodel/ColorPickerViewModel2.kt
new file mode 100644
index 0000000..3c77423
--- /dev/null
+++ b/src/com/android/wallpaper/customization/ui/viewmodel/ColorPickerViewModel2.kt
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.customization.ui.viewmodel
+
+import android.content.Context
+import com.android.customization.model.color.ColorOptionImpl
+import com.android.customization.module.logging.ThemesUserEventLogger
+import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
+import com.android.customization.picker.color.shared.model.ColorType
+import com.android.customization.picker.color.ui.viewmodel.ColorOptionIconViewModel
+import com.android.customization.picker.color.ui.viewmodel.ColorTypeTabViewModel
+import com.android.themepicker.R
+import com.android.wallpaper.picker.common.text.ui.viewmodel.Text
+import com.android.wallpaper.picker.option.ui.viewmodel.OptionItemViewModel
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.android.scopes.ViewModelScoped
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
+
+/** Models UI state for a color picker experience. */
+class ColorPickerViewModel2
+@AssistedInject
+constructor(
+ @ApplicationContext context: Context,
+ private val interactor: ColorPickerInteractor,
+ private val logger: ThemesUserEventLogger,
+ @Assisted private val viewModelScope: CoroutineScope,
+) {
+
+ private val selectedColorTypeTabId = MutableStateFlow<ColorType?>(null)
+
+ /** View-models for each color tab. */
+ val colorTypeTabs: Flow<Map<ColorType, ColorTypeTabViewModel>> =
+ combine(
+ interactor.colorOptions,
+ selectedColorTypeTabId,
+ ) { colorOptions, selectedColorTypeIdOrNull ->
+ colorOptions.keys
+ .mapIndexed { index, colorType ->
+ val isSelected =
+ (selectedColorTypeIdOrNull == null && index == 0) ||
+ selectedColorTypeIdOrNull == colorType
+ colorType to
+ ColorTypeTabViewModel(
+ name =
+ when (colorType) {
+ ColorType.WALLPAPER_COLOR ->
+ context.resources.getString(R.string.wallpaper_color_tab)
+ ColorType.PRESET_COLOR ->
+ context.resources.getString(R.string.preset_color_tab_2)
+ },
+ isSelected = isSelected,
+ onClick =
+ if (isSelected) {
+ null
+ } else {
+ { this.selectedColorTypeTabId.value = colorType }
+ },
+ )
+ }
+ .toMap()
+ }
+
+ /** View-models for each color tab subheader */
+ val colorTypeTabSubheader: Flow<String> =
+ selectedColorTypeTabId.map { selectedColorTypeIdOrNull ->
+ when (selectedColorTypeIdOrNull ?: ColorType.WALLPAPER_COLOR) {
+ ColorType.WALLPAPER_COLOR ->
+ context.resources.getString(R.string.wallpaper_color_subheader)
+ ColorType.PRESET_COLOR ->
+ context.resources.getString(R.string.preset_color_subheader)
+ }
+ }
+
+ /** The list of all color options mapped by their color type */
+ private val allColorOptions:
+ Flow<Map<ColorType, List<OptionItemViewModel<ColorOptionIconViewModel>>>> =
+ interactor.colorOptions.map { colorOptions ->
+ colorOptions
+ .map { colorOptionEntry ->
+ colorOptionEntry.key to
+ colorOptionEntry.value.map { colorOptionModel ->
+ val colorOption: ColorOptionImpl =
+ colorOptionModel.colorOption as ColorOptionImpl
+ val lightThemeColors =
+ colorOption.previewInfo.resolveColors(/* darkTheme= */ false)
+ val darkThemeColors =
+ colorOption.previewInfo.resolveColors(/* darkTheme= */ true)
+ val isSelectedFlow: StateFlow<Boolean> =
+ interactor.selectingColorOption
+ .map {
+ it?.colorOption?.isEquivalent(colorOptionModel.colorOption)
+ ?: colorOptionModel.isSelected
+ }
+ .stateIn(viewModelScope)
+ OptionItemViewModel<ColorOptionIconViewModel>(
+ key = MutableStateFlow(colorOptionModel.key) as StateFlow<String>,
+ payload =
+ ColorOptionIconViewModel(
+ lightThemeColor0 = lightThemeColors[0],
+ lightThemeColor1 = lightThemeColors[1],
+ lightThemeColor2 = lightThemeColors[2],
+ lightThemeColor3 = lightThemeColors[3],
+ darkThemeColor0 = darkThemeColors[0],
+ darkThemeColor1 = darkThemeColors[1],
+ darkThemeColor2 = darkThemeColors[2],
+ darkThemeColor3 = darkThemeColors[3],
+ ),
+ text =
+ Text.Loaded(
+ colorOption.getContentDescription(context).toString()
+ ),
+ isTextUserVisible = false,
+ isSelected = isSelectedFlow,
+ onClicked =
+ isSelectedFlow.map { isSelected ->
+ if (isSelected) {
+ null
+ } else {
+ {
+ viewModelScope.launch {
+ interactor.select(colorOptionModel)
+ logger.logThemeColorApplied(
+ colorOptionModel.colorOption
+ .sourceForLogging,
+ colorOptionModel.colorOption
+ .styleForLogging,
+ colorOptionModel.colorOption
+ .seedColorForLogging,
+ )
+ }
+ }
+ }
+ },
+ )
+ }
+ }
+ .toMap()
+ }
+
+ /** The list of all available color options for the selected Color Type. */
+ val colorOptions: Flow<List<OptionItemViewModel<ColorOptionIconViewModel>>> =
+ combine(allColorOptions, selectedColorTypeTabId) {
+ allColorOptions: Map<ColorType, List<OptionItemViewModel<ColorOptionIconViewModel>>>,
+ selectedColorTypeIdOrNull ->
+ val selectedColorTypeId = selectedColorTypeIdOrNull ?: ColorType.WALLPAPER_COLOR
+ allColorOptions[selectedColorTypeId]!!
+ }
+
+ @ViewModelScoped
+ @AssistedFactory
+ interface Factory {
+ fun create(viewModelScope: CoroutineScope): ColorPickerViewModel2
+ }
+}
diff --git a/src/com/android/wallpaper/customization/ui/viewmodel/KeyguardQuickAffordancePickerViewModel2.kt b/src/com/android/wallpaper/customization/ui/viewmodel/KeyguardQuickAffordancePickerViewModel2.kt
new file mode 100644
index 0000000..a7fafe5
--- /dev/null
+++ b/src/com/android/wallpaper/customization/ui/viewmodel/KeyguardQuickAffordancePickerViewModel2.kt
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.customization.ui.viewmodel
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Intent
+import android.graphics.drawable.Drawable
+import androidx.annotation.DrawableRes
+import com.android.customization.module.logging.ThemesUserEventLogger
+import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
+import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordanceSlotViewModel
+import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordanceSummaryViewModel
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.themepicker.R
+import com.android.wallpaper.picker.common.button.ui.viewmodel.ButtonStyle
+import com.android.wallpaper.picker.common.button.ui.viewmodel.ButtonViewModel
+import com.android.wallpaper.picker.common.dialog.ui.viewmodel.DialogViewModel
+import com.android.wallpaper.picker.common.icon.ui.viewmodel.Icon
+import com.android.wallpaper.picker.common.text.ui.viewmodel.Text
+import com.android.wallpaper.picker.option.ui.viewmodel.OptionItemViewModel
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.android.scopes.ViewModelScoped
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
+
+class KeyguardQuickAffordancePickerViewModel2
+@AssistedInject
+constructor(
+ @ApplicationContext private val applicationContext: Context,
+ private val quickAffordanceInteractor: KeyguardQuickAffordancePickerInteractor,
+ private val logger: ThemesUserEventLogger,
+ @Assisted private val viewModelScope: CoroutineScope,
+) {
+
+ /** A locally-selected slot, if the user ever switched from the original one. */
+ private val _selectedSlotId = MutableStateFlow<String?>(null)
+ /** The ID of the selected slot. */
+ val selectedSlotId: StateFlow<String> =
+ combine(
+ quickAffordanceInteractor.slots,
+ _selectedSlotId,
+ ) { slots, selectedSlotIdOrNull ->
+ if (selectedSlotIdOrNull != null) {
+ slots.first { slot -> slot.id == selectedSlotIdOrNull }
+ } else {
+ // If we haven't yet selected a new slot locally, default to the first slot.
+ slots[0]
+ }
+ }
+ .map { selectedSlot -> selectedSlot.id }
+ .stateIn(
+ scope = viewModelScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = "",
+ )
+
+ /** View-models for each slot, keyed by slot ID. */
+ val slots: Flow<Map<String, KeyguardQuickAffordanceSlotViewModel>> =
+ combine(
+ quickAffordanceInteractor.slots,
+ quickAffordanceInteractor.affordances,
+ quickAffordanceInteractor.selections,
+ selectedSlotId,
+ ) { slots, affordances, selections, selectedSlotId ->
+ slots.associate { slot ->
+ val selectedAffordanceIds =
+ selections
+ .filter { selection -> selection.slotId == slot.id }
+ .map { selection -> selection.affordanceId }
+ .toSet()
+ val selectedAffordances =
+ affordances.filter { affordance ->
+ selectedAffordanceIds.contains(affordance.id)
+ }
+ val isSelected = selectedSlotId == slot.id
+ slot.id to
+ KeyguardQuickAffordanceSlotViewModel(
+ name = getSlotName(slot.id),
+ isSelected = isSelected,
+ selectedQuickAffordances =
+ selectedAffordances.map { affordanceModel ->
+ OptionItemViewModel<Icon>(
+ key =
+ MutableStateFlow("${slot.id}::${affordanceModel.id}")
+ as StateFlow<String>,
+ payload =
+ Icon.Loaded(
+ drawable =
+ getAffordanceIcon(affordanceModel.iconResourceId),
+ contentDescription =
+ Text.Loaded(getSlotContentDescription(slot.id)),
+ ),
+ text = Text.Loaded(affordanceModel.name),
+ isSelected = MutableStateFlow(true) as StateFlow<Boolean>,
+ onClicked = flowOf(null),
+ onLongClicked = null,
+ isEnabled = true,
+ )
+ },
+ maxSelectedQuickAffordances = slot.maxSelectedQuickAffordances,
+ onClicked =
+ if (isSelected) {
+ null
+ } else {
+ { _selectedSlotId.tryEmit(slot.id) }
+ },
+ )
+ }
+ }
+
+ /**
+ * The set of IDs of the currently-selected affordances. These change with user selection of new
+ * or different affordances in the currently-selected slot or when slot selection changes.
+ */
+ private val selectedAffordanceIds: Flow<Set<String>> =
+ combine(
+ quickAffordanceInteractor.selections,
+ selectedSlotId,
+ ) { selections, selectedSlotId ->
+ selections
+ .filter { selection -> selection.slotId == selectedSlotId }
+ .map { selection -> selection.affordanceId }
+ .toSet()
+ }
+ .shareIn(
+ scope = viewModelScope,
+ started = SharingStarted.WhileSubscribed(),
+ replay = 1,
+ )
+
+ /** The list of all available quick affordances for the selected slot. */
+ val quickAffordances: Flow<List<OptionItemViewModel<Icon>>> =
+ quickAffordanceInteractor.affordances.map { affordances ->
+ val isNoneSelected = selectedAffordanceIds.map { it.isEmpty() }.stateIn(viewModelScope)
+ listOf(
+ none(
+ slotId = selectedSlotId,
+ isSelected = isNoneSelected,
+ onSelected =
+ combine(
+ isNoneSelected,
+ selectedSlotId,
+ ) { isSelected, selectedSlotId ->
+ if (!isSelected) {
+ {
+ viewModelScope.launch {
+ quickAffordanceInteractor.unselectAllFromSlot(
+ selectedSlotId
+ )
+ logger.logShortcutApplied(
+ shortcut = "none",
+ shortcutSlotId = selectedSlotId,
+ )
+ }
+ }
+ } else {
+ null
+ }
+ }
+ )
+ ) +
+ affordances.map { affordance ->
+ val affordanceIcon = getAffordanceIcon(affordance.iconResourceId)
+ val isSelectedFlow: StateFlow<Boolean> =
+ selectedAffordanceIds
+ .map { it.contains(affordance.id) }
+ .stateIn(viewModelScope)
+ OptionItemViewModel<Icon>(
+ key =
+ selectedSlotId
+ .map { slotId -> "$slotId::${affordance.id}" }
+ .stateIn(viewModelScope),
+ payload = Icon.Loaded(drawable = affordanceIcon, contentDescription = null),
+ text = Text.Loaded(affordance.name),
+ isSelected = isSelectedFlow,
+ onClicked =
+ if (affordance.isEnabled) {
+ combine(
+ isSelectedFlow,
+ selectedSlotId,
+ ) { isSelected, selectedSlotId ->
+ if (!isSelected) {
+ {
+ viewModelScope.launch {
+ quickAffordanceInteractor.select(
+ slotId = selectedSlotId,
+ affordanceId = affordance.id,
+ )
+ logger.logShortcutApplied(
+ shortcut = affordance.id,
+ shortcutSlotId = selectedSlotId,
+ )
+ }
+ }
+ } else {
+ null
+ }
+ }
+ } else {
+ flowOf {
+ showEnablementDialog(
+ icon = affordanceIcon,
+ name = affordance.name,
+ explanation = affordance.enablementExplanation,
+ actionText = affordance.enablementActionText,
+ actionIntent = affordance.enablementActionIntent,
+ )
+ }
+ },
+ onLongClicked =
+ if (affordance.configureIntent != null) {
+ { requestActivityStart(affordance.configureIntent) }
+ } else {
+ null
+ },
+ isEnabled = affordance.isEnabled,
+ )
+ }
+ }
+
+ @SuppressLint("UseCompatLoadingForDrawables")
+ val summary: Flow<KeyguardQuickAffordanceSummaryViewModel> =
+ slots.map { slots ->
+ val icon2 =
+ (slots[KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END]
+ ?.selectedQuickAffordances
+ ?.firstOrNull())
+ ?.payload
+ val icon1 =
+ (slots[KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START]
+ ?.selectedQuickAffordances
+ ?.firstOrNull())
+ ?.payload
+
+ KeyguardQuickAffordanceSummaryViewModel(
+ description = toDescriptionText(applicationContext, slots),
+ icon1 =
+ icon1
+ ?: if (icon2 == null) {
+ Icon.Resource(
+ res = R.drawable.link_off,
+ contentDescription = null,
+ )
+ } else {
+ null
+ },
+ icon2 = icon2,
+ )
+ }
+
+ private val _dialog = MutableStateFlow<DialogViewModel?>(null)
+ /**
+ * The current dialog to show. If `null`, no dialog should be shown.
+ *
+ * When the dialog is dismissed, [onDialogDismissed] must be called.
+ */
+ val dialog: Flow<DialogViewModel?> = _dialog.asStateFlow()
+
+ private val _activityStartRequests = MutableStateFlow<Intent?>(null)
+ /**
+ * Requests to start an activity with the given [Intent].
+ *
+ * Important: once the activity is started, the [Intent] should be consumed by calling
+ * [onActivityStarted].
+ */
+ val activityStartRequests: StateFlow<Intent?> = _activityStartRequests.asStateFlow()
+
+ /** Notifies that the dialog has been dismissed in the UI. */
+ fun onDialogDismissed() {
+ _dialog.value = null
+ }
+
+ /**
+ * Notifies that an activity request from [activityStartRequests] has been fulfilled (e.g. the
+ * activity was started and the view-model can forget needing to start this activity).
+ */
+ fun onActivityStarted() {
+ _activityStartRequests.value = null
+ }
+
+ private fun requestActivityStart(
+ intent: Intent,
+ ) {
+ _activityStartRequests.value = intent
+ }
+
+ private fun showEnablementDialog(
+ icon: Drawable,
+ name: String,
+ explanation: String,
+ actionText: String?,
+ actionIntent: Intent?,
+ ) {
+ _dialog.value =
+ DialogViewModel(
+ icon =
+ Icon.Loaded(
+ drawable = icon,
+ contentDescription = null,
+ ),
+ headline = Text.Resource(R.string.keyguard_affordance_enablement_dialog_headline),
+ message = Text.Loaded(explanation),
+ buttons =
+ buildList {
+ add(
+ ButtonViewModel(
+ text =
+ Text.Resource(
+ if (actionText != null) {
+ // This is not the only button on the dialog.
+ R.string.cancel
+ } else {
+ // This is the only button on the dialog.
+ R.string
+ .keyguard_affordance_enablement_dialog_dismiss_button
+ }
+ ),
+ style = ButtonStyle.Secondary,
+ ),
+ )
+
+ if (actionText != null) {
+ add(
+ ButtonViewModel(
+ text = Text.Loaded(actionText),
+ style = ButtonStyle.Primary,
+ onClicked = {
+ actionIntent?.let { intent -> requestActivityStart(intent) }
+ }
+ ),
+ )
+ }
+ },
+ )
+ }
+
+ /** Returns a view-model for the special "None" option. */
+ @SuppressLint("UseCompatLoadingForDrawables")
+ private suspend fun none(
+ slotId: StateFlow<String>,
+ isSelected: StateFlow<Boolean>,
+ onSelected: Flow<(() -> Unit)?>,
+ ): OptionItemViewModel<Icon> {
+ return OptionItemViewModel<Icon>(
+ key = slotId.map { "$it::none" }.stateIn(viewModelScope),
+ payload = Icon.Resource(res = R.drawable.link_off, contentDescription = null),
+ text = Text.Resource(res = R.string.keyguard_affordance_none),
+ isSelected = isSelected,
+ onClicked = onSelected,
+ onLongClicked = null,
+ isEnabled = true,
+ )
+ }
+
+ private fun getSlotName(slotId: String): String {
+ return applicationContext.getString(
+ when (slotId) {
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ->
+ R.string.keyguard_slot_name_bottom_start
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END ->
+ R.string.keyguard_slot_name_bottom_end
+ else -> error("No name for slot with ID of \"$slotId\"!")
+ }
+ )
+ }
+
+ private fun getSlotContentDescription(slotId: String): String {
+ return applicationContext.getString(
+ when (slotId) {
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ->
+ R.string.keyguard_slot_name_bottom_start
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END ->
+ R.string.keyguard_slot_name_bottom_end
+ else -> error("No accessibility label for slot with ID \"$slotId\"!")
+ }
+ )
+ }
+
+ private suspend fun getAffordanceIcon(@DrawableRes iconResourceId: Int): Drawable {
+ return quickAffordanceInteractor.getAffordanceIcon(iconResourceId)
+ }
+
+ private fun toDescriptionText(
+ context: Context,
+ slots: Map<String, KeyguardQuickAffordanceSlotViewModel>,
+ ): Text {
+ val bottomStartAffordanceName =
+ slots[KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START]
+ ?.selectedQuickAffordances
+ ?.firstOrNull()
+ ?.text
+ val bottomEndAffordanceName =
+ slots[KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END]
+ ?.selectedQuickAffordances
+ ?.firstOrNull()
+ ?.text
+
+ return when {
+ bottomStartAffordanceName != null && bottomEndAffordanceName != null -> {
+ Text.Loaded(
+ context.getString(
+ R.string.keyguard_quick_affordance_two_selected_template,
+ bottomStartAffordanceName.asString(context),
+ bottomEndAffordanceName.asString(context),
+ )
+ )
+ }
+ bottomStartAffordanceName != null -> bottomStartAffordanceName
+ bottomEndAffordanceName != null -> bottomEndAffordanceName
+ else -> Text.Resource(R.string.keyguard_quick_affordance_none_selected)
+ }
+ }
+
+ @ViewModelScoped
+ @AssistedFactory
+ interface Factory {
+ fun create(viewModelScope: CoroutineScope): KeyguardQuickAffordancePickerViewModel2
+ }
+}
diff --git a/src/com/android/wallpaper/customization/ui/viewmodel/ThemePickerCustomizationOptionsViewModel.kt b/src/com/android/wallpaper/customization/ui/viewmodel/ThemePickerCustomizationOptionsViewModel.kt
new file mode 100644
index 0000000..bc0366a
--- /dev/null
+++ b/src/com/android/wallpaper/customization/ui/viewmodel/ThemePickerCustomizationOptionsViewModel.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.customization.ui.viewmodel
+
+import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil
+import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationOptionsViewModel
+import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationOptionsViewModelFactory
+import com.android.wallpaper.picker.customization.ui.viewmodel.DefaultCustomizationOptionsViewModel
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import dagger.hilt.android.scopes.ViewModelScoped
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+class ThemePickerCustomizationOptionsViewModel
+@AssistedInject
+constructor(
+ defaultCustomizationOptionsViewModelFactory: DefaultCustomizationOptionsViewModel.Factory,
+ keyguardQuickAffordancePickerViewModel2Factory: KeyguardQuickAffordancePickerViewModel2.Factory,
+ colorPickerViewModel2Factory: ColorPickerViewModel2.Factory,
+ @Assisted private val viewModelScope: CoroutineScope,
+) : CustomizationOptionsViewModel {
+
+ private val defaultCustomizationOptionsViewModel =
+ defaultCustomizationOptionsViewModelFactory.create(viewModelScope)
+
+ val keyguardQuickAffordancePickerViewModel2 =
+ keyguardQuickAffordancePickerViewModel2Factory.create(viewModelScope = viewModelScope)
+ val colorPickerViewModel2 = colorPickerViewModel2Factory.create(viewModelScope = viewModelScope)
+
+ override val selectedOption = defaultCustomizationOptionsViewModel.selectedOption
+
+ override fun deselectOption(): Boolean = defaultCustomizationOptionsViewModel.deselectOption()
+
+ val onCustomizeClockClicked: Flow<(() -> Unit)?> =
+ selectedOption.map {
+ if (it == null) {
+ {
+ defaultCustomizationOptionsViewModel.selectOption(
+ ThemePickerCustomizationOptionUtil.ThemePickerLockCustomizationOption.CLOCK
+ )
+ }
+ } else {
+ null
+ }
+ }
+
+ val onCustomizeShortcutClicked: Flow<(() -> Unit)?> =
+ selectedOption.map {
+ if (it == null) {
+ {
+ defaultCustomizationOptionsViewModel.selectOption(
+ ThemePickerCustomizationOptionUtil.ThemePickerLockCustomizationOption
+ .SHORTCUTS
+ )
+ }
+ } else {
+ null
+ }
+ }
+
+ val onCustomizeColorsClicked: Flow<(() -> Unit)?> =
+ selectedOption.map {
+ if (it == null) {
+ {
+ defaultCustomizationOptionsViewModel.selectOption(
+ ThemePickerCustomizationOptionUtil.ThemePickerHomeCustomizationOption.COLORS
+ )
+ }
+ } else {
+ null
+ }
+ }
+
+ @ViewModelScoped
+ @AssistedFactory
+ interface Factory : CustomizationOptionsViewModelFactory {
+ override fun create(
+ viewModelScope: CoroutineScope
+ ): ThemePickerCustomizationOptionsViewModel
+ }
+}
diff --git a/src_override/com/android/wallpaper/module/AppModule.kt b/src_override/com/android/wallpaper/module/AppModule.kt
deleted file mode 100644
index 8de80d6..0000000
--- a/src_override/com/android/wallpaper/module/AppModule.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2023 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.wallpaper.module
-
-import android.content.Context
-import com.android.customization.model.color.ColorCustomizationManager
-import com.android.customization.model.theme.OverlayManagerCompat
-import com.android.customization.module.CustomizationInjector
-import com.android.customization.module.DefaultCustomizationPreferences
-import com.android.customization.module.ThemePickerInjector
-import com.android.customization.module.logging.ThemesUserEventLogger
-import com.android.customization.module.logging.ThemesUserEventLoggerImpl
-import com.android.wallpaper.module.logging.UserEventLogger
-import com.android.wallpaper.picker.preview.data.util.DefaultLiveWallpaperDownloader
-import com.android.wallpaper.picker.preview.data.util.LiveWallpaperDownloader
-import com.android.wallpaper.util.converter.DefaultWallpaperModelFactory
-import com.android.wallpaper.util.converter.WallpaperModelFactory
-import dagger.Binds
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.android.qualifiers.ApplicationContext
-import dagger.hilt.components.SingletonComponent
-import javax.inject.Singleton
-
-@Module
-@InstallIn(SingletonComponent::class)
-abstract class AppModule {
- @Binds @Singleton abstract fun bindInjector(impl: ThemePickerInjector): CustomizationInjector
-
- @Binds
- @Singleton
- abstract fun bindUserEventLogger(impl: ThemesUserEventLoggerImpl): UserEventLogger
-
- @Binds
- @Singleton
- abstract fun bindThemesUserEventLogger(impl: ThemesUserEventLoggerImpl): ThemesUserEventLogger
-
- @Binds
- @Singleton
- abstract fun bindWallpaperModelFactory(
- impl: DefaultWallpaperModelFactory
- ): WallpaperModelFactory
-
- @Binds
- @Singleton
- abstract fun bindLiveWallpaperDownloader(
- impl: DefaultLiveWallpaperDownloader
- ): LiveWallpaperDownloader
-
- companion object {
- @Provides
- @Singleton
- fun provideWallpaperPreferences(
- @ApplicationContext context: Context
- ): WallpaperPreferences {
- return DefaultCustomizationPreferences(context)
- }
-
- @Provides
- @Singleton
- fun provideColorCustomizationManager(
- @ApplicationContext context: Context
- ): ColorCustomizationManager {
- return ColorCustomizationManager.getInstance(context, OverlayManagerCompat(context))
- }
- }
-}
diff --git a/src_override/com/android/wallpaper/modules/ThemePickerActivityModule.kt b/src_override/com/android/wallpaper/modules/ThemePickerActivityModule.kt
new file mode 100644
index 0000000..90a0e3b
--- /dev/null
+++ b/src_override/com/android/wallpaper/modules/ThemePickerActivityModule.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.modules
+
+import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil
+import com.android.wallpaper.picker.customization.ui.util.CustomizationOptionUtil
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
+import dagger.hilt.android.scopes.ActivityScoped
+
+@Module
+@InstallIn(ActivityComponent::class)
+abstract class ThemePickerActivityModule {
+
+ @Binds
+ @ActivityScoped
+ abstract fun bindCustomizationOptionUtil(
+ impl: ThemePickerCustomizationOptionUtil
+ ): CustomizationOptionUtil
+}
diff --git a/src_override/com/android/wallpaper/modules/ThemePickerActivityRetainedModule.kt b/src_override/com/android/wallpaper/modules/ThemePickerActivityRetainedModule.kt
new file mode 100644
index 0000000..9462c6a
--- /dev/null
+++ b/src_override/com/android/wallpaper/modules/ThemePickerActivityRetainedModule.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.modules
+
+import com.android.wallpaper.picker.preview.data.util.DefaultLiveWallpaperDownloader
+import com.android.wallpaper.picker.preview.data.util.LiveWallpaperDownloader
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityRetainedComponent
+import dagger.hilt.android.scopes.ActivityRetainedScoped
+
+@Module
+@InstallIn(ActivityRetainedComponent::class)
+abstract class ThemePickerActivityRetainedModule {
+
+ @Binds
+ @ActivityRetainedScoped
+ abstract fun bindLiveWallpaperDownloader(
+ impl: DefaultLiveWallpaperDownloader
+ ): LiveWallpaperDownloader
+}
diff --git a/src_override/com/android/wallpaper/modules/ThemePickerAppModule.kt b/src_override/com/android/wallpaper/modules/ThemePickerAppModule.kt
new file mode 100644
index 0000000..271f925
--- /dev/null
+++ b/src_override/com/android/wallpaper/modules/ThemePickerAppModule.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 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.wallpaper.modules
+
+import android.content.Context
+import com.android.customization.model.color.ColorCustomizationManager
+import com.android.customization.model.theme.OverlayManagerCompat
+import com.android.customization.module.CustomizationInjector
+import com.android.customization.module.DefaultCustomizationPreferences
+import com.android.customization.module.ThemePickerInjector
+import com.android.customization.module.logging.ThemesUserEventLogger
+import com.android.customization.module.logging.ThemesUserEventLoggerImpl
+import com.android.customization.picker.color.data.repository.ColorPickerRepository
+import com.android.customization.picker.color.data.repository.ColorPickerRepositoryImpl
+import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
+import com.android.systemui.shared.customization.data.content.CustomizationProviderClientImpl
+import com.android.wallpaper.customization.ui.binder.ThemePickerCustomizationOptionsBinder
+import com.android.wallpaper.module.DefaultPartnerProvider
+import com.android.wallpaper.module.PartnerProvider
+import com.android.wallpaper.module.WallpaperPreferences
+import com.android.wallpaper.module.logging.UserEventLogger
+import com.android.wallpaper.picker.customization.ui.binder.CustomizationOptionsBinder
+import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
+import com.android.wallpaper.picker.preview.ui.util.DefaultImageEffectDialogUtil
+import com.android.wallpaper.picker.preview.ui.util.ImageEffectDialogUtil
+import com.android.wallpaper.util.converter.DefaultWallpaperModelFactory
+import com.android.wallpaper.util.converter.WallpaperModelFactory
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+import kotlinx.coroutines.CoroutineDispatcher
+
+@Module
+@InstallIn(SingletonComponent::class)
+abstract class ThemePickerAppModule {
+ @Binds @Singleton abstract fun bindInjector(impl: ThemePickerInjector): CustomizationInjector
+
+ @Binds
+ @Singleton
+ abstract fun bindUserEventLogger(impl: ThemesUserEventLoggerImpl): UserEventLogger
+
+ @Binds
+ @Singleton
+ abstract fun bindThemesUserEventLogger(impl: ThemesUserEventLoggerImpl): ThemesUserEventLogger
+
+ @Binds
+ @Singleton
+ abstract fun bindWallpaperModelFactory(
+ impl: DefaultWallpaperModelFactory
+ ): WallpaperModelFactory
+
+ @Binds
+ @Singleton
+ abstract fun bindPartnerProvider(impl: DefaultPartnerProvider): PartnerProvider
+
+ @Binds
+ @Singleton
+ abstract fun bindEffectsWallpaperDialogUtil(
+ impl: DefaultImageEffectDialogUtil
+ ): ImageEffectDialogUtil
+
+ @Binds
+ @Singleton
+ abstract fun bindCustomizationOptionsBinder(
+ impl: ThemePickerCustomizationOptionsBinder
+ ): CustomizationOptionsBinder
+
+ @Binds
+ @Singleton
+ abstract fun bindColorPickerRepository(impl: ColorPickerRepositoryImpl): ColorPickerRepository
+
+ @Binds
+ @Singleton
+ abstract fun bindWallpaperPreferences(
+ impl: DefaultCustomizationPreferences
+ ): WallpaperPreferences
+
+ companion object {
+
+ @Provides
+ @Singleton
+ fun provideColorCustomizationManager(
+ @ApplicationContext context: Context
+ ): ColorCustomizationManager {
+ return ColorCustomizationManager.getInstance(context, OverlayManagerCompat(context))
+ }
+
+ @Provides
+ @Singleton
+ fun provideCustomizationProviderClient(
+ @ApplicationContext context: Context,
+ @BackgroundDispatcher bgDispatcher: CoroutineDispatcher,
+ ): CustomizationProviderClient {
+ return CustomizationProviderClientImpl(context, bgDispatcher)
+ }
+ }
+}
diff --git a/src_override/com/android/wallpaper/modules/ThemePickerViewModelModule.kt b/src_override/com/android/wallpaper/modules/ThemePickerViewModelModule.kt
new file mode 100644
index 0000000..3a2da15
--- /dev/null
+++ b/src_override/com/android/wallpaper/modules/ThemePickerViewModelModule.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.modules
+
+import com.android.wallpaper.customization.ui.viewmodel.ThemePickerCustomizationOptionsViewModel
+import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationOptionsViewModelFactory
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ViewModelComponent
+import dagger.hilt.android.scopes.ViewModelScoped
+
+@Module
+@InstallIn(ViewModelComponent::class)
+abstract class ThemePickerViewModelModule {
+
+ @Binds
+ @ViewModelScoped
+ abstract fun bindCustomizationOptionsViewModelFactory(
+ impl: ThemePickerCustomizationOptionsViewModel.Factory
+ ): CustomizationOptionsViewModelFactory
+}
diff --git a/src_override/com/android/wallpaper/picker/di/modules/EffectsModule.kt b/src_override/com/android/wallpaper/picker/di/modules/EffectsModule.kt
index f49a273..4fc0fbb 100644
--- a/src_override/com/android/wallpaper/picker/di/modules/EffectsModule.kt
+++ b/src_override/com/android/wallpaper/picker/di/modules/EffectsModule.kt
@@ -26,7 +26,7 @@
/** This class provides the singleton scoped effects controller for wallpaper picker. */
@InstallIn(SingletonComponent::class)
@Module
-internal abstract class EffectsModule {
+abstract class EffectsModule {
@Binds
@Singleton
diff --git a/src_override/com/android/wallpaper/picker/di/modules/InteractorModule.kt b/src_override/com/android/wallpaper/picker/di/modules/InteractorModule.kt
deleted file mode 100644
index 81edb2f..0000000
--- a/src_override/com/android/wallpaper/picker/di/modules/InteractorModule.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2023 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.wallpaper.picker.di.modules
-
-import android.text.TextUtils
-import com.android.customization.model.color.ColorCustomizationManager
-import com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_PRESET
-import com.android.wallpaper.picker.customization.data.repository.WallpaperRepository
-import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.components.SingletonComponent
-import javax.inject.Singleton
-
-/** This class provides the singleton scoped interactors for theme picker. */
-@InstallIn(SingletonComponent::class)
-@Module
-internal object InteractorModule {
-
- @Provides
- @Singleton
- fun provideWallpaperInteractor(
- wallpaperRepository: WallpaperRepository,
- colorCustomizationManager: ColorCustomizationManager,
- ): WallpaperInteractor {
- return WallpaperInteractor(wallpaperRepository) {
- TextUtils.equals(colorCustomizationManager.currentColorSource, COLOR_SOURCE_PRESET)
- }
- }
-}
diff --git a/tests/Android.bp b/tests/Android.bp
index 690a1b6..5b12a4a 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -41,13 +41,13 @@
srcs: [
":ThemePickerTests_srcs",
":WallpaperPicker2Tests_srcs",
- "module/src/com/android/customization/TestModule.kt",
],
exclude_srcs: [":ThemePicker_src_prod"],
static_libs: [
"WallpaperPicker2TestLib",
"WallpaperPicker2TestRunner",
"ThemePickerTestLib",
+ "ThemePickerTestModule",
"SystemUICustomizationTestUtils",
"androidx.test.espresso.core",
"androidx.test.espresso.contrib",
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index 06c3834..40b0a27 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -23,6 +23,7 @@
android_library {
name: "ThemePickerTestLib",
+ defaults: ["ThemePicker_defaults"],
srcs: [
"src/**/*.java",
"src/**/*.kt",
diff --git a/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt b/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt
index caa5029..c0ae6f0 100644
--- a/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt
+++ b/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt
@@ -12,7 +12,6 @@
import com.android.customization.picker.clock.ui.view.ClockViewFactory
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
-import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
import com.android.customization.picker.color.ui.viewmodel.ColorPickerViewModel
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
import com.android.systemui.shared.clocks.ClockRegistry
@@ -58,17 +57,7 @@
throw UnsupportedOperationException("not implemented")
}
- override fun getColorPickerInteractor(
- context: Context,
- wallpaperColorsRepository: WallpaperColorsRepository,
- ): ColorPickerInteractor {
- throw UnsupportedOperationException("not implemented")
- }
-
- override fun getColorPickerViewModelFactory(
- context: Context,
- wallpaperColorsRepository: WallpaperColorsRepository,
- ): ColorPickerViewModel.Factory {
+ override fun getColorPickerViewModelFactory(context: Context): ColorPickerViewModel.Factory {
throw UnsupportedOperationException("not implemented")
}
diff --git a/tests/module/Android.bp b/tests/module/Android.bp
new file mode 100644
index 0000000..f865832
--- /dev/null
+++ b/tests/module/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2024 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_library {
+ name: "ThemePickerTestModule",
+ defaults: ["ThemePicker_defaults_with_overrides"],
+ srcs: ["src/com/android/wallpaper/ThemePickerTestModule.kt"],
+ static_libs: [
+ "ThemePickerTestLib",
+ "hilt_android",
+ "hilt_android_testing",
+ ],
+
+ platform_apis: true,
+}
diff --git a/tests/module/AndroidManifest.xml b/tests/module/AndroidManifest.xml
new file mode 100644
index 0000000..67ae9de
--- /dev/null
+++ b/tests/module/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.wallpaper">
+
+ <application />
+</manifest>
diff --git a/tests/module/src/com/android/customization/TestModule.kt b/tests/module/src/com/android/customization/TestModule.kt
deleted file mode 100644
index 4600434..0000000
--- a/tests/module/src/com/android/customization/TestModule.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.android.customization
-
-import androidx.test.core.app.ApplicationProvider
-import com.android.customization.model.color.ColorCustomizationManager
-import com.android.customization.model.theme.OverlayManagerCompat
-import com.android.customization.module.CustomizationInjector
-import com.android.customization.module.CustomizationPreferences
-import com.android.customization.module.logging.TestThemesUserEventLogger
-import com.android.customization.module.logging.ThemesUserEventLogger
-import com.android.customization.testing.TestCustomizationInjector
-import com.android.customization.testing.TestDefaultCustomizationPreferences
-import com.android.wallpaper.module.AppModule
-import com.android.wallpaper.module.Injector
-import com.android.wallpaper.module.WallpaperPreferences
-import com.android.wallpaper.module.logging.TestUserEventLogger
-import com.android.wallpaper.module.logging.UserEventLogger
-import com.android.wallpaper.picker.preview.data.util.DefaultLiveWallpaperDownloader
-import com.android.wallpaper.picker.preview.data.util.LiveWallpaperDownloader
-import com.android.wallpaper.testing.TestInjector
-import com.android.wallpaper.testing.TestWallpaperPreferences
-import com.android.wallpaper.util.converter.DefaultWallpaperModelFactory
-import com.android.wallpaper.util.converter.WallpaperModelFactory
-import dagger.Binds
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.components.SingletonComponent
-import dagger.hilt.testing.TestInstallIn
-import javax.inject.Singleton
-
-@Module
-@TestInstallIn(components = [SingletonComponent::class], replaces = [AppModule::class])
-abstract class TestModule {
- //// WallpaperPicker2 prod
-
- @Binds @Singleton abstract fun bindInjector(impl: TestCustomizationInjector): Injector
-
- @Binds @Singleton abstract fun bindUserEventLogger(impl: TestUserEventLogger): UserEventLogger
-
- @Binds
- @Singleton
- abstract fun bindThemesUserEventLogger(impl: TestThemesUserEventLogger): ThemesUserEventLogger
-
- @Binds
- @Singleton
- abstract fun bindWallpaperPrefs(impl: TestDefaultCustomizationPreferences): WallpaperPreferences
-
- //// WallpaperPicker2 test
-
- @Binds @Singleton abstract fun bindTestInjector(impl: TestCustomizationInjector): TestInjector
-
- @Binds
- @Singleton
- abstract fun bindTestWallpaperPrefs(
- impl: TestDefaultCustomizationPreferences
- ): TestWallpaperPreferences
-
- //// ThemePicker prod
-
- @Binds
- @Singleton
- abstract fun bindCustomizationInjector(impl: TestCustomizationInjector): CustomizationInjector
-
- @Binds
- @Singleton
- abstract fun bindCustomizationPrefs(
- impl: TestDefaultCustomizationPreferences
- ): CustomizationPreferences
-
- @Binds
- @Singleton
- abstract fun bindWallpaperModelFactory(
- impl: DefaultWallpaperModelFactory
- ): WallpaperModelFactory
-
- @Binds
- @Singleton
- abstract fun bindLiveWallpaperDownloader(
- impl: DefaultLiveWallpaperDownloader
- ): LiveWallpaperDownloader
-
- companion object {
- @Provides
- @Singleton
- fun provideColorCustomizationManager(): ColorCustomizationManager {
- return ColorCustomizationManager.getInstance(
- ApplicationProvider.getApplicationContext(),
- OverlayManagerCompat(ApplicationProvider.getApplicationContext())
- )
- }
- }
-}
diff --git a/tests/module/src/com/android/wallpaper/ThemePickerTestModule.kt b/tests/module/src/com/android/wallpaper/ThemePickerTestModule.kt
new file mode 100644
index 0000000..4a484f3
--- /dev/null
+++ b/tests/module/src/com/android/wallpaper/ThemePickerTestModule.kt
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2024 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.wallpaper
+
+import android.content.Context
+import androidx.test.core.app.ApplicationProvider
+import com.android.customization.model.color.ColorCustomizationManager
+import com.android.customization.model.theme.OverlayManagerCompat
+import com.android.customization.module.CustomizationInjector
+import com.android.customization.module.CustomizationPreferences
+import com.android.customization.module.logging.TestThemesUserEventLogger
+import com.android.customization.module.logging.ThemesUserEventLogger
+import com.android.customization.picker.color.data.repository.ColorPickerRepository
+import com.android.customization.picker.color.data.repository.ColorPickerRepositoryImpl
+import com.android.customization.testing.TestCustomizationInjector
+import com.android.customization.testing.TestDefaultCustomizationPreferences
+import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
+import com.android.systemui.shared.customization.data.content.CustomizationProviderClientImpl
+import com.android.wallpaper.effects.EffectsController
+import com.android.wallpaper.effects.FakeEffectsController
+import com.android.wallpaper.module.Injector
+import com.android.wallpaper.module.PartnerProvider
+import com.android.wallpaper.module.WallpaperPreferences
+import com.android.wallpaper.module.logging.TestUserEventLogger
+import com.android.wallpaper.module.logging.UserEventLogger
+import com.android.wallpaper.modules.ThemePickerAppModule
+import com.android.wallpaper.network.Requester
+import com.android.wallpaper.picker.customization.ui.binder.CustomizationOptionsBinder
+import com.android.wallpaper.picker.customization.ui.binder.DefaultCustomizationOptionsBinder
+import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
+import com.android.wallpaper.picker.di.modules.EffectsModule
+import com.android.wallpaper.picker.preview.ui.util.DefaultImageEffectDialogUtil
+import com.android.wallpaper.picker.preview.ui.util.ImageEffectDialogUtil
+import com.android.wallpaper.testing.FakeDefaultRequester
+import com.android.wallpaper.testing.TestPartnerProvider
+import com.android.wallpaper.util.converter.DefaultWallpaperModelFactory
+import com.android.wallpaper.util.converter.WallpaperModelFactory
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import dagger.hilt.testing.TestInstallIn
+import javax.inject.Singleton
+import kotlinx.coroutines.CoroutineDispatcher
+
+@Module
+@TestInstallIn(
+ components = [SingletonComponent::class],
+ replaces = [EffectsModule::class, ThemePickerAppModule::class]
+)
+abstract class ThemePickerTestModule {
+ //// WallpaperPicker2 prod
+
+ @Binds @Singleton abstract fun bindInjector(impl: TestCustomizationInjector): Injector
+
+ @Binds @Singleton abstract fun bindUserEventLogger(impl: TestUserEventLogger): UserEventLogger
+
+ @Binds @Singleton abstract fun bindFakeRequester(impl: FakeDefaultRequester): Requester
+
+ @Binds
+ @Singleton
+ abstract fun bindThemesUserEventLogger(impl: TestThemesUserEventLogger): ThemesUserEventLogger
+
+ @Binds
+ @Singleton
+ abstract fun bindWallpaperPrefs(impl: TestDefaultCustomizationPreferences): WallpaperPreferences
+
+ //// ThemePicker prod
+
+ @Binds
+ @Singleton
+ abstract fun bindCustomizationInjector(impl: TestCustomizationInjector): CustomizationInjector
+
+ @Binds
+ @Singleton
+ abstract fun bindCustomizationPrefs(
+ impl: TestDefaultCustomizationPreferences
+ ): CustomizationPreferences
+
+ @Binds
+ @Singleton
+ abstract fun bindWallpaperModelFactory(
+ impl: DefaultWallpaperModelFactory
+ ): WallpaperModelFactory
+
+ @Binds
+ @Singleton
+ abstract fun providePartnerProvider(impl: TestPartnerProvider): PartnerProvider
+
+ @Binds
+ @Singleton
+ abstract fun bindEffectsWallpaperDialogUtil(
+ impl: DefaultImageEffectDialogUtil
+ ): ImageEffectDialogUtil
+
+ @Binds
+ @Singleton
+ abstract fun bindEffectsController(impl: FakeEffectsController): EffectsController
+
+ @Binds
+ @Singleton
+ abstract fun bindCustomizationOptionsBinder(
+ impl: DefaultCustomizationOptionsBinder
+ ): CustomizationOptionsBinder
+
+ @Binds
+ @Singleton
+ abstract fun bindColorPickerRepository(impl: ColorPickerRepositoryImpl): ColorPickerRepository
+
+ companion object {
+ @Provides
+ @Singleton
+ fun provideColorCustomizationManager(): ColorCustomizationManager {
+ return ColorCustomizationManager.getInstance(
+ ApplicationProvider.getApplicationContext(),
+ OverlayManagerCompat(ApplicationProvider.getApplicationContext())
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideCustomizationProviderClient(
+ @ApplicationContext context: Context,
+ @BackgroundDispatcher bgDispatcher: CoroutineDispatcher,
+ ): CustomizationProviderClient {
+ return CustomizationProviderClientImpl(context, bgDispatcher)
+ }
+ }
+}
diff --git a/tests/robotests/Android.bp b/tests/robotests/Android.bp
index 4fecaef..a4fd7f3 100644
--- a/tests/robotests/Android.bp
+++ b/tests/robotests/Android.bp
@@ -1,3 +1,4 @@
+
package {
default_team: "trendy_team_android_kernel",
default_applicable_licenses: ["Android-Apache-2.0"],
@@ -7,7 +8,11 @@
name: "ThemePickerShell",
defaults: ["ThemePicker_defaults"],
platform_apis: true,
- static_libs: ["ThemePickerTestLib"],
+ static_libs: [
+ "ThemePickerTestLib",
+ "ThemePickerTestModule",
+ "WallpaperPicker2RoboLib",
+ ],
}
android_robolectric_test {
@@ -27,6 +32,10 @@
"truth",
"SystemUICustomizationTestUtils",
"ThemePickerApplicationLib",
+ "mockito-robolectric-prebuilt",
+ "mockito-kotlin2",
+ "hilt_android",
+ "hilt_android_testing",
],
libs: [
@@ -37,4 +46,6 @@
upstream: true,
instrumentation_for: "ThemePickerShell",
+
+ strict_mode: false,
}
diff --git a/tests/robotests/config/robolectric.properties b/tests/robotests/config/robolectric.properties
index fab7251..62f25a7 100644
--- a/tests/robotests/config/robolectric.properties
+++ b/tests/robotests/config/robolectric.properties
@@ -1 +1,2 @@
sdk=NEWEST_SDK
+application = dagger.hilt.android.testing.HiltTestApplication
diff --git a/tests/robotests/module b/tests/robotests/module
new file mode 120000
index 0000000..ad3c990
--- /dev/null
+++ b/tests/robotests/module
@@ -0,0 +1 @@
+../module
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt b/tests/robotests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt
index e9f4683..0776cc8 100644
--- a/tests/robotests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt
+++ b/tests/robotests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt
@@ -32,6 +32,7 @@
import com.android.customization.picker.color.shared.model.ColorType
import com.android.systemui.monet.Style
import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
import org.json.JSONObject
import org.junit.Before
import org.junit.Rule
@@ -58,7 +59,13 @@
fun setUp() {
MockitoAnnotations.initMocks(this)
val application = ApplicationProvider.getApplicationContext<Context>()
- manager = ColorCustomizationManager(provider, application.contentResolver, mockOM)
+ manager =
+ ColorCustomizationManager(
+ provider,
+ application.contentResolver,
+ mockOM,
+ MoreExecutors.newDirectExecutorService()
+ )
}
@Test
@@ -103,8 +110,6 @@
}
)
- Thread.sleep(100)
-
val overlaysJson = JSONObject(manager.storedOverlays)
assertThat(overlaysJson.getString(OVERLAY_COLOR_INDEX)).isEqualTo(value)
@@ -126,8 +131,6 @@
}
)
- Thread.sleep(100)
-
val overlaysJson = JSONObject(manager.storedOverlays)
assertThat(overlaysJson.getString(OVERLAY_COLOR_INDEX)).isEqualTo(value)
}
@@ -171,8 +174,6 @@
}
)
- Thread.sleep(100)
-
val overlaysJson = JSONObject(manager.storedOverlays)
assertThat(overlaysJson.getString(OVERLAY_COLOR_BOTH)).isEqualTo("1")
}
@@ -191,8 +192,6 @@
}
)
- Thread.sleep(100)
-
val overlaysJson = JSONObject(manager.storedOverlays)
assertThat(overlaysJson.getString(OVERLAY_COLOR_BOTH)).isEqualTo("0")
}
diff --git a/tests/robotests/src/com/android/customization/model/notifications/domain/interactor/NotificationsSnapshotRestorerTest.kt b/tests/robotests/src/com/android/customization/model/notifications/domain/interactor/NotificationsSnapshotRestorerTest.kt
new file mode 100644
index 0000000..bf8cfda
--- /dev/null
+++ b/tests/robotests/src/com/android/customization/model/notifications/domain/interactor/NotificationsSnapshotRestorerTest.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2024 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.customization.model.notifications.domain.interactor
+
+import android.provider.Settings
+import androidx.test.filters.SmallTest
+import com.android.customization.picker.notifications.domain.interactor.NotificationsSnapshotRestorer
+import com.android.systemui.shared.notifications.data.repository.NotificationSettingsRepository
+import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor
+import com.android.systemui.shared.settings.data.repository.FakeSecureSettingsRepository
+import com.android.wallpaper.testing.FakeSnapshotStore
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(RobolectricTestRunner::class)
+class NotificationsSnapshotRestorerTest {
+
+ private lateinit var underTest: NotificationsSnapshotRestorer
+ private lateinit var fakeSecureSettingsRepository: FakeSecureSettingsRepository
+ private lateinit var interactor: NotificationSettingsInteractor
+
+ private lateinit var testScope: TestScope
+
+ @Before
+ fun setUp() {
+ val testDispatcher = StandardTestDispatcher()
+ Dispatchers.setMain(testDispatcher)
+ testScope = TestScope(testDispatcher)
+ fakeSecureSettingsRepository = FakeSecureSettingsRepository()
+ interactor =
+ NotificationSettingsInteractor(
+ repository =
+ NotificationSettingsRepository(
+ scope = testScope.backgroundScope,
+ backgroundDispatcher = testDispatcher,
+ secureSettingsRepository = fakeSecureSettingsRepository,
+ ),
+ )
+ underTest =
+ NotificationsSnapshotRestorer(
+ interactor = interactor,
+ backgroundScope = testScope.backgroundScope
+ )
+ }
+
+ @Test
+ fun setUpAndRestore_Active() =
+ testScope.runTest {
+ fakeSecureSettingsRepository.setInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1)
+ val showNotifs = collectLastValue(interactor.isShowNotificationsOnLockScreenEnabled())
+
+ val store = FakeSnapshotStore()
+ store.store(underTest.setUpSnapshotRestorer(store = store))
+ val initialSnapshot = store.retrieve()
+ underTest.restoreToSnapshot(snapshot = initialSnapshot)
+
+ assertThat(showNotifs()).isTrue()
+ }
+
+ @Test
+ fun setUpAndRestore_Inactive() =
+ testScope.runTest {
+ fakeSecureSettingsRepository.setInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0)
+ val showNotifs = collectLastValue(interactor.isShowNotificationsOnLockScreenEnabled())
+
+ val store = FakeSnapshotStore()
+ store.store(underTest.setUpSnapshotRestorer(store = store))
+ val initialSnapshot = store.retrieve()
+ underTest.restoreToSnapshot(snapshot = initialSnapshot)
+
+ assertThat(showNotifs()).isFalse()
+ }
+
+ @Test
+ fun setUp_deactivate_restoreToActive() = runTest {
+ fakeSecureSettingsRepository.setInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1)
+ val showNotifs = collectLastValue(interactor.isShowNotificationsOnLockScreenEnabled())
+ val store = FakeSnapshotStore()
+ store.store(underTest.setUpSnapshotRestorer(store = store))
+ val initialSnapshot = store.retrieve()
+
+ fakeSecureSettingsRepository.setInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0)
+ underTest.restoreToSnapshot(snapshot = initialSnapshot)
+
+ assertThat(showNotifs()).isTrue()
+ }
+
+ @Test
+ fun setUp_activate_restoreToInactive() = runTest {
+ fakeSecureSettingsRepository.setInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0)
+ val showNotifs = collectLastValue(interactor.isShowNotificationsOnLockScreenEnabled())
+ val store = FakeSnapshotStore()
+ store.store(underTest.setUpSnapshotRestorer(store = store))
+ val initialSnapshot = store.retrieve()
+
+ fakeSecureSettingsRepository.setInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1)
+ underTest.restoreToSnapshot(snapshot = initialSnapshot)
+
+ assertThat(showNotifs()).isFalse()
+ }
+}
diff --git a/tests/robotests/src/com/android/customization/model/picker/color/domain/interactor/ColorPickerInteractorTest.kt b/tests/robotests/src/com/android/customization/model/picker/color/domain/interactor/ColorPickerInteractorTest.kt
index d4f24ee..97d4a9a 100644
--- a/tests/robotests/src/com/android/customization/model/picker/color/domain/interactor/ColorPickerInteractorTest.kt
+++ b/tests/robotests/src/com/android/customization/model/picker/color/domain/interactor/ColorPickerInteractorTest.kt
@@ -52,11 +52,10 @@
underTest =
ColorPickerInteractor(
repository = repository,
- snapshotRestorer = {
- ColorPickerSnapshotRestorer(interactor = underTest).apply {
+ snapshotRestorer =
+ ColorPickerSnapshotRestorer(repository = repository).apply {
runBlocking { setUpSnapshotRestorer(store = store) }
- }
- },
+ },
)
repository.setOptions(4, 4, ColorType.WALLPAPER_COLOR, 0)
}
diff --git a/tests/robotests/src/com/android/customization/model/picker/color/domain/interactor/ColorPickerSnapshotRestorerTest.kt b/tests/robotests/src/com/android/customization/model/picker/color/domain/interactor/ColorPickerSnapshotRestorerTest.kt
index 5f3e39e..b050237 100644
--- a/tests/robotests/src/com/android/customization/model/picker/color/domain/interactor/ColorPickerSnapshotRestorerTest.kt
+++ b/tests/robotests/src/com/android/customization/model/picker/color/domain/interactor/ColorPickerSnapshotRestorerTest.kt
@@ -21,7 +21,6 @@
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.customization.picker.color.data.repository.FakeColorPickerRepository
-import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
import com.android.customization.picker.color.domain.interactor.ColorPickerSnapshotRestorer
import com.android.customization.picker.color.shared.model.ColorOptionModel
import com.android.customization.picker.color.shared.model.ColorType
@@ -51,14 +50,7 @@
fun setUp() {
context = InstrumentationRegistry.getInstrumentation().targetContext
repository = FakeColorPickerRepository(context = context)
- underTest =
- ColorPickerSnapshotRestorer(
- interactor =
- ColorPickerInteractor(
- repository = repository,
- snapshotRestorer = { underTest },
- )
- )
+ underTest = ColorPickerSnapshotRestorer(repository = repository)
store = FakeSnapshotStore()
}
diff --git a/tests/robotests/src/com/android/customization/model/picker/color/ui/viewmodel/ColorPickerViewModelTest.kt b/tests/robotests/src/com/android/customization/model/picker/color/ui/viewmodel/ColorPickerViewModelTest.kt
index 889720e..f5878a4 100644
--- a/tests/robotests/src/com/android/customization/model/picker/color/ui/viewmodel/ColorPickerViewModelTest.kt
+++ b/tests/robotests/src/com/android/customization/model/picker/color/ui/viewmodel/ColorPickerViewModelTest.kt
@@ -76,11 +76,10 @@
interactor =
ColorPickerInteractor(
repository = repository,
- snapshotRestorer = {
- ColorPickerSnapshotRestorer(interactor = interactor).apply {
+ snapshotRestorer =
+ ColorPickerSnapshotRestorer(repository = repository).apply {
runBlocking { setUpSnapshotRestorer(store = store) }
- }
- },
+ },
)
underTest =
diff --git a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepositoryTest.kt b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepositoryTest.kt
index 8687b30..55fb2cb 100644
--- a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepositoryTest.kt
+++ b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepositoryTest.kt
@@ -53,7 +53,7 @@
underTest =
KeyguardQuickAffordancePickerRepository(
client = client,
- scope = testScope.backgroundScope,
+ mainScope = testScope.backgroundScope,
)
}
diff --git a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt
index 4b4790a..2b84ee4 100644
--- a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt
+++ b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt
@@ -24,12 +24,10 @@
import com.android.customization.picker.quickaffordance.shared.model.KeyguardQuickAffordancePickerSelectionModel
import com.android.systemui.shared.customization.data.content.FakeCustomizationProviderClient
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
-import com.android.wallpaper.testing.FakeSnapshotStore
import com.android.wallpaper.testing.collectLastValue
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.resetMain
@@ -62,16 +60,10 @@
repository =
KeyguardQuickAffordancePickerRepository(
client = client,
- scope = testScope.backgroundScope,
+ mainScope = testScope.backgroundScope,
),
client = client,
- snapshotRestorer = {
- KeyguardQuickAffordanceSnapshotRestorer(
- interactor = underTest,
- client = client,
- )
- .apply { runBlocking { setUpSnapshotRestorer(FakeSnapshotStore()) } }
- },
+ snapshotRestorer = KeyguardQuickAffordanceSnapshotRestorer(client),
)
}
diff --git a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt
index 53ade86..870d9f5 100644
--- a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt
+++ b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt
@@ -38,7 +38,6 @@
import com.android.wallpaper.picker.customization.data.repository.WallpaperRepository
import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
import com.android.wallpaper.picker.option.ui.viewmodel.OptionItemViewModel
-import com.android.wallpaper.testing.FakeSnapshotStore
import com.android.wallpaper.testing.FakeWallpaperClient
import com.android.wallpaper.testing.TestCurrentWallpaperInfoFactory
import com.android.wallpaper.testing.TestInjector
@@ -48,7 +47,6 @@
import com.google.common.truth.Truth.assertWithMessage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.resetMain
@@ -89,16 +87,10 @@
repository =
KeyguardQuickAffordancePickerRepository(
client = client,
- scope = testScope.backgroundScope,
+ mainScope = testScope.backgroundScope,
),
client = client,
- snapshotRestorer = {
- KeyguardQuickAffordanceSnapshotRestorer(
- interactor = quickAffordanceInteractor,
- client = client,
- )
- .apply { runBlocking { setUpSnapshotRestorer(FakeSnapshotStore()) } }
- },
+ snapshotRestorer = KeyguardQuickAffordanceSnapshotRestorer(client),
)
wallpaperInteractor =
WallpaperInteractor(
diff --git a/tests/robotests/src/com/android/customization/model/picker/settings/data/repository/ColorContrastSectionRepositoryTest.kt b/tests/robotests/src/com/android/customization/model/picker/settings/data/repository/ColorContrastSectionRepositoryTest.kt
new file mode 100644
index 0000000..cde597a
--- /dev/null
+++ b/tests/robotests/src/com/android/customization/model/picker/settings/data/repository/ColorContrastSectionRepositoryTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 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.customization.model.picker.settings.data.repository
+
+import androidx.test.filters.SmallTest
+import com.android.customization.picker.settings.data.repository.ColorContrastSectionRepository
+import com.android.wallpaper.testing.FakeUiModeManager
+import com.google.common.truth.Truth.assertThat
+import dagger.hilt.android.testing.HiltAndroidRule
+import dagger.hilt.android.testing.HiltAndroidTest
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.toList
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@HiltAndroidTest
+@SmallTest
+@RunWith(RobolectricTestRunner::class)
+@OptIn(ExperimentalCoroutinesApi::class)
+class ColorContrastSectionRepositoryTest {
+ @get:Rule var hiltRule = HiltAndroidRule(this)
+
+ @Inject lateinit var uiModeManager: FakeUiModeManager
+ @Inject lateinit var underTest: ColorContrastSectionRepository
+ @Inject lateinit var testScope: TestScope
+
+ @Before
+ fun setUp() {
+ hiltRule.inject()
+ }
+
+ @Test
+ fun creationSucceeds() {
+ assertThat(underTest).isNotNull()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun contrastFlowEmitsValues() =
+ testScope.runTest {
+ val nextContrastValues = listOf(0.5f, 0.7f, 0.8f)
+ // Set up a flow to collect all contrast values
+ val flowCollector = mutableListOf<Float>()
+ // Start collecting values from the flow, using an unconfined dispatcher to start
+ // collecting from the flow right away (rather than explicitly calling `runCurrent`)
+ // See https://developer.android.com/kotlin/flow/test#continuous-collection
+ backgroundScope.launch(UnconfinedTestDispatcher()) {
+ underTest.contrast.toList(flowCollector)
+ }
+
+ nextContrastValues.forEach { uiModeManager.setContrast(it) }
+
+ // Ignore the first contrast value from constructing the repository
+ val collectedValues = flowCollector.drop(1)
+ assertThat(collectedValues).containsExactlyElementsIn(nextContrastValues)
+ }
+}
diff --git a/tests/robotests/src/com/android/customization/model/picker/settings/domain/interactor/ColorContrastSectionInteractorTest.kt b/tests/robotests/src/com/android/customization/model/picker/settings/domain/interactor/ColorContrastSectionInteractorTest.kt
new file mode 100644
index 0000000..afa6427
--- /dev/null
+++ b/tests/robotests/src/com/android/customization/model/picker/settings/domain/interactor/ColorContrastSectionInteractorTest.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 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.customization.model.picker.settings.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.customization.picker.settings.domain.interactor.ColorContrastSectionInteractor
+import com.android.wallpaper.testing.FakeUiModeManager
+import com.google.common.truth.Truth.assertThat
+import dagger.hilt.android.testing.HiltAndroidRule
+import dagger.hilt.android.testing.HiltAndroidTest
+import javax.inject.Inject
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@SmallTest
+@HiltAndroidTest
+@RunWith(RobolectricTestRunner::class)
+class ColorContrastSectionInteractorTest {
+ @get:Rule var hiltRule = HiltAndroidRule(this)
+
+ @Inject lateinit var uiModeManager: FakeUiModeManager
+ @Inject lateinit var interactor: ColorContrastSectionInteractor
+
+ @Before
+ fun setUp() {
+ hiltRule.inject()
+ }
+
+ @Test
+ fun contrastEmitCorrectValuesFromRepository() = runTest {
+ val expectedContrast = 1.5f
+ uiModeManager.setContrast(expectedContrast)
+
+ val result = interactor.contrast.first()
+
+ assertThat(result).isEqualTo(expectedContrast)
+ }
+}
diff --git a/tests/robotests/src/com/android/customization/model/picker/settings/ui/viewmodel/ColorContrastSectionViewModelTest.kt b/tests/robotests/src/com/android/customization/model/picker/settings/ui/viewmodel/ColorContrastSectionViewModelTest.kt
new file mode 100644
index 0000000..0c420e0
--- /dev/null
+++ b/tests/robotests/src/com/android/customization/model/picker/settings/ui/viewmodel/ColorContrastSectionViewModelTest.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 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.customization.model.picker.settings.ui.viewmodel
+
+import com.android.customization.picker.settings.ui.viewmodel.ColorContrastSectionDataViewModel
+import com.android.customization.picker.settings.ui.viewmodel.ColorContrastSectionViewModel
+import com.android.themepicker.R
+import com.android.wallpaper.picker.common.icon.ui.viewmodel.Icon
+import com.android.wallpaper.picker.common.text.ui.viewmodel.Text
+import com.android.wallpaper.testing.FakeUiModeManager
+import dagger.hilt.android.testing.HiltAndroidRule
+import dagger.hilt.android.testing.HiltAndroidTest
+import javax.inject.Inject
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@HiltAndroidTest
+@RunWith(RobolectricTestRunner::class)
+class ColorContrastSectionViewModelTest {
+ @get:Rule var hiltRule = HiltAndroidRule(this)
+
+ private lateinit var viewModel: ColorContrastSectionViewModel
+
+ @Inject lateinit var testDispatcher: TestDispatcher
+ @Inject lateinit var uiModeManager: FakeUiModeManager
+ @Inject lateinit var viewModelFactory: ColorContrastSectionViewModel.Factory
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Before
+ fun setUp() {
+ hiltRule.inject()
+ Dispatchers.setMain(testDispatcher)
+ viewModel = viewModelFactory.create(ColorContrastSectionViewModel::class.java)
+ }
+
+ @Test
+ fun summaryEmitsCorrectDataValueForStandard() = runTest {
+ uiModeManager.setContrast(ColorContrastSectionViewModel.ContrastValue.STANDARD.value)
+ val expected =
+ ColorContrastSectionDataViewModel(
+ Text.Resource(R.string.color_contrast_default_title),
+ Icon.Resource(res = R.drawable.ic_contrast_standard, contentDescription = null)
+ )
+
+ val result = viewModel.summary.first()
+
+ assertEquals(expected, result)
+ }
+
+ @Test
+ fun summaryEmitsCorrectDataValueForMedium() = runTest {
+ uiModeManager.setContrast(ColorContrastSectionViewModel.ContrastValue.MEDIUM.value)
+ val expected =
+ ColorContrastSectionDataViewModel(
+ Text.Resource(R.string.color_contrast_medium_title),
+ Icon.Resource(res = R.drawable.ic_contrast_medium, contentDescription = null)
+ )
+
+ val result = viewModel.summary.first()
+
+ assertEquals(expected, result)
+ }
+
+ @Test
+ fun summaryEmitsCorrectDataValueForHigh() = runTest {
+ uiModeManager.setContrast(ColorContrastSectionViewModel.ContrastValue.HIGH.value)
+ val expected =
+ ColorContrastSectionDataViewModel(
+ Text.Resource(R.string.color_contrast_high_title),
+ Icon.Resource(res = R.drawable.ic_contrast_high, contentDescription = null)
+ )
+
+ val result = viewModel.summary.first()
+
+ assertEquals(expected, result)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun summaryThrowsIllegalArgumentExceptionForInvalidValue() = runTest {
+ uiModeManager.setContrast(999f)
+
+ viewModel.summary.collect() // This should throw an IllegalArgumentException
+ }
+}
diff --git a/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt b/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
index 6fe76b9..41192e7 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
@@ -39,6 +39,10 @@
override fun getController(clockId: String): ClockController = clockControllers.get(clockId)!!
+ override fun setReactiveTouchInteractionEnabled(clockId: String, enable: Boolean) {
+ TODO("Not yet implemented")
+ }
+
override fun getLargeView(clockId: String): View {
TODO("Not yet implemented")
}
diff --git a/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt b/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
index d3ae9cb..9d82fc1 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
@@ -70,14 +70,14 @@
}
},
)
+ val colorPickerRepository = FakeColorPickerRepository(context = context)
colorPickerInteractor =
ColorPickerInteractor(
- repository = FakeColorPickerRepository(context = context),
- snapshotRestorer = {
- ColorPickerSnapshotRestorer(interactor = colorPickerInteractor).apply {
+ repository = colorPickerRepository,
+ snapshotRestorer =
+ ColorPickerSnapshotRestorer(repository = colorPickerRepository).apply {
runBlocking { setUpSnapshotRestorer(store = FakeSnapshotStore()) }
- }
- },
+ },
)
underTest =
ClockSettingsViewModel.Factory(
diff --git a/tests/robotests/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModelTest.kt b/tests/robotests/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModelTest.kt
index 8966de5..e9f7ffd 100644
--- a/tests/robotests/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModelTest.kt
+++ b/tests/robotests/src/com/android/customization/picker/notifications/ui/viewmodel/NotificationSectionViewModelTest.kt
@@ -80,7 +80,7 @@
@Test
fun `toggles back and forth`() =
testScope.runTest {
- val isSwitchOn = collectLastValue(underTest.isSwitchOn)
+ val isSwitchOn = collectLastValue(underTest.isSwitchOn())
val initialIsSwitchOn = isSwitchOn()
diff --git a/tests/robotests/src/com/android/wallpaper/customization/ui/viewmodel/ColorPickerViewModel2Test.kt b/tests/robotests/src/com/android/wallpaper/customization/ui/viewmodel/ColorPickerViewModel2Test.kt
new file mode 100644
index 0000000..a43a7ce
--- /dev/null
+++ b/tests/robotests/src/com/android/wallpaper/customization/ui/viewmodel/ColorPickerViewModel2Test.kt
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2024 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.wallpaper.customization.ui.viewmodel
+
+import android.content.Context
+import android.graphics.Color
+import android.stats.style.StyleEnums
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.customization.model.color.ColorOptionsProvider
+import com.android.customization.module.logging.TestThemesUserEventLogger
+import com.android.customization.picker.color.data.repository.FakeColorPickerRepository
+import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
+import com.android.customization.picker.color.domain.interactor.ColorPickerSnapshotRestorer
+import com.android.customization.picker.color.shared.model.ColorType
+import com.android.customization.picker.color.ui.viewmodel.ColorOptionIconViewModel
+import com.android.customization.picker.color.ui.viewmodel.ColorTypeTabViewModel
+import com.android.systemui.monet.Style
+import com.android.wallpaper.picker.option.ui.viewmodel.OptionItemViewModel
+import com.android.wallpaper.testing.FakeSnapshotStore
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(RobolectricTestRunner::class)
+class ColorPickerViewModel2Test {
+ private val logger = TestThemesUserEventLogger()
+ private lateinit var underTest: ColorPickerViewModel2
+ private lateinit var repository: FakeColorPickerRepository
+ private lateinit var interactor: ColorPickerInteractor
+ private lateinit var store: FakeSnapshotStore
+
+ private lateinit var context: Context
+ private lateinit var testScope: TestScope
+
+ @Before
+ fun setUp() {
+ context = InstrumentationRegistry.getInstrumentation().targetContext
+ val testDispatcher = UnconfinedTestDispatcher()
+ Dispatchers.setMain(testDispatcher)
+ testScope = TestScope(testDispatcher)
+ repository = FakeColorPickerRepository(context = context)
+ store = FakeSnapshotStore()
+
+ interactor =
+ ColorPickerInteractor(
+ repository = repository,
+ snapshotRestorer =
+ ColorPickerSnapshotRestorer(repository = repository).apply {
+ runBlocking { setUpSnapshotRestorer(store = store) }
+ },
+ )
+
+ underTest =
+ ColorPickerViewModel2(
+ context = context,
+ interactor = interactor,
+ logger = logger,
+ viewModelScope = testScope.backgroundScope,
+ )
+
+ repository.setOptions(4, 4, ColorType.WALLPAPER_COLOR, 0)
+ }
+
+ @After
+ fun tearDown() {
+ Dispatchers.resetMain()
+ }
+
+ @Test
+ fun `Log selected wallpaper color`() =
+ testScope.runTest {
+ repository.setOptions(
+ listOf(
+ repository.buildWallpaperOption(
+ ColorOptionsProvider.COLOR_SOURCE_LOCK,
+ Style.EXPRESSIVE,
+ "121212"
+ )
+ ),
+ listOf(repository.buildPresetOption(Style.FRUIT_SALAD, "#ABCDEF")),
+ ColorType.PRESET_COLOR,
+ 0
+ )
+
+ val colorTypes = collectLastValue(underTest.colorTypeTabs)
+ val colorOptions = collectLastValue(underTest.colorOptions)
+
+ // Select "Wallpaper colors" tab
+ colorTypes()?.get(ColorType.WALLPAPER_COLOR)?.onClick?.invoke()
+ // Select a color option
+ selectColorOption(colorOptions, 0)
+
+ assertThat(logger.themeColorSource)
+ .isEqualTo(StyleEnums.COLOR_SOURCE_LOCK_SCREEN_WALLPAPER)
+ assertThat(logger.themeColorStyle).isEqualTo(Style.EXPRESSIVE.toString().hashCode())
+ assertThat(logger.themeSeedColor).isEqualTo(Color.parseColor("#121212"))
+ }
+
+ @Test
+ fun `Log selected preset color`() =
+ testScope.runTest {
+ repository.setOptions(
+ listOf(
+ repository.buildWallpaperOption(
+ ColorOptionsProvider.COLOR_SOURCE_LOCK,
+ Style.EXPRESSIVE,
+ "121212"
+ )
+ ),
+ listOf(repository.buildPresetOption(Style.FRUIT_SALAD, "#ABCDEF")),
+ ColorType.WALLPAPER_COLOR,
+ 0
+ )
+
+ val colorTypes = collectLastValue(underTest.colorTypeTabs)
+ val colorOptions = collectLastValue(underTest.colorOptions)
+
+ // Select "Wallpaper colors" tab
+ colorTypes()?.get(ColorType.PRESET_COLOR)?.onClick?.invoke()
+ // Select a color option
+ selectColorOption(colorOptions, 0)
+
+ assertThat(logger.themeColorSource).isEqualTo(StyleEnums.COLOR_SOURCE_PRESET_COLOR)
+ assertThat(logger.themeColorStyle).isEqualTo(Style.FRUIT_SALAD.toString().hashCode())
+ assertThat(logger.themeSeedColor).isEqualTo(Color.parseColor("#ABCDEF"))
+ }
+
+ @Test
+ fun `Select a preset color`() =
+ testScope.runTest {
+ val colorTypes = collectLastValue(underTest.colorTypeTabs)
+ val colorOptions = collectLastValue(underTest.colorOptions)
+
+ // Initially, the wallpaper color tab should be selected
+ assertPickerUiState(
+ colorTypes = colorTypes(),
+ colorOptions = colorOptions(),
+ selectedColorTypeText = "Wallpaper colors",
+ selectedColorOptionIndex = 0
+ )
+
+ // Select "Basic colors" tab
+ colorTypes()?.get(ColorType.PRESET_COLOR)?.onClick?.invoke()
+ assertPickerUiState(
+ colorTypes = colorTypes(),
+ colorOptions = colorOptions(),
+ selectedColorTypeText = "Basic colors",
+ selectedColorOptionIndex = -1
+ )
+
+ // Select a color option
+ selectColorOption(colorOptions, 2)
+
+ // Check original option is no longer selected
+ colorTypes()?.get(ColorType.WALLPAPER_COLOR)?.onClick?.invoke()
+ assertPickerUiState(
+ colorTypes = colorTypes(),
+ colorOptions = colorOptions(),
+ selectedColorTypeText = "Wallpaper colors",
+ selectedColorOptionIndex = -1
+ )
+
+ // Check new option is selected
+ colorTypes()?.get(ColorType.PRESET_COLOR)?.onClick?.invoke()
+ assertPickerUiState(
+ colorTypes = colorTypes(),
+ colorOptions = colorOptions(),
+ selectedColorTypeText = "Basic colors",
+ selectedColorOptionIndex = 2
+ )
+ }
+
+ /** Simulates a user selecting the affordance at the given index, if that is clickable. */
+ private fun TestScope.selectColorOption(
+ colorOptions: () -> List<OptionItemViewModel<ColorOptionIconViewModel>>?,
+ index: Int,
+ ) {
+ val onClickedFlow = colorOptions()?.get(index)?.onClicked
+ val onClickedLastValueOrNull: (() -> (() -> Unit)?)? =
+ onClickedFlow?.let { collectLastValue(it) }
+ onClickedLastValueOrNull?.let { onClickedLastValue ->
+ val onClickedOrNull: (() -> Unit)? = onClickedLastValue()
+ onClickedOrNull?.let { onClicked -> onClicked() }
+ }
+ }
+
+ /**
+ * Asserts the entire picker UI state is what is expected. This includes the color type tabs and
+ * the color options list.
+ *
+ * @param colorTypes The observed color type view-models, keyed by ColorType
+ * @param colorOptions The observed color options
+ * @param selectedColorTypeText The text of the color type that's expected to be selected
+ * @param selectedColorOptionIndex The index of the color option that's expected to be selected,
+ * -1 stands for no color option should be selected
+ */
+ private fun TestScope.assertPickerUiState(
+ colorTypes: Map<ColorType, ColorTypeTabViewModel>?,
+ colorOptions: List<OptionItemViewModel<ColorOptionIconViewModel>>?,
+ selectedColorTypeText: String,
+ selectedColorOptionIndex: Int,
+ ) {
+ assertColorTypeTabUiState(
+ colorTypes = colorTypes,
+ colorTypeId = ColorType.WALLPAPER_COLOR,
+ isSelected = "Wallpaper colors" == selectedColorTypeText,
+ )
+ assertColorTypeTabUiState(
+ colorTypes = colorTypes,
+ colorTypeId = ColorType.PRESET_COLOR,
+ isSelected = "Basic colors" == selectedColorTypeText,
+ )
+ assertColorOptionUiState(colorOptions, selectedColorOptionIndex)
+ }
+
+ /**
+ * Asserts the picker section UI state is what is expected.
+ *
+ * @param colorOptions The observed color options
+ * @param selectedColorOptionIndex The index of the color option that's expected to be selected,
+ * -1 stands for no color option should be selected
+ */
+ private fun TestScope.assertColorOptionUiState(
+ colorOptions: List<OptionItemViewModel<ColorOptionIconViewModel>>?,
+ selectedColorOptionIndex: Int,
+ ) {
+ var foundSelectedColorOption = false
+ assertThat(colorOptions).isNotNull()
+ if (colorOptions != null) {
+ for (i in colorOptions.indices) {
+ val colorOptionHasSelectedIndex = i == selectedColorOptionIndex
+ val isSelected: Boolean? = collectLastValue(colorOptions[i].isSelected).invoke()
+ assertWithMessage(
+ "Expected color option with index \"${i}\" to have" +
+ " isSelected=$colorOptionHasSelectedIndex but it was" +
+ " ${isSelected}, num options: ${colorOptions.size}"
+ )
+ .that(isSelected)
+ .isEqualTo(colorOptionHasSelectedIndex)
+ foundSelectedColorOption = foundSelectedColorOption || colorOptionHasSelectedIndex
+ }
+ if (selectedColorOptionIndex == -1) {
+ assertWithMessage(
+ "Expected no color options to be selected, but a color option is" +
+ " selected"
+ )
+ .that(foundSelectedColorOption)
+ .isFalse()
+ } else {
+ assertWithMessage(
+ "Expected a color option to be selected, but no color option is" +
+ " selected"
+ )
+ .that(foundSelectedColorOption)
+ .isTrue()
+ }
+ }
+ }
+
+ /**
+ * Asserts that a color type tab has the correct UI state.
+ *
+ * @param colorTypes The observed color type view-models, keyed by ColorType enum
+ * @param colorTypeId the ID of the color type to assert
+ * @param isSelected Whether that color type should be selected
+ */
+ private fun assertColorTypeTabUiState(
+ colorTypes: Map<ColorType, ColorTypeTabViewModel>?,
+ colorTypeId: ColorType,
+ isSelected: Boolean,
+ ) {
+ val viewModel =
+ colorTypes?.get(colorTypeId) ?: error("No color type with ID \"$colorTypeId\"!")
+ assertThat(viewModel.isSelected).isEqualTo(isSelected)
+ }
+}