[automerger skipped] Use Mockito 4.6.1 API am: 4a8115738d -s ours
am skip reason: Merged-In Ia1d57375170cd8b0c33f3685b2dc3ef0c52ab117 with SHA-1 953ca71dff is already in history
Original change: https://android-review.googlesource.com/c/platform/packages/apps/ThemePicker/+/2152893
Change-Id: Ida800adbd9aeb94b24996e12d59d061f521c0dd1
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 57d30ce..c85fd2b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -69,12 +69,19 @@
name: "ThemePicker",
static_libs: [
+ "guava",
+ "monet",
+ "renderscript_toolkit",
"wallpaper-common-deps",
"SettingsLibSettingsTheme",
"SystemUI-statsd",
"styleprotoslite",
],
+ jni_libs: [
+ "librenderscript-toolkit",
+ ],
+
srcs: [
":WallpaperPicker2_srcs",
":ThemePicker_srcs",
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c6e79a9..ff8f187 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -57,9 +57,26 @@
android:theme="@style/CustomizationTheme.NoActionBar"
android:exported="false"/>
+ <activity
+ tools:node="replace"
+ android:name="com.android.wallpaper.picker.PassThroughCustomizationPickerActivity"
+ android:label="@string/app_name"
+ android:resizeableActivity="false"
+ android:theme="@style/CustomizationTheme.NoActionBar"
+ android:exported="false"/>
+
+ <activity
+ tools:node="replace"
+ android:name="com.android.wallpaper.picker.TrampolinePickerActivity"
+ android:label="@string/app_name"
+ android:relinquishTaskIdentity="true"
+ android:resizeableActivity="false"
+ android:theme="@style/CustomizationTheme.NoActionBar"
+ android:exported="false"/>
+
<activity-alias
android:name="com.android.customization.picker.CustomizationPickerActivity"
- android:targetActivity="com.android.wallpaper.picker.CustomizationPickerActivity"
+ android:targetActivity="com.android.wallpaper.picker.TrampolinePickerActivity"
android:label="@string/app_name"
android:exported="true">
<intent-filter>
diff --git a/res/drawable/color_chip_seed_filled0.xml b/res/drawable/color_chip_seed_filled0.xml
new file mode 100644
index 0000000..a93bc6b
--- /dev/null
+++ b/res/drawable/color_chip_seed_filled0.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape android:shape="rectangle">
+ <corners
+ android:topLeftRadius="@dimen/component_color_chip_small_size_default" />
+ <size
+ android:width="@dimen/component_color_chip_small_size_default"
+ android:height="@dimen/component_color_chip_small_size_default" />
+ <solid android:color="@android:color/black" />
+ </shape>
+ </item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/color_chip_seed_filled1.xml b/res/drawable/color_chip_seed_filled1.xml
new file mode 100644
index 0000000..a0672bc
--- /dev/null
+++ b/res/drawable/color_chip_seed_filled1.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape android:shape="rectangle">
+ <corners
+ android:bottomLeftRadius="@dimen/component_color_chip_small_size_default" />
+ <size
+ android:width="@dimen/component_color_chip_small_size_default"
+ android:height="@dimen/component_color_chip_small_size_default" />
+ <solid android:color="@android:color/black" />
+ </shape>
+ </item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/color_chip_seed_filled2.xml b/res/drawable/color_chip_seed_filled2.xml
new file mode 100644
index 0000000..545fbdd
--- /dev/null
+++ b/res/drawable/color_chip_seed_filled2.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape android:shape="rectangle">
+ <corners
+ android:topRightRadius="@dimen/component_color_chip_small_size_default" />
+ <size
+ android:width="@dimen/component_color_chip_small_size_default"
+ android:height="@dimen/component_color_chip_small_size_default" />
+ <solid android:color="@android:color/black" />
+ </shape>
+ </item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/color_chip_seed_filled3.xml b/res/drawable/color_chip_seed_filled3.xml
new file mode 100644
index 0000000..0e286a5
--- /dev/null
+++ b/res/drawable/color_chip_seed_filled3.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape android:shape="rectangle">
+ <corners
+ android:bottomRightRadius="@dimen/component_color_chip_small_size_default" />
+ <size
+ android:width="@dimen/component_color_chip_small_size_default"
+ android:height="@dimen/component_color_chip_small_size_default" />
+ <solid android:color="@android:color/black" />
+ </shape>
+ </item>
+</selector>
\ No newline at end of file
diff --git a/res/layout-land/fragment_grid_picker.xml b/res/layout-land/fragment_grid_picker.xml
index 2861e7d..0fd52c8 100644
--- a/res/layout-land/fragment_grid_picker.xml
+++ b/res/layout-land/fragment_grid_picker.xml
@@ -26,35 +26,41 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <LinearLayout
- android:id="@+id/content_section"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
- <FrameLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:clipToPadding="false"
- android:paddingTop="@dimen/preview_content_padding_top"
- android:paddingBottom="@dimen/preview_content_padding_bottom"
- android:background="?android:colorSecondary">
- <include layout="@layout/grid_preview_card"/>
- </FrameLayout>
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/content_section"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
- <FrameLayout
- android:id="@+id/options_section"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:paddingVertical="10dp">
+ <FrameLayout
+ android:id="@+id/preview_card_container"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:background="?android:colorSecondary"
+ android:clipToPadding="false"
+ android:paddingBottom="@dimen/preview_content_padding_bottom"
+ android:paddingTop="@dimen/preview_content_padding_top"
+ app:layout_constraintHorizontal_weight="1"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toLeftOf="@+id/options_section">
+ <include layout="@layout/grid_preview_card"/>
+ </FrameLayout>
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/options_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
- </FrameLayout>
- </LinearLayout>
+ <FrameLayout
+ android:id="@+id/options_section"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:paddingVertical="10dp"
+ app:layout_constraintHorizontal_weight="1"
+ app:layout_constraintLeft_toRightOf="@+id/preview_card_container"
+ app:layout_constraintRight_toRightOf="parent">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/options_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ </FrameLayout>
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/loading_indicator"
style="@android:style/Widget.DeviceDefault.ProgressBar"
diff --git a/res/layout/color_option.xml b/res/layout/color_option.xml
new file mode 100644
index 0000000..9bbfd7f
--- /dev/null
+++ b/res/layout/color_option.xml
@@ -0,0 +1,63 @@
+<?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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="vertical">
+
+ <FrameLayout
+ android:id="@+id/option_tile"
+ android:layout_width="@dimen/option_tile_width"
+ android:layout_height="@dimen/option_tile_width"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/option_border_color">
+ <ImageView
+ android:id="@+id/color_preview_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginRight="@dimen/color_seed_chip_margin"
+ android:layout_marginBottom="@dimen/color_seed_chip_margin"
+ android:src="@drawable/color_chip_seed_filled0"/>
+ <ImageView
+ android:id="@+id/color_preview_1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginLeft="@dimen/color_seed_chip_margin"
+ android:layout_marginBottom="@dimen/color_seed_chip_margin"
+ android:src="@drawable/color_chip_seed_filled2"/>
+ <ImageView
+ android:id="@+id/color_preview_2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginRight="@dimen/color_seed_chip_margin"
+ android:layout_marginTop="@dimen/color_seed_chip_margin"
+ android:src="@drawable/color_chip_seed_filled1"/>
+ <ImageView
+ android:id="@+id/color_preview_3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginLeft="@dimen/color_seed_chip_margin"
+ android:layout_marginTop="@dimen/color_seed_chip_margin"
+ android:src="@drawable/color_chip_seed_filled3"/>
+ </FrameLayout>
+</FrameLayout>
diff --git a/res/layout/color_options_view.xml b/res/layout/color_options_view.xml
new file mode 100644
index 0000000..65028a6
--- /dev/null
+++ b/res/layout/color_options_view.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/color_option_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:orientation="horizontal" />
+</FrameLayout>
diff --git a/res/layout/color_pages_view.xml b/res/layout/color_pages_view.xml
new file mode 100644
index 0000000..3ccbd41
--- /dev/null
+++ b/res/layout/color_pages_view.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <androidx.viewpager2.widget.ViewPager2
+ android:id="@+id/color_page_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+ <com.android.wallpaper.widget.PageIndicator
+ android:id="@+id/color_page_indicator"
+ android:layout_marginTop="@dimen/color_page_indicator_margin_top"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layout_gravity="center"/>
+</LinearLayout>
diff --git a/res/layout/color_section_view.xml b/res/layout/color_section_view.xml
new file mode 100644
index 0000000..6095c9b
--- /dev/null
+++ b/res/layout/color_section_view.xml
@@ -0,0 +1,38 @@
+<?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.color.ColorSectionView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/section_bottom_padding"
+ android:orientation="vertical">
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/separated_tabs_horizontal_padding">
+ <include layout="@layout/separated_tabs" />
+ </FrameLayout>
+
+ <androidx.viewpager2.widget.ViewPager2
+ android:id="@+id/color_section_view_pager"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/color_options_container_top_margin"
+ android:clipChildren="false"
+ android:clipToPadding="false"/>
+</com.android.customization.picker.color.ColorSectionView>
diff --git a/res/layout/fragment_grid_picker.xml b/res/layout/fragment_grid_picker.xml
index aec8e49..34547fc 100644
--- a/res/layout/fragment_grid_picker.xml
+++ b/res/layout/fragment_grid_picker.xml
@@ -33,8 +33,8 @@
<FrameLayout
android:id="@+id/preview_card_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
android:clipToPadding="false"
android:paddingTop="@dimen/preview_page_top_margin"
android:paddingBottom="@dimen/preview_page_bottom_margin"
@@ -42,7 +42,8 @@
app:layout_constraintBottom_toTopOf="@+id/options_container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent">
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_bias="@dimen/preview_card_vertical_bias">
<include layout="@layout/grid_preview_card" />
</FrameLayout>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 1d2b248..4a6733e 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Tema-ikone"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Verander programrooster"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Muurpapierkleure"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Muurpapierkleur"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Basiese kleure"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Kleur het verander"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamies"</string>
</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index ded03a2..592ad89 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"ገጽታ ያላቸው አዶዎች"</string>
<string name="beta_title" msgid="8703819523760746458">"ቤታ"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"የመተግበሪያ ፍርግርግን ይቀይሩ"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"የልጣፍ ቀለማት"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"የልጣፍ ቀለም"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"መሰረታዊ ቀለሞች"</string>
+ <string name="color_changed" msgid="7029571720331641235">"ቀለም ተቀይሯል"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ተለዋዋጭ"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 8b4af4c..ef802d2 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"رموز مستوحاة من موضوع معيّن"</string>
<string name="beta_title" msgid="8703819523760746458">"تجريبي"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"تغيير شبكة التطبيقات"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"ألوان الخلفية"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"لون الخلفية"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"الألوان الأساسية"</string>
+ <string name="color_changed" msgid="7029571720331641235">"تم تغيير اللون."</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ألوان ديناميكية"</string>
</resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 663e3c5..fb72239 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -42,7 +42,7 @@
<string name="preview_name_shape" msgid="5676971146080968721">"আকৃতি"</string>
<string name="preview_name_wallpaper" msgid="1738652462949531828">"ৱালপেপাৰ"</string>
<string name="font_card_title" msgid="2343292653502548685">"ABC • abc • 123"</string>
- <string name="font_card_body" msgid="6790525594503904468">"প্ৰত্যেকখন স্ক্ৰীণত আপোনাৰ প্ৰিয় ফণ্ট যোগ কৰক"</string>
+ <string name="font_card_body" msgid="6790525594503904468">"প্ৰত্যেকখন স্ক্ৰীনত আপোনাৰ প্ৰিয় ফ’ণ্ট যোগ দিয়ক"</string>
<string name="grid_options_title" msgid="7071930966989877023">"এটা গ্ৰিডৰ আকাৰ বাছনি কৰক"</string>
<string name="grid_title_pattern" msgid="9188866567612607806">"<xliff:g id="ID_1">%1$d</xliff:g>x<xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="applied_theme_msg" msgid="3749018706366796244">"শৈলী সফলতাৰে ছেট কৰা হ’ল"</string>
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"থীমযুক্ত চিহ্ন"</string>
<string name="beta_title" msgid="8703819523760746458">"বিটা"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"এপৰ গ্ৰিড সলনি কৰক"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"ৱালপেপাৰৰ ৰং"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"ৱালপেপাৰৰ ৰং"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"প্ৰাথমিক ৰং"</string>
+ <string name="color_changed" msgid="7029571720331641235">"ৰং সলনি কৰা হৈছে"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ডাইনামিক"</string>
</resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 0c6efab..2d8209b 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Temalı ikonalar"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Tətbiq torunu dəyişin"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Divar kağızı rəngləri"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Divar kağızı rəngi"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Əsas rənglər"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Rəng dəyişdirildi"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamik"</string>
</resources>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 35a35fe..d8aacd6 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Tematske ikone"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Promenite mrežu aplikacija"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Boje pozadine"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Boja pozadine"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Osnovne boje"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Boja je promenjena"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamički"</string>
</resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 13ad63e..4151478 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Тэматычныя значкі"</string>
<string name="beta_title" msgid="8703819523760746458">"Бэта"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Змяніць сетку праграм"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Колеры шпалер"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Колер шпалер"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Асноўныя колеры"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Колер зменены"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Дынамічны"</string>
</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 8f19803..849af69 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Икони с теми"</string>
<string name="beta_title" msgid="8703819523760746458">"Бета"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Промяна на решетката с приложения"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Цветове от тапета"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Цвят от тапета"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Основни цветове"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Цветът бе променен"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Динамично"</string>
</resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 2e94198..b1c9abe 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"থিমযুক্ত আইকন"</string>
<string name="beta_title" msgid="8703819523760746458">"বিটা"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"অ্যাপ গ্রিড পরিবর্তন করুন"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"ওয়ালপেপারের রঙ"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"ওয়ালপেপারের রঙ"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"প্রাথমিক রঙ"</string>
+ <string name="color_changed" msgid="7029571720331641235">"রঙ পরিবর্তন করা হয়েছে"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ডায়নামিক"</string>
</resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 29075d6..11c4587 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Tematske ikone"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Promjena mreže aplikacije"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Boje pozadinske slike"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Boja pozadinske slike"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Osnovne boje"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Boja je promijenjena"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamički"</string>
</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index c8fdb3d..f9a3a33 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Icones temàtiques"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Canvia la quadrícula d\'aplicacions"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Colors del fons"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Color del fons de pantalla"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Colors bàsics"</string>
+ <string name="color_changed" msgid="7029571720331641235">"S\'ha canviat el color"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinàmic"</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 0b3bf29..3bdbe89 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Tematické ikony"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Změnit mřížku aplikací"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Barvy tapety"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Barva tapety"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Základní barvy"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Barva byla změněna"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamické"</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index ee0888a..68fe7b3 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Temaikoner"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Juster appgitter"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Baggrundsfarver"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Baggrundsfarve"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Standardfarver"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Farven er ændret"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamisk"</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 6a83d72..c55bffb 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Symboldesigns"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"App-Raster ändern"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Hintergrundfarben"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Hintergrundfarbe"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Standardfarben"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Farbe geändert"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamisch"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index c067781..db4400f 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Θεματικά εικονίδια"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Αλλαγή πλέγματος εφαρμογής"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Χρώματα ταπετσαρίας"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Χρώμα ταπετσαρίας"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Βασικά χρώματα"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Το χρώμα άλλαξε"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Δυναμική"</string>
</resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 953a985..afd6deb 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Themed icons"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Change app grid"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Wallpaper colours"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Wallpaper colour"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Basic colours"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Colour changed"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamic"</string>
</resources>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 953a985..afd6deb 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Themed icons"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Change app grid"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Wallpaper colours"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Wallpaper colour"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Basic colours"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Colour changed"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamic"</string>
</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 953a985..afd6deb 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Themed icons"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Change app grid"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Wallpaper colours"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Wallpaper colour"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Basic colours"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Colour changed"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamic"</string>
</resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 953a985..afd6deb 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Themed icons"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Change app grid"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Wallpaper colours"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Wallpaper colour"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Basic colours"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Colour changed"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamic"</string>
</resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index fae727a..8ed71cd 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Themed icons"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Change app grid"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Wallpaper colors"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Wallpaper color"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Basic colors"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Color changed"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamic"</string>
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 50b3bc5..0eb30c7 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Íconos temáticos"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Cambiar cuadrícula de apps"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Colores del fondo"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Color del fondo de pantalla"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Colores básicos"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Se cambió el color"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinámico"</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 17cfabe..c45e390 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Iconos con tema"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Cambiar cuadrícula de aplicaciones"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Colores del fondo"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Color del fondo de pantalla"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Colores básicos"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Color cambiado"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinámico"</string>
</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index f444cb2..2a6e051 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Temaatilised ikoonid"</string>
<string name="beta_title" msgid="8703819523760746458">"Beeta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Rakenduste ruudustiku muutmine"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Taustapildi värvid"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Taustapildi värv"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Põhivärvid"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Värvi muudeti"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dünaamiline"</string>
</resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 7e4b016..7944b93 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Ikono gaidunak"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Aldatu aplikazioen sareta"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Horma-papereko koloreak"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Horma-paperaren kolorea"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Oinarrizko koloreak"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Aldatu da kolorea"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamikoa"</string>
</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 500af38..4a5f763 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"نمادهای دارای زمینه"</string>
<string name="beta_title" msgid="8703819523760746458">"بتا"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"تغییر جدول برنامه"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"رنگهای کاغذدیواری"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"رنگ کاغذدیواری"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"رنگهای اصلی"</string>
+ <string name="color_changed" msgid="7029571720331641235">"رنگ تغییر کرد"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"پویا"</string>
</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 1d393ee..37f57b8 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Kuvakkeiden teemat"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Muuta sovellusruudukkoa"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Taustakuvan värit"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Taustakuvan väri"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Perusvärit"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Väri vaihdettu"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynaaminen"</string>
</resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 57f348e..c271e5c 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Icônes du thème"</string>
<string name="beta_title" msgid="8703819523760746458">"Bêta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Modifiez la grille d\'applications"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Couleurs fond d\'écran"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Couleur du fond d\'écran"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Couleurs de base"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Couleur changée"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamique"</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index b436871..f6b5546 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Icônes à thème"</string>
<string name="beta_title" msgid="8703819523760746458">"Bêta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Modifier la grille d\'applis"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Couleurs fond d\'écran"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Couleur du fond d\'écran"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Couleurs de base"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Couleur modifiée"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamique"</string>
</resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index de26228..5b90944 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Tema das iconas"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Cambia a grade de aplicacións"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Cores do fondo"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Cor do fondo de pantalla"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Cores básicas"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Cor modificada"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinámica"</string>
</resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index e2bed3f..1ff79ad 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"થીમવાળા આઇકન"</string>
<string name="beta_title" msgid="8703819523760746458">"બીટા"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"ઍપ ગ્રિડ બદલો"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"વૉલપેપરના રંગો"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"વૉલપેપરનો રંગ"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"મૂળભૂત રંગો"</string>
+ <string name="color_changed" msgid="7029571720331641235">"રંગ બદલ્યો છે"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ડાઇનૅમિક"</string>
</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 43fb23b..a207bfe 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"थीम वाले आइकॉन"</string>
<string name="beta_title" msgid="8703819523760746458">"बीटा"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"ऐप्लिकेशन ग्रिड बदलें"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"वॉलपेपर के रंग"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"वॉलपेपर का रंग"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"सामान्य रंग"</string>
+ <string name="color_changed" msgid="7029571720331641235">"रंग बदल दिया गया है"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"डाइनैमिक"</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 30bbd97..b603fa6 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Tematske ikone"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Promjena rešetke aplikacije"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Boje pozadine"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Boja pozadine"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Osnovne boje"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Promijenjena boja"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamično"</string>
</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 6ebbc07..620d36c 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Tematikus ikonok"</string>
<string name="beta_title" msgid="8703819523760746458">"Béta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Alkalmazásrács módosítása"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Háttérképszínek"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Háttérkép színe"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Alapszínek"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Szín módosítva"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamikus"</string>
</resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index a7b9bcd..7c7d059 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Թեմատիկ պատկերակներ"</string>
<string name="beta_title" msgid="8703819523760746458">"Բետա"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Փոխել հավելվածների ցանցը"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Պաստառի գույներ"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Պաստառի գույն"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Հիմնական գույներ"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Գույնը փոխվեց"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Դինամիկ"</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 60bfcb9..7e48536 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Ikon bertema"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Ubah petak aplikasi"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Warna wallpaper"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Warna wallpaper"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Warna dasar"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Warna diubah"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamis"</string>
</resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 69eb141..9312a5c 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Þematákn"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Breyta forritatöflu"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Veggfóðurslitir"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Veggfóðurslitur"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Grunnlitir"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Lit breytt"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Breytilegt"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index b74912d..08df999 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Icone a tema"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Cambia griglia di app"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Colori di sfondo"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Colore dello sfondo"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Colori di base"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Colore modificato"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamica"</string>
</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 876a60a..5d9e2d9 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"סמלים מעוצבים"</string>
<string name="beta_title" msgid="8703819523760746458">"בטא"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"שינוי רשת האפליקציות"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"צבעי הטפט"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"צבע הטפט"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"הצבעים הבסיסיים"</string>
+ <string name="color_changed" msgid="7029571720331641235">"הצבע השתנה"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"דינמי"</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 29cb668..f6a20d3 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"テーマアイコン"</string>
<string name="beta_title" msgid="8703819523760746458">"ベータ版"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"アプリグリッドを変更します"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"壁紙の色"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"壁紙の色"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"基本の色"</string>
+ <string name="color_changed" msgid="7029571720331641235">"色を変更しました"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"動的"</string>
</resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index a74d2fa..7fb2f96 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"თემატური ხატულები"</string>
<string name="beta_title" msgid="8703819523760746458">"ბეტა"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"აპების ბადის შეცვლა"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"ფონის ფერები"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"ფონის ფერი"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"ძირითადი ფერები"</string>
+ <string name="color_changed" msgid="7029571720331641235">"ფერი შეიცვალა"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"დინამიკური"</string>
</resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index cbd2ebc..c62d6a0 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Тақырыптық белгішелер"</string>
<string name="beta_title" msgid="8703819523760746458">"Бета"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Қолданбалар торын өзгерту"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Тұсқағаз түстері"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Тұсқағаз түсі"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Негізгі түстер"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Түс өзгертілді."</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Динамикалық"</string>
</resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 00eea2f..02080a7 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"រូបតំណាងប្ដូររចនាប័ទ្ម"</string>
<string name="beta_title" msgid="8703819523760746458">"បេតា"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"ប្ដូរក្រឡាកម្មវិធី"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"ពណ៌ផ្ទាំងរូបភាព"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"ពណ៌ផ្ទាំងរូបភាព"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"ពណ៌លំនាំដើម"</string>
+ <string name="color_changed" msgid="7029571720331641235">"បានផ្លាស់ប្ដូរពណ៌"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ឌីណាមិក"</string>
</resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 1ed1847..95d8df3 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"ಥೀಮ್ ಮಾಡಿದ ಐಕಾನ್ಗಳು"</string>
<string name="beta_title" msgid="8703819523760746458">"ಬೀಟಾ"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"ಆ್ಯಪ್ ಗ್ರಿಡ್ ಬದಲಾಯಿಸಿ"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"ವಾಲ್ಪೇಪರ್ ಬಣ್ಣಗಳು"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"ವಾಲ್ಪೇಪರ್ ಬಣ್ಣ"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"ಮೂಲ ಬಣ್ಣಗಳು"</string>
+ <string name="color_changed" msgid="7029571720331641235">"ಬಣ್ಣ ಬದಲಾಗಿದೆ"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ಡೈನಾಮಿಕ್"</string>
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 923f092..25e7d43 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"테마 아이콘"</string>
<string name="beta_title" msgid="8703819523760746458">"베타"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"앱 그리드 변경"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"배경화면 색상"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"배경화면 색상"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"기본 색상"</string>
+ <string name="color_changed" msgid="7029571720331641235">"색상 변경됨"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"동적"</string>
</resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index b83f458..f7b60ef 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Тематикалык сүрөтчөлөр"</string>
<string name="beta_title" msgid="8703819523760746458">"Бета"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Колдонмонун торчосун өзгөртүү"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Тушкагаздын түстөрү"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Тушкагаздын түсү"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Негизги түстөр"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Түс өзгөртүлдү"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Динамикалык"</string>
</resources>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 3bad9e6..601f06f 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -27,7 +27,7 @@
<dimen name="preview_theme_tile_size">14dp</dimen>
<dimen name="preview_theme_shape_size">30dp</dimen>
- <dimen name="options_container_width">400dp</dimen>
+ <dimen name="options_container_width">0dp</dimen>
<dimen name="option_bottom_margin">8dp</dimen>
<dimen name="option_tile_width">62dp</dimen>
<dimen name="option_tile_padding_horizontal">7dp</dimen>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 5f9acf6..8fe51ba 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"ໄອຄອນຕາມຮູບແບບສີສັນ"</string>
<string name="beta_title" msgid="8703819523760746458">"ເບຕ້າ"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"ປ່ຽນຕາຕະລາງແອັບ"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"ສີຮູບພື້ນຫຼັງ"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"ສີຮູບພື້ນຫຼັງ"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"ສີພື້ນຖານ"</string>
+ <string name="color_changed" msgid="7029571720331641235">"ປ່ຽນສີແລ້ວ"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ໄດນາມິກ"</string>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index b790726..02b289b 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Teminės piktogramos"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Programų tinklelio keitimas"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Ekrano fono spalvos"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Ekrano fono spalva"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Pagrindinės spalvos"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Spalva pakeista"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinaminės"</string>
</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index f090215..f8fb310 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Motīvu ikonas"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Mainīt lietotņu režģi"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Fona tapetes krāsas"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Fona tapetes krāsa"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Pamatkrāsas"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Krāsa mainīta"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamiska"</string>
</resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 0f086b4..197058c 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Икони со тема"</string>
<string name="beta_title" msgid="8703819523760746458">"Бета"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Променете ја мрежата на апликации"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Бои од тапетот"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Боја на тапет"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Основни бои"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Бојата е променета"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Динамично"</string>
</resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 7ed3912..91ae2dc 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"തീമുള്ള ഐക്കണുകൾ"</string>
<string name="beta_title" msgid="8703819523760746458">"ബീറ്റ"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"ആപ്പ് ഗ്രിഡ് മാറ്റുക"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"വാൾപേപ്പർ നിറങ്ങൾ"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"വാൾപേപ്പറിനിന്റെ നിറം"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"അടിസ്ഥാന നിറങ്ങൾ"</string>
+ <string name="color_changed" msgid="7029571720331641235">"നിറം മാറ്റി"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ഡൈനാമിക്"</string>
</resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index bcab83d..6fc45b5 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Загварын дүрс тэмдэг"</string>
<string name="beta_title" msgid="8703819523760746458">"Бета"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Аппын хүснэгтийг өөрчлөх"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Дэлгэцийн зургийн өнгө"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Дэлгэцийн зургийн өнгө"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Суурь өнгөнүүд"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Өнгийг өөрчилсөн"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Динамик"</string>
</resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 4622270..0eba26e 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"थीम असलेले आयकन"</string>
<string name="beta_title" msgid="8703819523760746458">"बीटा"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"अॅप ग्रिड बदला"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"वॉलपेपरचे रंग"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"वॉलपेपरचा रंग"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"डीफॉल्ट रंग"</string>
+ <string name="color_changed" msgid="7029571720331641235">"रंग बदलला आहे"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"सतत बदलणारे"</string>
</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 3fedc89..a241339 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Ikon bertema"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Tukar grid apl"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Warna kertas dinding"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Warna kertas dinding"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Warna asas"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Warna ditukar"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamik"</string>
</resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index f08adf4..f4eeb3f 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"အပြင်အဆင်သုံး သင်္ကေတများ"</string>
<string name="beta_title" msgid="8703819523760746458">"စမ်းသပ်ဆော့ဖ်ဝဲ"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"အက်ပ်ဇယား ပြောင်းရန်"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"နောက်ခံအရောင်များ"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"နောက်ခံအရောင်"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"အခြေခံအရောင်များ"</string>
+ <string name="color_changed" msgid="7029571720331641235">"အရောင် ပြောင်းလိုက်ပါပြီ"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ပြောင်းနိုင်သော"</string>
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 808828d..a82f28b 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Temaikoner"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Endre apprutenett"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Bakgrunnsfarger"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Bakgrunnsfarge"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Grunnleggende farger"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Fargen er endret"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamisk"</string>
</resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 0f3dfd5..a29a975 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"थिम भएका आइकन"</string>
<string name="beta_title" msgid="8703819523760746458">"बिटा"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"एप ग्रिड बदल्नुहोस्"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"वालपेपरका रङहरू"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"वालपेपरको रङ"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"आधारभूत रङहरू"</string>
+ <string name="color_changed" msgid="7029571720331641235">"रङ बदलियो"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"गतिशील"</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 9d7de8b..6210372 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Thema-iconen"</string>
<string name="beta_title" msgid="8703819523760746458">"Bèta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"App-raster wijzigen"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Achtergrondkleuren"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Achtergrondkleur"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Basiskleuren"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Kleur gewijzigd"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamisch"</string>
</resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 5cd59a2..628fe74 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"ଥିମ୍ ଯୁକ୍ତ ଆଇକନ୍"</string>
<string name="beta_title" msgid="8703819523760746458">"ବିଟା"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"ଆପ୍ ଗ୍ରିଡ୍ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"ୱାଲପେପର ରଙ୍ଗଗୁଡ଼ିକ"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"ୱାଲପେପର ରଙ୍ଗ"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"ମୌଳିକ ରଙ୍ଗଗୁଡ଼ିକ"</string>
+ <string name="color_changed" msgid="7029571720331641235">"ରଙ୍ଗ ପରିବର୍ତ୍ତନ କରାଯାଇଛି"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ଡାଇନାମିକ"</string>
</resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 070455a..1d9d119 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"ਥੀਮ ਵਾਲੇ ਪ੍ਰਤੀਕ"</string>
<string name="beta_title" msgid="8703819523760746458">"ਬੀਟਾ"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"ਐਪ ਗ੍ਰਿਡ ਬਦਲੋ"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"ਵਾਲਪੇਪਰ ਦੇ ਰੰਗ"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"ਵਾਲਪੇਪਰ ਦਾ ਰੰਗ"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"ਮੂਲ ਰੰਗ"</string>
+ <string name="color_changed" msgid="7029571720331641235">"ਰੰਗ ਬਦਲਿਆ ਗਿਆ"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ਪਰਿਵਰਤਨਸ਼ੀਲ"</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 18d7d57..b3140dc 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Ikony z motywem"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Zmień siatkę aplikacji"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Kolory tapety"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Kolor tapety"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Kolory podstawowe"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Kolor został zmieniony"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamicznie"</string>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 48995e5..a9a4fe3 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Ícones temáticos"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Altere a grelha de apps"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Cores imag. de fundo"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Cor da imagem de fundo"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Cores básicas"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Cor alterada"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinâmico"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 6054585..c858265 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Ícones com tema"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Mudar a grade de apps"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Cores do plano de fundo"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Cor do plano de fundo"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Cores básicas"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Cor trocada"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinâmica"</string>
</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index b819165..7389836 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Pictograme tematice"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Schimbați grila de aplicații"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Culori de fundal"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Culoarea imaginii de fundal"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Culori de bază"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Culoare modificată"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamic"</string>
</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index c8f2a69..1a674ff 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Тематические значки"</string>
<string name="beta_title" msgid="8703819523760746458">"Бета"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Настроить сетку приложений"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Цвета обоев"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Цвет обоев"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Основные цвета"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Цвет изменен"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Динамически"</string>
</resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 2ec8efd..2e85b26 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"තේමාගත නිරූපක"</string>
<string name="beta_title" msgid="8703819523760746458">"බීටා"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"යෙදුම් ජාලකය වෙනස් කරන්න"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"වෝල්පේපර වර්ණ"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"වෝල්පේපර වර්ණය"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"මූලික වර්ණ"</string>
+ <string name="color_changed" msgid="7029571720331641235">"වර්ණය වෙනස් විය"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ගතික"</string>
</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 7293003..7431dec 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Prefarbené ikony"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Zmeniť mriežku aplikácií"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Farby tapety"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Farba tapety"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Základné farby"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Farba bola zmenená"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamické"</string>
</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index c7592d5..a637d4f 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Ikone s temo"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Spreminjanje mreže aplikacij."</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Barve zaslon. ozadja"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Barva zaslonskega ozadja"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Osnovne barve"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Barva je spremenjena."</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamično"</string>
</resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 1793163..8f6259c 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Ikona me temë"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Ndrysho rrjetën e aplikacioneve"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Ngjyra imazhi sfondi"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Ngjyra e imazhit të sfondit"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Ngjyra bazë"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Ngjyra ka ndryshuar"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamike"</string>
</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 80fa87d..3a7de2b 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Тематске иконе"</string>
<string name="beta_title" msgid="8703819523760746458">"Бета"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Промените мрежу апликација"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Боје позадине"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Боја позадине"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Основне боје"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Боја је промењена"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Динамички"</string>
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index f84613f..d16ff0f 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Ikoner med tema"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Ändra rutnät för appar"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Bakgrundsfärger"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Bakgrundsfärg"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Standardfärger"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Färgen har ändrats"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamisk"</string>
</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index c4dc13a..1a01433 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Aikoni zenye mada"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Badilisha gridi ya programu"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Rangi za mandhari"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Rangi ya mandhari"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Rangi za msingi"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Rangi imebadilishwa"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Inayobadilika"</string>
</resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index e2d1384..3a2bffb 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"தீம் செய்யப்பட்ட ஐகான்கள்"</string>
<string name="beta_title" msgid="8703819523760746458">"பீட்டா"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"ஆப்ஸ் கட்டக் காட்சியை மாற்றும்"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"வால்பேப்பர் நிறங்கள்"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"வால்பேப்பரின் நிறம்"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"அடிப்படை வண்ணங்கள்"</string>
+ <string name="color_changed" msgid="7029571720331641235">"வண்ணம் மாற்றப்பட்டது"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"டைனமிக்"</string>
</resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index f195a9c..72fd0c3 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"రూపానికి తగిన చిహ్నాలు"</string>
<string name="beta_title" msgid="8703819523760746458">"బీటా"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"యాప్ గ్రిడ్ను మార్చండి"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"వాల్పేపర్ రంగులు"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"వాల్పేపర్ రంగు"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"ప్రాథమిక రంగులు"</string>
+ <string name="color_changed" msgid="7029571720331641235">"రంగు మార్చబడింది"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"డైనమిక్"</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 3adb04a..3375c30 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"ไอคอนตามธีม"</string>
<string name="beta_title" msgid="8703819523760746458">"เบต้า"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"เปลี่ยนแปลงตารางกริดสำหรับแอป"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"สีวอลเปเปอร์"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"สีวอลเปเปอร์"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"สีพื้นฐาน"</string>
+ <string name="color_changed" msgid="7029571720331641235">"เปลี่ยนสีแล้ว"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ไดนามิก"</string>
</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index f59f3e9..591a107 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Mga may temang icon"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Baguhin ang grid ng app"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Kulay ng wallpaper"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Kulay ng wallpaper"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Mga basic na kulay"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Pinalitan ang kulay"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dynamic"</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 7c01dd6..e90cc22 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Tema simgeleri"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Uygulama ızgarasını değiştirin"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Duvar kağıdı renkleri"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Duvar kağıdı rengi"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Temel renkler"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Renk değişti"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamik"</string>
</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 6117e09..a41a498 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Тема значків"</string>
<string name="beta_title" msgid="8703819523760746458">"Бета"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Змінити сітку додатків"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Кольори малюнка"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Колір фонового малюнка"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Основні кольори"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Колір змінено"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Динамічний"</string>
</resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index fa5e259..8ae85d3 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"تھیم کردہ آئیکنز"</string>
<string name="beta_title" msgid="8703819523760746458">"بی ٹا"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"ایپ گرڈ تبدیل کریں"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"وال پیپر کے رنگ"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"وال پیپر کا رنگ"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"بنیادی رنگ"</string>
+ <string name="color_changed" msgid="7029571720331641235">"رنگ کو تبدیل کر دیا گیا"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"ڈائنیمک"</string>
</resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index eee5210..44563b5 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Mavzuga oid ikonkalar"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Ilovalar jadvalini oʻzgartirish"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Fon ranglari"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Fon rasmi rangi"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Asosiy ranglar"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Rang oʻzgartirildi"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Dinamik"</string>
</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 4e4281b..c078772 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Biểu tượng theo chủ đề"</string>
<string name="beta_title" msgid="8703819523760746458">"Thử nghiệm"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Thay đổi lưới ứng dụng"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Màu hình nền"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Màu hình nền"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Màu cơ bản"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Đã thay đổi màu"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Động"</string>
</resources>
diff --git a/res/values-w600dp-port/dimens.xml b/res/values-w600dp-port/dimens.xml
new file mode 100644
index 0000000..ba92746
--- /dev/null
+++ b/res/values-w600dp-port/dimens.xml
@@ -0,0 +1,24 @@
+<?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
+ -->
+<resources>
+ <!-- Dimensions for the customization option tiles -->
+ <dimen name="option_tile_width">79dp</dimen>
+ <dimen name="option_tile_grid_padding_horizontal">8dp</dimen>
+
+ <dimen name="component_color_chip_small_size_default">30dp</dimen>
+ <dimen name="color_seed_chip_margin">15dp</dimen>
+</resources>
diff --git a/res/values-w800dp/dimens.xml b/res/values-w800dp/dimens.xml
new file mode 100644
index 0000000..4cd6242
--- /dev/null
+++ b/res/values-w800dp/dimens.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+<resources>
+ <!-- Dimensions for the customization option tiles -->
+ <dimen name="option_tile_width">87dp</dimen>
+ <dimen name="option_tile_grid_padding_horizontal">8dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values-w800dp/integers.xml b/res/values-w800dp/integers.xml
new file mode 100644
index 0000000..23fa48a
--- /dev/null
+++ b/res/values-w800dp/integers.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+<resources>
+ <integer name="options_grid_num_columns">6</integer>
+</resources>
diff --git a/res/values-w840dp/attrs.xml b/res/values-w840dp/attrs.xml
new file mode 100644
index 0000000..f63f574
--- /dev/null
+++ b/res/values-w840dp/attrs.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<resources>
+ <item name="linear_layout_horizontal_display_options_max" format="float" type="dimen">6.35
+ </item>
+</resources>
\ No newline at end of file
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 13a6c87..1a20566 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"带主题的图标"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta 版"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"更改应用网格"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"壁纸颜色"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"壁纸颜色"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"基本颜色"</string>
+ <string name="color_changed" msgid="7029571720331641235">"颜色已更改"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"动态"</string>
</resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index e06d883..df0972c 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"主題圖示"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta 版本"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"變更應用程式網格"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"桌布顏色"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"桌布顏色"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"基本顏色"</string>
+ <string name="color_changed" msgid="7029571720331641235">"已經變咗顏色"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"動態"</string>
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 454db85..478d759 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"圖示套用主題色"</string>
<string name="beta_title" msgid="8703819523760746458">"Beta 版"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"變更應用程式格線"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"桌布顏色"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"桌布顏色"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"基本顏色"</string>
+ <string name="color_changed" msgid="7029571720331641235">"顏色已變更"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"動態"</string>
</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 532491d..e399001 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -84,4 +84,9 @@
<string name="themed_icon_title" msgid="7312460430471956558">"Izithonjana ezinetimu"</string>
<string name="beta_title" msgid="8703819523760746458">"I-beta"</string>
<string name="gird_picker_entry_content_description" msgid="9087651470212293439">"Shintsha igridi ye-app"</string>
+ <string name="wallpaper_color_tab" msgid="1447926591721403840">"Imibala yesithombe sangemuva"</string>
+ <string name="wallpaper_color_title" msgid="5687965239180986458">"Umbala wesithombe sangemuva"</string>
+ <string name="preset_color_tab" msgid="3133391839341329314">"Imibala eyisisekelo"</string>
+ <string name="color_changed" msgid="7029571720331641235">"Umbala ushintshiwe"</string>
+ <string name="adaptive_color_title" msgid="1336508599235896205">"Okuguqukayo"</string>
</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
new file mode 100644
index 0000000..288dd19
--- /dev/null
+++ b/res/values/attrs.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<resources>
+ <item name="linear_layout_horizontal_display_options_max" format="float" type="dimen">4.35
+ </item>
+</resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 2086480..0ad221e 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -38,6 +38,7 @@
<dimen name="option_tile_margin_horizontal">6dp</dimen>
<dimen name="option_tile_padding_vertical">12dp</dimen>
<dimen name="option_tile_padding_horizontal">12dp</dimen>
+ <dimen name="option_tile_grid_padding_horizontal">4dp</dimen>
<dimen name="option_icon_size">16dp</dimen>
<dimen name="theme_option_icon_sample_height">22dp</dimen>
<dimen name="theme_option_icon_sample_width">22dp</dimen>
@@ -123,4 +124,15 @@
<dimen name="beta_tag_background_width">46dp</dimen>
<dimen name="beta_tag_background_height">24dp</dimen>
+
+ <!-- For the color option section -->
+ <dimen name="color_options_container_top_margin">24dp</dimen>
+
+ <!-- For the color page. -->
+ <dimen name="color_page_indicator_margin_top">16dp</dimen>
+
+ <dimen name="component_color_chip_small_size_default">29dp</dimen>
+ <dimen name="color_seed_option_tile_padding">10dp</dimen>
+ <dimen name="color_seed_option_tile_padding_selected">6dp</dimen>
+ <dimen name="color_seed_chip_margin">14dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f2d0f21..1a15fd0 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -247,4 +247,17 @@
<!-- The content description of grid picker entry. [CHAR LIMIT=NONE] -->
<string name="gird_picker_entry_content_description" msgid="7538418512525897691">Change app grid</string>
+
+ <!-- The title for the tab with colors from wallpaper. [CHAR_LIMIT=20]-->
+ <string name="wallpaper_color_tab">Wallpaper colors</string>
+ <!-- The description on an item that shows a color obtained from the wallpaper
+ (used mainly for accessibility). [CHAR_LIMIT=NONE] -->
+ <string name="wallpaper_color_title">Wallpaper color</string>
+ <!-- The title for the tab with a default set of color options. [CHAR_LIMIT=20]-->
+ <string name="preset_color_tab">Basic colors</string>
+ <!-- The text for A11y announcement when color changes. -->
+ <string name="color_changed">Color changed</string>
+ <!-- Title of a section of color selection option that obtains colors automatically from the
+ wallpaper instead of a set color [CHAR LIMIT=15] -->
+ <string name="adaptive_color_title">Dynamic</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c0a0aed..3991b65 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -41,6 +41,17 @@
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowDisablePreview">true</item>
+ <item name="snackbarStyle">@style/SnackbarMargin</item>
+
+ <item name="borderlessButtonStyle">@style/Widget.AppCompat.Button.Borderless</item>
+ <item name="colorAccent">@color/accent_color</item>
+ <item name="colorSurface">@color/design_default_color_surface</item>
+ <item name="colorOnSurface">@color/design_default_color_on_surface</item>
+ </style>
+
+ <!-- Snackbar margin -->
+ <style name="SnackbarMargin" parent="Widget.MaterialComponents.Snackbar">
+ <item name="android:layout_margin">48dp</item>
</style>
<!-- Bottom nav -->
diff --git a/robolectric_tests/Android.mk b/robolectric_tests/Android.mk
index 1117cc3..7d9b0e1 100644
--- a/robolectric_tests/Android.mk
+++ b/robolectric_tests/Android.mk
@@ -29,7 +29,7 @@
mockito-robolectric-prebuilt \
truth-prebuilt
LOCAL_JAVA_LIBRARIES := \
- platform-robolectric-3.6.2-prebuilt
+ platform-robolectric-4.5.1-prebuilt
LOCAL_JAVA_RESOURCE_DIRS := config
diff --git a/robolectric_tests/config/robolectric.properties b/robolectric_tests/config/robolectric.properties
index 6a5d031..6c518c0 100644
--- a/robolectric_tests/config/robolectric.properties
+++ b/robolectric_tests/config/robolectric.properties
@@ -1,2 +1,2 @@
manifest=packages/apps/ThemePicker/AndroidManifest.xml
-sdk=27
+sdk=31
diff --git a/robolectric_tests/robolectric_gradle_config/robolectric.properties b/robolectric_tests/robolectric_gradle_config/robolectric.properties
index 926e354..2916ca9 100644
--- a/robolectric_tests/robolectric_gradle_config/robolectric.properties
+++ b/robolectric_tests/robolectric_gradle_config/robolectric.properties
@@ -1,3 +1,3 @@
# Do not include the manifest definition in this version
# as it is specified directly in the gradle file
-sdk=27
\ No newline at end of file
+sdk=31
\ No newline at end of file
diff --git a/robolectric_tests/src/com/android/customization/model/clock/ClockManagerTest.java b/robolectric_tests/src/com/android/customization/model/clock/ClockManagerTest.java
index f431006..574548a 100644
--- a/robolectric_tests/src/com/android/customization/model/clock/ClockManagerTest.java
+++ b/robolectric_tests/src/com/android/customization/model/clock/ClockManagerTest.java
@@ -18,8 +18,8 @@
import static junit.framework.TestCase.fail;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.provider.Settings.Secure;
@@ -86,7 +86,9 @@
@Test
public void testApply_whenJSONExceptionOccurs_callsOnError() {
- when(mMockClockface.getId()).thenThrow(JSONException.class);
+ doAnswer((invocation) -> {
+ throw new JSONException("Fake Test Excepton");
+ }).when(mMockClockface).getId();
mManager.apply(mMockClockface, mMockCallback);
diff --git a/robolectric_tests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt b/robolectric_tests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt
new file mode 100644
index 0000000..f6f4227
--- /dev/null
+++ b/robolectric_tests/src/com/android/customization/model/color/ColorCustomizationManagerTest.kt
@@ -0,0 +1,175 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color
+
+import android.app.WallpaperColors
+import android.graphics.Color
+import com.android.customization.model.CustomizationManager
+import com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE
+import com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR
+import com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_HOME
+import com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_PRESET
+import com.android.customization.model.color.ColorOptionsProvider.OVERLAY_COLOR_BOTH
+import com.android.customization.model.color.ColorOptionsProvider.OVERLAY_COLOR_INDEX
+import com.android.customization.model.color.ColorOptionsProvider.OVERLAY_COLOR_SOURCE
+import com.android.customization.model.theme.OverlayManagerCompat
+import com.android.systemui.monet.Style
+import com.google.common.truth.Truth.assertThat
+import org.json.JSONObject
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.RuntimeEnvironment
+
+/**
+ * Tests of {@link ColorCustomizationManager}.
+ */
+// TODO(b/222433744): most of these tests are failing due to the manager apk missing in the image
+@RunWith(RobolectricTestRunner::class)
+class ColorCustomizationManagerTest {
+
+ @get:Rule
+ val rule: MockitoRule = MockitoJUnit.rule()
+
+ @Mock private lateinit var provider: ColorOptionsProvider
+ @Mock private lateinit var mockOM: OverlayManagerCompat
+
+ private lateinit var manager: ColorCustomizationManager
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ val application = RuntimeEnvironment.application
+ manager = ColorCustomizationManager(provider, application.contentResolver, mockOM)
+ }
+
+ @Test
+ fun testParseSettings() {
+ val source = COLOR_SOURCE_HOME
+ val style = Style.SPRITZ
+ val someColor = "aabbcc"
+ val someOtherColor = "bbccdd"
+ val settings = mapOf(OVERLAY_CATEGORY_SYSTEM_PALETTE to someColor,
+ OVERLAY_CATEGORY_COLOR to someOtherColor,
+ OVERLAY_COLOR_SOURCE to source,
+ ColorOption.TIMESTAMP_FIELD to "12345")
+ val json = JSONObject(settings).toString()
+
+ manager.parseSettings(json)
+
+ assertThat(manager.currentColorSource).isEqualTo(source)
+ assertThat(manager.currentStyle).isEqualTo(style)
+ assertThat(manager.currentOverlays.size).isEqualTo(2)
+ assertThat(manager.currentOverlays.get(OVERLAY_CATEGORY_COLOR)).isEqualTo(someOtherColor)
+ assertThat(manager.currentOverlays.get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
+ .isEqualTo(someColor)
+ }
+
+ @Test
+ fun apply_ColorBundle_index() {
+ testApplyColorBundle(1, "1")
+ testApplyColorBundle(2, "2")
+ testApplyColorBundle(3, "3")
+ testApplyColorBundle(4, "4")
+ }
+
+ private fun testApplyColorBundle(index: Int, value: String) {
+ manager.apply(getColorBundle(index), object : CustomizationManager.Callback {
+ override fun onSuccess() {}
+ override fun onError(throwable: Throwable?) {}
+ })
+
+ val overlaysJson = JSONObject(manager.storedOverlays)
+
+ assertThat(overlaysJson.getString(OVERLAY_COLOR_INDEX)).isEqualTo(value)
+ }
+
+ private fun getColorBundle(index: Int): ColorBundle {
+ return ColorBundle(
+ "fake color", mapOf("fake_package" to "fake_color"),
+ /* isDefault= */ false,
+ null,
+ /* index= */ index,
+ null
+ )
+ }
+
+ @Test
+ fun apply_ColorSeed_index() {
+ testApplyColorSeed(1, "1")
+ testApplyColorSeed(2, "2")
+ testApplyColorSeed(3, "3")
+ testApplyColorSeed(4, "4")
+ }
+
+ private fun testApplyColorSeed(index: Int, value: String) {
+ manager.apply(getColorSeed(index), object : CustomizationManager.Callback {
+ override fun onSuccess() {}
+ override fun onError(throwable: Throwable?) {}
+ })
+
+ val overlaysJson = JSONObject(manager.storedOverlays)
+ assertThat(overlaysJson.getString(OVERLAY_COLOR_INDEX)).isEqualTo(value)
+ }
+
+ private fun getColorSeed(index: Int): ColorSeedOption {
+ return ColorSeedOption(
+ "fake color",
+ mapOf("fake_package" to "fake_color"),
+ /* isDefault= */ false,
+ COLOR_SOURCE_PRESET,
+ null,
+ index,
+ null
+ )
+ }
+
+ @Test
+ fun testApply_colorSeedFromWallpaperBoth_shouldReturnBothValue() {
+ val wallpaperColor = WallpaperColors(Color.valueOf(Color.RED), null, null)
+ manager.setWallpaperColors(wallpaperColor, wallpaperColor)
+
+ manager.apply(getColorSeed(anyInt()), object : CustomizationManager.Callback {
+ override fun onSuccess() {}
+ override fun onError(throwable: Throwable?) {}
+ })
+
+ val overlaysJson = JSONObject(manager.storedOverlays)
+ assertThat(overlaysJson.getString(OVERLAY_COLOR_BOTH)).isEqualTo("1")
+ }
+
+ @Test
+ fun testApply_colorSeedFromWallpaperDifferent_shouldReturnNonBothValue() {
+ val wallpaperColor1 = WallpaperColors(Color.valueOf(Color.RED), null, null)
+ val wallpaperColor2 = WallpaperColors(Color.valueOf(Color.BLUE), null, null)
+ manager.setWallpaperColors(wallpaperColor1, wallpaperColor2)
+
+ manager.apply(getColorSeed(anyInt()), object : CustomizationManager.Callback {
+ override fun onSuccess() {}
+ override fun onError(throwable: Throwable?) {}
+ })
+
+ val overlaysJson = JSONObject(manager.storedOverlays)
+ assertThat(overlaysJson.getString(OVERLAY_COLOR_BOTH)).isEqualTo("0")
+ }
+}
diff --git a/robolectric_tests/src/com/android/customization/model/color/ColorOptionTest.kt b/robolectric_tests/src/com/android/customization/model/color/ColorOptionTest.kt
new file mode 100644
index 0000000..271aa83
--- /dev/null
+++ b/robolectric_tests/src/com/android/customization/model/color/ColorOptionTest.kt
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color
+
+import com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_HOME
+import com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_LOCK
+import com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_PRESET
+import com.android.systemui.monet.Style
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertEquals
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.robolectric.RobolectricTestRunner
+
+/**
+ * Tests of {@link ColorOption}.
+ */
+@RunWith(RobolectricTestRunner::class)
+class ColorOptionTest {
+
+ @get:Rule
+ val rule: MockitoRule = MockitoJUnit.rule()
+
+ @Mock
+ private lateinit var manager: ColorCustomizationManager
+
+ @Test
+ fun colorOption_Source_Preset() {
+ val bundleOption: ColorOption = ColorBundle("fake color",
+ mapOf("fake_package" to "fake_color"), false, null, /* index= */ 0, null)
+ assertEquals(COLOR_SOURCE_PRESET, bundleOption.source)
+ }
+
+ @Test
+ fun colorOption_bundle_index() {
+ testBundleOptionIndex(1)
+ testBundleOptionIndex(2)
+ testBundleOptionIndex(3)
+ testBundleOptionIndex(4)
+ }
+
+ private fun testBundleOptionIndex(index: Int) {
+ val bundleOption: ColorBundle = ColorBundle("fake color",
+ mapOf("fake_package" to "fake_color"), false, null, /* index= */ index, null)
+ assertThat(bundleOption.index).isEqualTo(index)
+ }
+
+ @Test
+ fun colorOption_Source_Seed() {
+ testSeedOptionSource(COLOR_SOURCE_HOME)
+ testSeedOptionSource(COLOR_SOURCE_LOCK)
+ }
+
+ private fun testSeedOptionSource(source: String) {
+ val seedOption: ColorOption = ColorSeedOption("fake color",
+ mapOf("fake_package" to "fake_color"), false, source, null, /* index= */ 0, null)
+ assertThat(seedOption.source).isEqualTo(source)
+ }
+
+ @Test
+ fun colorOption_seed_style() {
+ testSeedOptionStyle(Style.TONAL_SPOT)
+ testSeedOptionStyle(Style.SPRITZ)
+ testSeedOptionStyle(Style.VIBRANT)
+ testSeedOptionStyle(Style.EXPRESSIVE)
+ }
+
+ private fun testSeedOptionStyle(style: Style) {
+ val seedOption: ColorOption = ColorSeedOption("fake color",
+ mapOf("fake_package" to "fake_color"), /* isDefault= */ false, "fake_source", style,
+ 0, null)
+ assertThat(seedOption.style).isEqualTo(style)
+ }
+
+ @Test
+ fun colorOption_seed_index() {
+ testSeedOptionIndex(1)
+ testSeedOptionIndex(2)
+ testSeedOptionIndex(3)
+ testSeedOptionIndex(4)
+ }
+
+ private fun testSeedOptionIndex(index: Int) {
+ val seedOption: ColorOption = ColorSeedOption("fake color",
+ mapOf("fake_package" to "fake_color"),
+ /* isDefault= */ false,
+ "fake_source",
+ Style.TONAL_SPOT,
+ index,
+ /* previewInfo= */ null)
+ assertThat(seedOption.index).isEqualTo(index)
+ }
+
+ private fun setUpSeedOption(isDefault: Boolean, source: String = "some_source")
+ : ColorSeedOption {
+ val overlays = if (isDefault) {
+ HashMap()
+ } else {
+ mapOf("package" to "value", "otherPackage" to "otherValue")
+ }
+ `when`(manager.currentOverlays).thenReturn(overlays)
+ return ColorSeedOption("seed",
+ overlays,
+ isDefault,
+ source,
+ Style.TONAL_SPOT,
+ /* index= */ 0,
+ /* previewInfo= */ null)
+ }
+
+ @Test
+ fun seedOption_isActive_notDefault_SourceSet() {
+ val source = "some_source"
+ val seedOption = setUpSeedOption(false, source)
+ `when`(manager.currentColorSource).thenReturn(source)
+
+ assertThat(seedOption.isActive(manager)).isTrue()
+ }
+
+ @Test
+ fun seedOption_isActive_notDefault_NoSource() {
+ val seedOption = setUpSeedOption(false)
+ `when`(manager.currentColorSource).thenReturn(null)
+
+ assertThat(seedOption.isActive(manager)).isTrue()
+ }
+
+ @Test
+ fun seedOption_isActive_notDefault_differentSource() {
+ val seedOption = setUpSeedOption(false)
+ `when`(manager.currentColorSource).thenReturn("some_other_source")
+
+ assertThat(seedOption.isActive(manager)).isFalse()
+ }
+
+ @Test
+ fun seedOption_isActive_default_emptyJson() {
+ val seedOption = setUpSeedOption(true)
+ `when`(manager.storedOverlays).thenReturn("")
+
+ assertThat(seedOption.isActive(manager)).isTrue()
+ }
+
+ @Test
+ fun seedOption_isActive_default_nonEmptyJson() {
+ val seedOption = setUpSeedOption(true)
+
+ `when`(manager.storedOverlays).thenReturn("{non-empty-json}")
+
+ // Should still be Active because overlays is empty
+ assertThat(seedOption.isActive(manager)).isTrue()
+ }
+
+ @Test
+ fun seedOption_isActive_default_nonEmptyOverlays() {
+ val seedOption = setUpSeedOption(true)
+
+ `when`(manager.currentOverlays).thenReturn(mapOf("a" to "b"))
+ // TODO(b/222433744): failing as it's true
+ assertThat(seedOption.isActive(manager)).isFalse()
+ }
+}
diff --git a/robolectric_tests/src/com/android/customization/model/color/ColorSectionControllerTest.java b/robolectric_tests/src/com/android/customization/model/color/ColorSectionControllerTest.java
new file mode 100644
index 0000000..820e641
--- /dev/null
+++ b/robolectric_tests/src/com/android/customization/model/color/ColorSectionControllerTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.android.wallpaper.model.WallpaperColorsViewModel;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+/**
+ * Tests of {@link ColorSectionController}.
+ */
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public final class ColorSectionControllerTest {
+
+ private AppCompatActivity mActivity;
+ private ColorSectionController mColorSectionController;
+
+ /**
+ * Set up the test case.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mActivity = Robolectric.buildActivity(AppCompatActivity.class).create().get();
+ mColorSectionController = new ColorSectionController(mActivity,
+ new WallpaperColorsViewModel(), mActivity, null);
+ }
+
+ /**
+ * isAvailable()'s test.
+ */
+ @Test
+ @Config(manifest = Config.NONE)
+ public void isAvailable_nullContext_shouldReturnFalse() {
+ assertThat(mColorSectionController.isAvailable(/* context= */ null)).isFalse();
+ }
+}
+
diff --git a/robolectric_tests/src/com/android/customization/model/grid/GridOptionsManagerTest.java b/robolectric_tests/src/com/android/customization/model/grid/GridOptionsManagerTest.java
index ed47420..f954656 100644
--- a/robolectric_tests/src/com/android/customization/model/grid/GridOptionsManagerTest.java
+++ b/robolectric_tests/src/com/android/customization/model/grid/GridOptionsManagerTest.java
@@ -31,7 +31,6 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
@@ -69,7 +68,6 @@
@Test
public void testFetch_backgroundThread() {
mManager.fetchOptions(null, false);
- Robolectric.flushBackgroundThreadScheduler();
verify(mProvider).fetch(anyBoolean());
}
}
diff --git a/src/com/android/customization/model/ResourceConstants.java b/src/com/android/customization/model/ResourceConstants.java
index 86eb7f4..aaee935 100644
--- a/src/com/android/customization/model/ResourceConstants.java
+++ b/src/com/android/customization/model/ResourceConstants.java
@@ -58,6 +58,8 @@
* Overlay Categories that theme picker handles.
*/
String OVERLAY_CATEGORY_COLOR = "android.theme.customization.accent_color";
+ String OVERLAY_CATEGORY_SYSTEM_PALETTE = "android.theme.customization.system_palette";
+ String OVERLAY_CATEGORY_THEME_STYLE = "android.theme.customization.theme_style";
String OVERLAY_CATEGORY_FONT = "android.theme.customization.font";
String OVERLAY_CATEGORY_SHAPE = "android.theme.customization.adaptive_icon_shape";
String OVERLAY_CATEGORY_ICON_ANDROID = "android.theme.customization.icon_pack.android";
@@ -88,6 +90,14 @@
"ic_battery_80_24dp"
};
+ /**
+ * Color bundle strings used to reference system resources.
+ */
+ String COLOR_BUNDLES_ARRAY_NAME = "color_bundles";
+ String COLOR_BUNDLE_NAME_PREFIX = "bundle_name_";
+ String COLOR_BUNDLE_MAIN_COLOR_PREFIX = "color_secondary_";
+ String COLOR_BUNDLE_STYLE_PREFIX = "color_style_";
+
ArrayList<String> sTargetPackages = new ArrayList<>();
String ACCENT_COLOR_LIGHT_NAME = "accent_device_default_light";
String ACCENT_COLOR_DARK_NAME = "accent_device_default_dark";
diff --git a/src/com/android/customization/model/clock/ContentProviderClockProvider.java b/src/com/android/customization/model/clock/ContentProviderClockProvider.java
index 8f4c031..f0df031 100644
--- a/src/com/android/customization/model/clock/ContentProviderClockProvider.java
+++ b/src/com/android/customization/model/clock/ContentProviderClockProvider.java
@@ -8,8 +8,10 @@
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
-import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
import android.text.TextUtils;
+import android.util.Log;
import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
import com.android.customization.model.clock.Clockface.Builder;
@@ -21,9 +23,19 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
public class ContentProviderClockProvider implements ClockProvider {
+ private static final String TAG = "ContentProviderClockProvider";
+ private static final ExecutorService sExecutorService = Executors.newSingleThreadExecutor();
+ private static final String LIST_OPTIONS = "list_options";
+ private static final String COL_TITLE = "title";
+ private static final String COL_ID = "id";
+ private static final String COL_THUMBNAIL = "thumbnail";
+ private static final String COL_PREVIEW = "preview";
+
private final Context mContext;
private final ProviderInfo mProviderInfo;
private List<Clockface> mClocks;
@@ -75,42 +87,7 @@
}
return;
}
- new ClocksFetchTask(mContext, mProviderInfo, options -> {
- mClocks = options;
- if (callback != null) {
- if (!mClocks.isEmpty()) {
- callback.onOptionsLoaded(mClocks);
- } else {
- callback.onError(null);
- }
- }
- }).execute();
- }
-
- private static class ClocksFetchTask extends AsyncTask<Void, Void, List<Clockface>> {
-
- private static final String LIST_OPTIONS = "list_options";
-
- private static final String COL_NAME = "name";
- private static final String COL_TITLE = "title";
- private static final String COL_ID = "id";
- private static final String COL_THUMBNAIL = "thumbnail";
- private static final String COL_PREVIEW = "preview";
-
- private final OptionsFetchedListener<Clockface> mCallback;
- private Context mContext;
- private final ProviderInfo mProviderInfo;
-
- public ClocksFetchTask(Context context, ProviderInfo providerInfo,
- OptionsFetchedListener<Clockface> callback) {
- super();
- mContext = context;
- mProviderInfo = providerInfo;
- mCallback = callback;
- }
-
- @Override
- protected List<Clockface> doInBackground(Void... voids) {
+ sExecutorService.submit(() -> {
Uri optionsUri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(mProviderInfo.authority)
@@ -121,7 +98,7 @@
List<Clockface> clockfaces = new ArrayList<>();
try (Cursor c = resolver.query(optionsUri, null, null, null, null)) {
- while(c.moveToNext()) {
+ while (c != null && c.moveToNext()) {
String id = c.getString(c.getColumnIndex(COL_ID));
String title = c.getString(c.getColumnIndex(COL_TITLE));
String thumbnailUri = c.getString(c.getColumnIndex(COL_THUMBNAIL));
@@ -140,16 +117,19 @@
Glide.get(mContext).clearDiskCache();
} catch (Exception e) {
clockfaces = null;
- } finally {
- mContext = null;
+ Log.e(TAG, "Failed to query clock face options.", e);
}
- return clockfaces;
- }
-
- @Override
- protected void onPostExecute(List<Clockface> clockfaces) {
- super.onPostExecute(clockfaces);
- mCallback.onOptionsLoaded(clockfaces);
- }
+ final List<Clockface> clockfaceList = clockfaces;
+ new Handler(Looper.getMainLooper()).post(() -> {
+ mClocks = clockfaceList;
+ if (callback != null) {
+ if (!mClocks.isEmpty()) {
+ callback.onOptionsLoaded(mClocks);
+ } else {
+ callback.onError(null);
+ }
+ }
+ });
+ });
}
}
diff --git a/src/com/android/customization/model/color/ColorBundle.java b/src/com/android/customization/model/color/ColorBundle.java
new file mode 100644
index 0000000..dc5a367
--- /dev/null
+++ b/src/com/android/customization/model/color/ColorBundle.java
@@ -0,0 +1,350 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color;
+
+import static com.android.customization.model.ResourceConstants.PATH_SIZE;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.Path;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.PathShape;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.ImageView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.Dimension;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.core.graphics.PathParser;
+
+import com.android.customization.model.ResourceConstants;
+import com.android.systemui.monet.Style;
+import com.android.wallpaper.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents a preset color available for the user to chose as their theming option.
+ */
+public class ColorBundle extends ColorOption {
+
+ private final PreviewInfo mPreviewInfo;
+
+ @VisibleForTesting ColorBundle(String title,
+ Map<String, String> overlayPackages, boolean isDefault, Style style, int index,
+ PreviewInfo previewInfo) {
+ super(title, overlayPackages, isDefault, style, index);
+ mPreviewInfo = previewInfo;
+ }
+
+ @Override
+ public void bindThumbnailTile(View view) {
+ Resources res = view.getContext().getResources();
+ int primaryColor = mPreviewInfo.resolvePrimaryColor(res);
+ int secondaryColor = mPreviewInfo.resolveSecondaryColor(res);
+ int padding = view.isActivated()
+ ? res.getDimensionPixelSize(R.dimen.color_seed_option_tile_padding_selected)
+ : res.getDimensionPixelSize(R.dimen.color_seed_option_tile_padding);
+
+ for (int i = 0; i < mPreviewColorIds.length; i++) {
+ ImageView colorPreviewImageView = view.findViewById(mPreviewColorIds[i]);
+ int color = i % 2 == 0 ? primaryColor : secondaryColor;
+ colorPreviewImageView.getDrawable().setColorFilter(color, PorterDuff.Mode.SRC);
+ colorPreviewImageView.setPadding(padding, padding, padding, padding);
+ }
+ view.setContentDescription(getContentDescription(view.getContext()));
+ }
+
+ @Override
+ public PreviewInfo getPreviewInfo() {
+ return mPreviewInfo;
+ }
+
+ @Override
+ public int getLayoutResId() {
+ return R.layout.color_option;
+ }
+
+ @Override
+ public String getSource() {
+ return ColorOptionsProvider.COLOR_SOURCE_PRESET;
+ }
+
+ /**
+ * The preview information of {@link ColorBundle}
+ */
+ public static class PreviewInfo implements ColorOption.PreviewInfo {
+ @ColorInt
+ public final int secondaryColorLight;
+ @ColorInt public final int secondaryColorDark;
+ // Monet system palette and accent colors
+ @ColorInt public final int primaryColorLight;
+ @ColorInt public final int primaryColorDark;
+ public final List<Drawable> icons;
+ public final Drawable shapeDrawable;
+ @Dimension
+ public final int bottomSheetCornerRadius;
+
+ @ColorInt private int mOverrideSecondaryColorLight = Color.TRANSPARENT;
+ @ColorInt private int mOverrideSecondaryColorDark = Color.TRANSPARENT;
+ @ColorInt private int mOverridePrimaryColorLight = Color.TRANSPARENT;
+ @ColorInt private int mOverridePrimaryColorDark = Color.TRANSPARENT;
+
+ private PreviewInfo(
+ int secondaryColorLight, int secondaryColorDark, int colorSystemPaletteLight,
+ int primaryColorDark, List<Drawable> icons, Drawable shapeDrawable,
+ @Dimension int cornerRadius) {
+ this.secondaryColorLight = secondaryColorLight;
+ this.secondaryColorDark = secondaryColorDark;
+ this.primaryColorLight = colorSystemPaletteLight;
+ this.primaryColorDark = primaryColorDark;
+ this.icons = icons;
+ this.shapeDrawable = shapeDrawable;
+ this.bottomSheetCornerRadius = cornerRadius;
+ }
+
+ /**
+ * Returns the accent color to be applied corresponding with the current configuration's
+ * UI mode.
+ * @return one of {@link #secondaryColorDark} or {@link #secondaryColorLight}
+ */
+ @ColorInt
+ public int resolveSecondaryColor(Resources res) {
+ boolean night = (res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES;
+ if (mOverrideSecondaryColorDark != Color.TRANSPARENT
+ || mOverrideSecondaryColorLight != Color.TRANSPARENT) {
+ return night ? mOverrideSecondaryColorDark : mOverrideSecondaryColorLight;
+ }
+ return night ? secondaryColorDark : secondaryColorLight;
+ }
+
+ /**
+ * Returns the palette (main) color to be applied corresponding with the current
+ * configuration's UI mode.
+ * @return one of {@link #secondaryColorDark} or {@link #secondaryColorLight}
+ */
+ @ColorInt
+ public int resolvePrimaryColor(Resources res) {
+ boolean night = (res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES;
+ if (mOverridePrimaryColorDark != Color.TRANSPARENT
+ || mOverridePrimaryColorLight != Color.TRANSPARENT) {
+ return night ? mOverridePrimaryColorDark : mOverridePrimaryColorLight;
+ }
+ return night ? primaryColorDark
+ : primaryColorLight;
+ }
+
+ /**
+ * Sets accent colors to override the ones in this bundle
+ */
+ public void setOverrideAccentColors(int overrideColorAccentLight,
+ int overrideColorAccentDark) {
+ mOverrideSecondaryColorLight = overrideColorAccentLight;
+ mOverrideSecondaryColorDark = overrideColorAccentDark;
+ }
+
+ /**
+ * Sets palette colors to override the ones in this bundle
+ */
+ public void setOverridePaletteColors(int overrideColorPaletteLight,
+ int overrideColorPaletteDark) {
+ mOverridePrimaryColorLight = overrideColorPaletteLight;
+ mOverridePrimaryColorDark = overrideColorPaletteDark;
+ }
+ }
+
+ /**
+ * The builder of ColorBundle
+ */
+ public static class Builder {
+ protected String mTitle;
+ @ColorInt private int mSecondaryColorLight = Color.TRANSPARENT;
+ @ColorInt private int mSecondaryColorDark = Color.TRANSPARENT;
+ // System and Monet colors
+ @ColorInt private int mPrimaryColorLight = Color.TRANSPARENT;
+ @ColorInt private int mPrimaryColorDark = Color.TRANSPARENT;
+ private List<Drawable> mIcons = new ArrayList<>();
+ private boolean mIsDefault;
+ private Style mStyle = Style.TONAL_SPOT;
+ private int mIndex;
+ protected Map<String, String> mPackages = new HashMap<>();
+
+ /**
+ * Builds the ColorBundle
+ * @param context {@link Context}
+ * @return new {@link ColorBundle} object
+ */
+ public ColorBundle build(Context context) {
+ if (mTitle == null) {
+ mTitle = context.getString(R.string.adaptive_color_title);
+ }
+ return new ColorBundle(mTitle, mPackages, mIsDefault, mStyle, mIndex,
+ createPreviewInfo(context));
+ }
+
+ /**
+ * Creates preview information
+ * @param context the {@link Context}
+ * @return the {@link PreviewInfo} object
+ */
+ public PreviewInfo createPreviewInfo(@NonNull Context context) {
+ ShapeDrawable shapeDrawable = null;
+ Resources system = context.getResources().getSystem();
+ String pathString = system.getString(
+ system.getIdentifier(ResourceConstants.CONFIG_ICON_MASK,
+ "string", ResourceConstants.ANDROID_PACKAGE));
+ Path path = null;
+ if (!TextUtils.isEmpty(pathString)) {
+ path = PathParser.createPathFromPathData(pathString);
+ }
+ if (path != null) {
+ PathShape shape = new PathShape(path, PATH_SIZE, PATH_SIZE);
+ shapeDrawable = new ShapeDrawable(shape);
+ shapeDrawable.setIntrinsicHeight((int) PATH_SIZE);
+ shapeDrawable.setIntrinsicWidth((int) PATH_SIZE);
+ }
+ return new PreviewInfo(mSecondaryColorLight,
+ mSecondaryColorDark, mPrimaryColorLight, mPrimaryColorDark, mIcons,
+ shapeDrawable, system.getDimensionPixelOffset(
+ system.getIdentifier(ResourceConstants.CONFIG_CORNERRADIUS,
+ "dimen", ResourceConstants.ANDROID_PACKAGE)));
+ }
+
+ public Map<String, String> getPackages() {
+ return Collections.unmodifiableMap(mPackages);
+ }
+
+ /**
+ * Gets title of this {@link ColorBundle} object
+ * @return title string
+ */
+ public String getTitle() {
+ return mTitle;
+ }
+
+ /**
+ * Sets title of bundle
+ * @param title specified title
+ * @return this of {@link Builder}
+ */
+ public Builder setTitle(String title) {
+ mTitle = title;
+ return this;
+ }
+
+ /**
+ * Sets color accent (light)
+ * @param colorSecondaryLight color accent light in {@link ColorInt}
+ * @return this of {@link Builder}
+ */
+ public Builder setColorSecondaryLight(@ColorInt int colorSecondaryLight) {
+ mSecondaryColorLight = colorSecondaryLight;
+ return this;
+ }
+
+ /**
+ * Sets color accent (dark)
+ * @param colorSecondaryDark color accent dark in {@link ColorInt}
+ * @return this of {@link Builder}
+ */
+ public Builder setColorSecondaryDark(@ColorInt int colorSecondaryDark) {
+ mSecondaryColorDark = colorSecondaryDark;
+ return this;
+ }
+
+ /**
+ * Sets color system palette (light)
+ * @param colorPrimaryLight color system palette in {@link ColorInt}
+ * @return this of {@link Builder}
+ */
+ public Builder setColorPrimaryLight(@ColorInt int colorPrimaryLight) {
+ mPrimaryColorLight = colorPrimaryLight;
+ return this;
+ }
+
+ /**
+ * Sets color system palette (dark)
+ * @param colorPrimaryDark color system palette in {@link ColorInt}
+ * @return this of {@link Builder}
+ */
+ public Builder setColorPrimaryDark(@ColorInt int colorPrimaryDark) {
+ mPrimaryColorDark = colorPrimaryDark;
+ return this;
+ }
+
+ /**
+ * Sets icon for bundle
+ * @param icon icon in {@link Drawable}
+ * @return this of {@link Builder}
+ */
+ public Builder addIcon(Drawable icon) {
+ mIcons.add(icon);
+ return this;
+ }
+
+ /**
+ * Sets overlay package for bundle
+ * @param category the category of bundle
+ * @param packageName tha name of package in the category
+ * @return this of {@link Builder}
+ */
+ public Builder addOverlayPackage(String category, String packageName) {
+ mPackages.put(category, packageName);
+ return this;
+ }
+
+ /**
+ * Sets the style of this color seed
+ * @param style color style of {@link Style}
+ * @return this of {@link Builder}
+ */
+ public Builder setStyle(Style style) {
+ mStyle = style;
+ return this;
+ }
+
+ /**
+ * Sets color option index of bundle
+ * @param index color option index
+ * @return this of {@link Builder}
+ */
+ public Builder setIndex(int index) {
+ mIndex = index;
+ return this;
+ }
+
+ /**
+ * Sets as default bundle
+ * @return this of {@link Builder}
+ */
+ public Builder asDefault() {
+ mIsDefault = true;
+ return this;
+ }
+ }
+}
diff --git a/src/com/android/customization/model/color/ColorBundlePreviewExtractor.java b/src/com/android/customization/model/color/ColorBundlePreviewExtractor.java
new file mode 100644
index 0000000..b67eec8
--- /dev/null
+++ b/src/com/android/customization/model/color/ColorBundlePreviewExtractor.java
@@ -0,0 +1,105 @@
+/**
+ * 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.
+ */
+package com.android.customization.model.color;
+
+import static com.android.customization.model.ResourceConstants.ANDROID_PACKAGE;
+import static com.android.customization.model.ResourceConstants.ICONS_FOR_PREVIEW;
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE;
+import static com.android.customization.model.color.ColorUtils.toColorString;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.ColorInt;
+
+import com.android.systemui.monet.ColorScheme;
+import com.android.systemui.monet.Style;
+
+/**
+ * Utility class to read all the details of a color bundle for previewing it
+ * (eg, actual color values)
+ */
+class ColorBundlePreviewExtractor {
+
+ private static final String TAG = "ColorBundlePreviewExtractor";
+
+ private final PackageManager mPackageManager;
+
+ ColorBundlePreviewExtractor(Context context) {
+ mPackageManager = context.getPackageManager();
+ }
+
+ void addSecondaryColor(ColorBundle.Builder builder, @ColorInt int color) {
+ ColorScheme darkColorScheme = new ColorScheme(color, true);
+ ColorScheme lightColorScheme = new ColorScheme(color, false);
+ int lightSecondary = lightColorScheme.getAccentColor();
+ int darkSecondary = darkColorScheme.getAccentColor();
+ builder.addOverlayPackage(OVERLAY_CATEGORY_COLOR, toColorString(color))
+ .setColorSecondaryLight(lightSecondary)
+ .setColorSecondaryDark(darkSecondary);
+ }
+
+ void addPrimaryColor(ColorBundle.Builder builder, @ColorInt int color) {
+ ColorScheme darkColorScheme = new ColorScheme(color, true);
+ ColorScheme lightColorScheme = new ColorScheme(color, false);
+ int lightPrimary = lightColorScheme.getAccentColor();
+ int darkPrimary = darkColorScheme.getAccentColor();
+ builder.addOverlayPackage(OVERLAY_CATEGORY_SYSTEM_PALETTE, toColorString(color))
+ .setColorPrimaryLight(lightPrimary)
+ .setColorPrimaryDark(darkPrimary);
+ }
+
+ void addColorStyle(ColorBundle.Builder builder, String styleName) {
+ Style s = Style.TONAL_SPOT;
+ if (!TextUtils.isEmpty(styleName)) {
+ try {
+ s = Style.valueOf(styleName);
+ } catch (IllegalArgumentException e) {
+ Log.i(TAG, "Unknown style : " + styleName + ". Will default to TONAL_SPOT.");
+ }
+ }
+ builder.setStyle(s);
+ }
+
+ void addAndroidIconOverlay(ColorBundle.Builder builder) throws NameNotFoundException {
+ addSystemDefaultIcons(builder, ICONS_FOR_PREVIEW);
+ }
+
+ void addSystemDefaultIcons(ColorBundle.Builder builder, String... previewIcons) {
+ try {
+ for (String iconName : previewIcons) {
+ builder.addIcon(loadIconPreviewDrawable(iconName));
+ }
+ } catch (NameNotFoundException | NotFoundException e) {
+ Log.w(TAG, "Didn't find android package icons, will skip preview", e);
+ }
+ }
+
+ Drawable loadIconPreviewDrawable(String drawableName)
+ throws NameNotFoundException, NotFoundException {
+ Resources packageRes = mPackageManager.getResourcesForApplication(ANDROID_PACKAGE);
+ Resources res = Resources.getSystem();
+ return res.getDrawable(packageRes.getIdentifier(drawableName, "drawable",
+ ANDROID_PACKAGE), null);
+ }
+}
diff --git a/src/com/android/customization/model/color/ColorCustomizationManager.java b/src/com/android/customization/model/color/ColorCustomizationManager.java
new file mode 100644
index 0000000..908480f
--- /dev/null
+++ b/src/com/android/customization/model/color/ColorCustomizationManager.java
@@ -0,0 +1,268 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color;
+
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE;
+import static com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_PRESET;
+import static com.android.customization.model.color.ColorOptionsProvider.OVERLAY_COLOR_BOTH;
+import static com.android.customization.model.color.ColorOptionsProvider.OVERLAY_COLOR_INDEX;
+import static com.android.customization.model.color.ColorOptionsProvider.OVERLAY_COLOR_SOURCE;
+import static com.android.customization.model.color.ColorOptionsProvider.OVERLAY_THEME_STYLE;
+
+import android.app.WallpaperColors;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.customization.model.CustomizationManager;
+import com.android.customization.model.ResourceConstants;
+import com.android.customization.model.color.ColorOptionsProvider.ColorSource;
+import com.android.customization.model.theme.OverlayManagerCompat;
+import com.android.wallpaper.R;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/** The Color manager to manage Color bundle related operations. */
+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 {
+ COLOR_OVERLAY_SETTINGS.add(OVERLAY_CATEGORY_SYSTEM_PALETTE);
+ COLOR_OVERLAY_SETTINGS.add(OVERLAY_CATEGORY_COLOR);
+ COLOR_OVERLAY_SETTINGS.add(OVERLAY_COLOR_SOURCE);
+ COLOR_OVERLAY_SETTINGS.add(OVERLAY_THEME_STYLE);
+ }
+
+ private static ColorCustomizationManager sColorCustomizationManager;
+
+ private final ColorOptionsProvider mProvider;
+ private final OverlayManagerCompat mOverlayManagerCompat;
+ private final ContentResolver mContentResolver;
+ private final ContentObserver mObserver;
+
+ private Map<String, String> mCurrentOverlays;
+ @ColorSource private String mCurrentSource;
+ private String mCurrentStyle;
+ private WallpaperColors mHomeWallpaperColors;
+ private WallpaperColors mLockWallpaperColors;
+
+ /** Returns the {@link ColorCustomizationManager} instance. */
+ public static ColorCustomizationManager getInstance(Context context,
+ OverlayManagerCompat overlayManagerCompat) {
+ if (sColorCustomizationManager == null) {
+ Context appContext = context.getApplicationContext();
+ sColorCustomizationManager = new ColorCustomizationManager(
+ new ColorProvider(appContext,
+ appContext.getString(R.string.themes_stub_package)),
+ appContext.getContentResolver(), overlayManagerCompat);
+ }
+ return sColorCustomizationManager;
+ }
+
+ @VisibleForTesting
+ ColorCustomizationManager(ColorOptionsProvider provider, ContentResolver contentResolver,
+ OverlayManagerCompat overlayManagerCompat) {
+ mProvider = provider;
+ mContentResolver = contentResolver;
+ mObserver = new ContentObserver(/* handler= */ null) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ // Resets current overlays when system's theme setting is changed.
+ if (TextUtils.equals(uri.getLastPathSegment(), ResourceConstants.THEME_SETTING)) {
+ Log.i(TAG, "Resetting " + mCurrentOverlays + ", " + mCurrentStyle + ", "
+ + mCurrentSource + " to null");
+ mCurrentOverlays = null;
+ mCurrentStyle = null;
+ mCurrentSource = null;
+ }
+ }
+ };
+ mContentResolver.registerContentObserver(
+ Settings.Secure.CONTENT_URI, /* notifyForDescendants= */ true, mObserver);
+ mOverlayManagerCompat = overlayManagerCompat;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mOverlayManagerCompat.isAvailable() && mProvider.isAvailable();
+ }
+
+ @Override
+ public void apply(ColorOption theme, Callback callback) {
+ applyOverlays(theme, callback);
+ }
+
+ private void applyOverlays(ColorOption colorOption, Callback callback) {
+ sExecutorService.submit(() -> {
+ String currentStoredOverlays = getStoredOverlays();
+ if (TextUtils.isEmpty(currentStoredOverlays)) {
+ currentStoredOverlays = "{}";
+ }
+ JSONObject overlaysJson = null;
+ try {
+ overlaysJson = new JSONObject(currentStoredOverlays);
+ JSONObject colorJson = colorOption.getJsonPackages(true);
+ for (String setting : COLOR_OVERLAY_SETTINGS) {
+ overlaysJson.remove(setting);
+ }
+ for (Iterator<String> it = colorJson.keys(); it.hasNext(); ) {
+ String key = it.next();
+ overlaysJson.put(key, colorJson.get(key));
+ }
+ overlaysJson.put(OVERLAY_COLOR_SOURCE, colorOption.getSource());
+ overlaysJson.put(OVERLAY_COLOR_INDEX, String.valueOf(colorOption.getIndex()));
+ overlaysJson.put(OVERLAY_THEME_STYLE,
+ String.valueOf(colorOption.getStyle().toString()));
+
+ // OVERLAY_COLOR_BOTH is only for wallpaper color case, not preset.
+ if (!COLOR_SOURCE_PRESET.equals(colorOption.getSource())) {
+ boolean isForBoth =
+ (mLockWallpaperColors == null || mLockWallpaperColors.equals(
+ mHomeWallpaperColors));
+ overlaysJson.put(OVERLAY_COLOR_BOTH, isForBoth ? "1" : "0");
+ } else {
+ overlaysJson.remove(OVERLAY_COLOR_BOTH);
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ boolean allApplied = overlaysJson != null && Settings.Secure.putString(
+ mContentResolver, ResourceConstants.THEME_SETTING, overlaysJson.toString());
+ new Handler(Looper.getMainLooper()).post(() -> {
+ if (allApplied) {
+ callback.onSuccess();
+ } else {
+ callback.onError(null);
+ }
+ });
+ });
+ }
+
+ @Override
+ public void fetchOptions(OptionsFetchedListener<ColorOption> callback, boolean reload) {
+ WallpaperColors lockWallpaperColors = mLockWallpaperColors;
+ if (lockWallpaperColors != null && mLockWallpaperColors.equals(mHomeWallpaperColors)) {
+ lockWallpaperColors = null;
+ }
+ mProvider.fetch(callback, reload, mHomeWallpaperColors, lockWallpaperColors);
+ }
+
+ /**
+ * Sets the current wallpaper colors to extract seeds from
+ */
+ public void setWallpaperColors(WallpaperColors homeColors,
+ @Nullable WallpaperColors lockColors) {
+ mHomeWallpaperColors = homeColors;
+ mLockWallpaperColors = lockColors;
+ }
+
+ /**
+ * Gets current overlays mapping
+ * @return the {@link Map} of overlays
+ */
+ public Map<String, String> getCurrentOverlays() {
+ if (mCurrentOverlays == null) {
+ parseSettings(getStoredOverlays());
+ }
+ return mCurrentOverlays;
+ }
+
+ /**
+ * @return The source of the currently applied color. One of
+ * {@link ColorOptionsProvider#COLOR_SOURCE_HOME},{@link ColorOptionsProvider#COLOR_SOURCE_LOCK}
+ * or {@link ColorOptionsProvider#COLOR_SOURCE_PRESET}.
+ */
+ @ColorSource
+ public String getCurrentColorSource() {
+ if (mCurrentSource == null) {
+ parseSettings(getStoredOverlays());
+ }
+ return mCurrentSource;
+ }
+
+ /**
+ * @return The style of the currently applied color. One of enum values in
+ * {@link com.android.systemui.monet.Style}.
+ */
+ public String getCurrentStyle() {
+ if (mCurrentStyle == null) {
+ parseSettings(getStoredOverlays());
+ }
+ return mCurrentStyle;
+ }
+
+ public String getStoredOverlays() {
+ return Settings.Secure.getString(mContentResolver, ResourceConstants.THEME_SETTING);
+ }
+
+ @VisibleForTesting
+ void parseSettings(String serializedJson) {
+ Map<String, String> allSettings = parseColorSettings(serializedJson);
+ mCurrentSource = allSettings.remove(OVERLAY_COLOR_SOURCE);
+ mCurrentStyle = allSettings.remove(OVERLAY_THEME_STYLE);
+ mCurrentOverlays = allSettings;
+ }
+
+ private Map<String, String> parseColorSettings(String serializedJsonSettings) {
+ Map<String, String> overlayPackages = new HashMap<>();
+ if (serializedJsonSettings != null) {
+ try {
+ final JSONObject jsonPackages = new JSONObject(serializedJsonSettings);
+
+ JSONArray names = jsonPackages.names();
+ if (names != null) {
+ for (int i = 0; i < names.length(); i++) {
+ String category = names.getString(i);
+ if (COLOR_OVERLAY_SETTINGS.contains(category)) {
+ try {
+ overlayPackages.put(category, jsonPackages.getString(category));
+ } catch (JSONException e) {
+ Log.e(TAG, "parseColorOverlays: " + e.getLocalizedMessage(), e);
+ }
+ }
+ }
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "parseColorOverlays: " + e.getLocalizedMessage(), e);
+ }
+ }
+ return overlayPackages;
+ }
+}
diff --git a/src/com/android/customization/model/color/ColorOption.java b/src/com/android/customization/model/color/ColorOption.java
new file mode 100644
index 0000000..c8b28c2
--- /dev/null
+++ b/src/com/android/customization/model/color/ColorOption.java
@@ -0,0 +1,223 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color;
+
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.customization.model.CustomizationManager;
+import com.android.customization.model.CustomizationOption;
+import com.android.customization.model.color.ColorOptionsProvider.ColorSource;
+import com.android.systemui.monet.Style;
+import com.android.wallpaper.R;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Represents a color choice for the user.
+ * This could be a preset color or those obtained from a wallpaper.
+ */
+public abstract class ColorOption implements CustomizationOption<ColorOption> {
+
+ private static final String TAG = "ColorOption";
+ private static final String EMPTY_JSON = "{}";
+ @VisibleForTesting
+ static final String TIMESTAMP_FIELD = "_applied_timestamp";
+
+ protected final Map<String, String> mPackagesByCategory;
+ protected final int[] mPreviewColorIds = {R.id.color_preview_0, R.id.color_preview_1,
+ R.id.color_preview_2, R.id.color_preview_3};
+ private final String mTitle;
+ private final boolean mIsDefault;
+ private final Style mStyle;
+ private final int mIndex;
+ private CharSequence mContentDescription;
+
+ protected ColorOption(String title, Map<String, String> overlayPackages, boolean isDefault,
+ Style style, int index) {
+ mTitle = title;
+ mIsDefault = isDefault;
+ mStyle = style;
+ mIndex = index;
+ mPackagesByCategory = Collections.unmodifiableMap(removeNullValues(overlayPackages));
+ }
+
+ @Override
+ public String getTitle() {
+ return mTitle;
+ }
+
+ @Override
+ public boolean isActive(CustomizationManager<ColorOption> manager) {
+ ColorCustomizationManager colorManager = (ColorCustomizationManager) manager;
+
+ String currentStyle = colorManager.getCurrentStyle();
+ if (TextUtils.isEmpty(currentStyle)) {
+ currentStyle = Style.TONAL_SPOT.toString();
+ }
+ boolean isCurrentStyle = TextUtils.equals(getStyle().toString(), currentStyle);
+
+ if (mIsDefault) {
+ String serializedOverlays = colorManager.getStoredOverlays();
+ return (TextUtils.isEmpty(serializedOverlays) || EMPTY_JSON.equals(serializedOverlays)
+ || colorManager.getCurrentOverlays().isEmpty() || !(serializedOverlays.contains(
+ OVERLAY_CATEGORY_SYSTEM_PALETTE) || serializedOverlays.contains(
+ OVERLAY_CATEGORY_COLOR))) && isCurrentStyle;
+ } else {
+ Map<String, String> currentOverlays = colorManager.getCurrentOverlays();
+ String currentSource = colorManager.getCurrentColorSource();
+ boolean isCurrentSource = TextUtils.isEmpty(currentSource) || getSource().equals(
+ currentSource);
+ return isCurrentSource && isCurrentStyle && mPackagesByCategory.equals(currentOverlays);
+ }
+ }
+
+ /**
+ * This is similar to #equals() but it only compares this theme's packages with the other, that
+ * is, it will return true if applying this theme has the same effect of applying the given one.
+ */
+ public boolean isEquivalent(ColorOption other) {
+ if (other == null) {
+ return false;
+ }
+ if (mIsDefault) {
+ return other.isDefault() || TextUtils.isEmpty(other.getSerializedPackages())
+ || EMPTY_JSON.equals(other.getSerializedPackages());
+ }
+ // Map#equals ensures keys and values are compared.
+ return mPackagesByCategory.equals(other.mPackagesByCategory);
+ }
+
+ /**
+ * Returns the {@link PreviewInfo} object for this ColorOption
+ */
+ public abstract PreviewInfo getPreviewInfo();
+
+ boolean isDefault() {
+ return mIsDefault;
+ }
+
+ public Map<String, String> getPackagesByCategory() {
+ return mPackagesByCategory;
+ }
+
+ public String getSerializedPackages() {
+ return getJsonPackages(false).toString();
+ }
+
+ public String getSerializedPackagesWithTimestamp() {
+ return getJsonPackages(true).toString();
+ }
+
+ /**
+ * Get a JSONObject representation of this color option, with the current values for each
+ * field, and optionally a {@link TIMESTAMP_FIELD} field.
+ * @param insertTimestamp whether to add a field with the current timestamp
+ * @return the JSONObject for this color option
+ */
+ public JSONObject getJsonPackages(boolean insertTimestamp) {
+ JSONObject json;
+ if (isDefault()) {
+ json = new JSONObject();
+ } else {
+ json = new JSONObject(mPackagesByCategory);
+ // Remove items with null values to avoid deserialization issues.
+ removeNullValues(json);
+ }
+ if (insertTimestamp) {
+ try {
+ json.put(TIMESTAMP_FIELD, System.currentTimeMillis());
+ } catch (JSONException e) {
+ Log.e(TAG, "Couldn't add timestamp to serialized themebundle");
+ }
+ }
+ return json;
+ }
+
+ private void removeNullValues(JSONObject json) {
+ Iterator<String> keys = json.keys();
+ Set<String> keysToRemove = new HashSet<>();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ if (json.isNull(key)) {
+ keysToRemove.add(key);
+ }
+ }
+ for (String key : keysToRemove) {
+ json.remove(key);
+ }
+ }
+
+ private Map<String, String> removeNullValues(Map<String, String> map) {
+ return map.entrySet()
+ .stream()
+ .filter(entry -> entry.getValue() != null)
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+ }
+
+ protected CharSequence getContentDescription(Context context) {
+ if (mContentDescription == null) {
+ CharSequence defaultName = context.getString(R.string.default_theme_title);
+ if (isDefault()) {
+ mContentDescription = defaultName;
+ } else {
+ mContentDescription = mTitle;
+ }
+ }
+ return mContentDescription;
+ }
+
+ /**
+ * @return the source of this color option
+ */
+ @ColorSource
+ public abstract String getSource();
+
+ /**
+ * @return the style of this color option
+ */
+ public Style getStyle() {
+ return mStyle;
+ }
+
+ /**
+ * @return the index of this color option
+ */
+ public int getIndex() {
+ return mIndex;
+ }
+
+ /**
+ * The preview information of {@link ColorOption}
+ */
+ public interface PreviewInfo {
+ }
+
+}
diff --git a/src/com/android/customization/model/color/ColorOptionsProvider.java b/src/com/android/customization/model/color/ColorOptionsProvider.java
new file mode 100644
index 0000000..2803c7b
--- /dev/null
+++ b/src/com/android/customization/model/color/ColorOptionsProvider.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color;
+
+import android.app.WallpaperColors;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.StringDef;
+
+import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
+
+/**
+ * Interface for a class that can retrieve Colors from the system.
+ */
+public interface ColorOptionsProvider {
+
+ /**
+ * Extra setting indicating the source of the color overlays (it can be one of
+ * COLOR_SOURCE_PRESET, COLOR_SOURCE_HOME or COLOR_SOURCE_LOCK)
+ */
+ String OVERLAY_COLOR_SOURCE = "android.theme.customization.color_source";
+
+ /**
+ * Extra setting indicating the style of the color overlays (it can be one of
+ * {@link com.android.systemui.monet.Style}).
+ */
+ String OVERLAY_THEME_STYLE = "android.theme.customization.theme_style";
+
+ /**
+ * Users selected color option, its value starts from 1 (which means first option).
+ */
+ String OVERLAY_COLOR_INDEX = "android.theme.customization.color_index";
+
+ /**
+ * Users selected color from both home and lock screen.
+ * Example value: 0 means home or lock screen, 1 means both.
+ */
+ String OVERLAY_COLOR_BOTH = "android.theme.customization.color_both";
+
+ String COLOR_SOURCE_PRESET = "preset";
+ String COLOR_SOURCE_HOME = "home_wallpaper";
+ String COLOR_SOURCE_LOCK = "lock_wallpaper";
+
+ @StringDef({COLOR_SOURCE_PRESET, COLOR_SOURCE_HOME, COLOR_SOURCE_LOCK})
+ @interface ColorSource{}
+
+
+ /**
+ * Returns whether themes are available in the current setup.
+ */
+ boolean isAvailable();
+
+ /**
+ * Retrieve the available themes.
+ * @param callback called when the themes have been retrieved (or immediately if cached)
+ * @param reload whether to reload themes if they're cached.
+ * @param homeWallpaperColors to get seed colors from
+ * @param lockWallpaperColors WallpaperColors from the lockscreen wallpaper to get seeds from,
+ * if different than homeWallpaperColors
+ */
+ void fetch(OptionsFetchedListener<ColorOption> callback, boolean reload,
+ @Nullable WallpaperColors homeWallpaperColors,
+ @Nullable WallpaperColors lockWallpaperColors);
+}
diff --git a/src/com/android/customization/model/color/ColorProvider.kt b/src/com/android/customization/model/color/ColorProvider.kt
new file mode 100644
index 0000000..a63f904
--- /dev/null
+++ b/src/com/android/customization/model/color/ColorProvider.kt
@@ -0,0 +1,281 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color
+
+import android.app.WallpaperColors
+import android.content.Context
+import android.content.res.ColorStateList
+import android.content.res.Resources
+import android.text.TextUtils
+import androidx.annotation.ColorInt
+import androidx.core.graphics.ColorUtils.setAlphaComponent
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import com.android.customization.model.CustomizationManager.OptionsFetchedListener
+import com.android.customization.model.ResourceConstants.COLOR_BUNDLES_ARRAY_NAME
+import com.android.customization.model.ResourceConstants.COLOR_BUNDLE_MAIN_COLOR_PREFIX
+import com.android.customization.model.ResourceConstants.COLOR_BUNDLE_NAME_PREFIX
+import com.android.customization.model.ResourceConstants.COLOR_BUNDLE_STYLE_PREFIX
+import com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE
+import com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR
+import com.android.customization.model.ResourcesApkProvider
+import com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_HOME
+import com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_LOCK
+import com.android.customization.model.color.ColorUtils.toColorString
+import com.android.systemui.monet.ColorScheme
+import com.android.systemui.monet.Style
+import com.android.wallpaper.compat.WallpaperManagerCompat
+import com.android.wallpaper.module.InjectorProvider
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import java.util.*
+
+/**
+ * Default implementation of {@link ColorOptionsProvider} that reads preset colors from
+ * a stub APK.
+ */
+class ColorProvider(context: Context, stubPackageName: String) :
+ ResourcesApkProvider(context, stubPackageName), ColorOptionsProvider {
+
+ companion object {
+ const val themeStyleEnabled = true
+ val styleSize = if (themeStyleEnabled) Style.values().size else 1
+ private const val TAG = "ColorProvider"
+ private const val MAX_SEED_COLORS = 4
+ private const val MAX_PRESET_COLORS = 4
+ private const val ALPHA_MASK = 0xFF
+ }
+
+ private val monetEnabled = ColorUtils.isMonetEnabled(context)
+ // TODO(b/202145216): Use style method to fetch the list of style.
+ private var styleList = if (themeStyleEnabled) arrayOf(
+ Style.TONAL_SPOT, Style.SPRITZ, Style.VIBRANT, Style.EXPRESSIVE
+ ) else arrayOf(Style.TONAL_SPOT)
+
+ private val scope = if (mContext is LifecycleOwner) {
+ mContext.lifecycleScope
+ } else {
+ CoroutineScope(Dispatchers.Default + SupervisorJob())
+ }
+
+ private var colorsAvailable = true
+ private var colorBundles: List<ColorOption>? = null
+ private var homeWallpaperColors: WallpaperColors? = null
+ private var lockWallpaperColors: WallpaperColors? = null
+
+
+ override fun isAvailable(): Boolean {
+ return monetEnabled && super.isAvailable() && colorsAvailable
+ }
+
+ override fun fetch(callback: OptionsFetchedListener<ColorOption>?, reload: Boolean,
+ homeWallpaperColors: WallpaperColors?,
+ lockWallpaperColors: WallpaperColors?) {
+ val wallpaperColorsChanged = this.homeWallpaperColors != homeWallpaperColors
+ || this.lockWallpaperColors != lockWallpaperColors
+ if (wallpaperColorsChanged) {
+ this.homeWallpaperColors = homeWallpaperColors
+ this.lockWallpaperColors = lockWallpaperColors
+ }
+ if(colorBundles == null || reload || wallpaperColorsChanged) {
+ scope.launch {
+ try {
+ if (colorBundles == null || reload) {
+ loadPreset()
+ }
+ if (wallpaperColorsChanged || reload) {
+ loadSeedColors(homeWallpaperColors, lockWallpaperColors)
+ }
+ } catch (e: Throwable) {
+ colorsAvailable = false
+ callback?.onError(e)
+ return@launch
+ }
+ callback?.onOptionsLoaded(colorBundles)
+ }
+ } else {
+ callback?.onOptionsLoaded(colorBundles)
+ }
+ }
+
+ private fun isLockScreenWallpaperLastApplied(): Boolean {
+ // The WallpaperId increases every time a new wallpaper is set, so the larger wallpaper id
+ // is the most recently set wallpaper
+ val manager = InjectorProvider.getInjector().getWallpaperManagerCompat(mContext)
+ return manager.getWallpaperId(WallpaperManagerCompat.FLAG_LOCK) >
+ manager.getWallpaperId(WallpaperManagerCompat.FLAG_SYSTEM)
+ }
+
+ private fun loadSeedColors(homeWallpaperColors: WallpaperColors?,
+ lockWallpaperColors: WallpaperColors?) {
+ if (homeWallpaperColors == null) return
+
+ val bundles: MutableList<ColorOption> = ArrayList()
+ val colorsPerSource = if (lockWallpaperColors == null) {
+ MAX_SEED_COLORS
+ } else {
+ MAX_SEED_COLORS / 2
+ }
+
+ if (lockWallpaperColors != null) {
+ val shouldLockColorsGoFirst = isLockScreenWallpaperLastApplied()
+ // First half of the colors
+ buildColorSeeds(
+ if (shouldLockColorsGoFirst) lockWallpaperColors else homeWallpaperColors,
+ colorsPerSource,
+ if (shouldLockColorsGoFirst) COLOR_SOURCE_LOCK else COLOR_SOURCE_HOME,
+ true,
+ bundles)
+ // Second half of the colors
+ buildColorSeeds(
+ if (shouldLockColorsGoFirst) homeWallpaperColors else lockWallpaperColors,
+ MAX_SEED_COLORS - bundles.size / styleSize,
+ if (shouldLockColorsGoFirst) COLOR_SOURCE_HOME else COLOR_SOURCE_LOCK,
+ false,
+ bundles)
+ } else {
+ buildColorSeeds(homeWallpaperColors, colorsPerSource, COLOR_SOURCE_HOME, true, bundles)
+ }
+
+ bundles.addAll(colorBundles?.filterNot{it is ColorSeedOption} ?: emptyList())
+ colorBundles = bundles
+ }
+
+ private fun buildColorSeeds(wallpaperColors: WallpaperColors, maxColors: Int, source: String,
+ containsDefault: Boolean, bundles: MutableList<ColorOption>) {
+ val seedColors = ColorScheme.getSeedColors(wallpaperColors)
+ val defaultSeed = seedColors.first()
+ buildBundle(defaultSeed, 0, containsDefault, source, bundles)
+ for ((i, colorInt) in seedColors.drop(1).take(maxColors - 1).withIndex()) {
+ buildBundle(colorInt, i + 1, false, source, bundles)
+ }
+ }
+
+ private fun buildBundle(colorInt: Int, i: Int, isDefault: Boolean, source: String,
+ bundles: MutableList<ColorOption>) {
+ // TODO(b/202145216): Measure time cost in the loop.
+ for (style in styleList) {
+ val builder = ColorSeedOption.Builder()
+ val lightColorScheme = ColorScheme(colorInt, /* darkTheme= */ false, style)
+ val darkColorScheme = ColorScheme(colorInt, /* darkTheme= */ true, style)
+ builder.setLightColors(lightColorScheme.getLightColorPreview())
+ .setDarkColors(darkColorScheme.getDarkColorPreview())
+ .addOverlayPackage(OVERLAY_CATEGORY_SYSTEM_PALETTE,
+ if (isDefault) "" else toColorString(colorInt)
+ )
+ .addOverlayPackage(OVERLAY_CATEGORY_COLOR,
+ if (isDefault) "" else toColorString(colorInt)
+ )
+ .setSource(source)
+ .setStyle(style)
+ // Color option index value starts from 1.
+ .setIndex(i + 1)
+
+ if (isDefault) builder.asDefault()
+
+ bundles.add(builder.build())
+ }
+ }
+
+ /**
+ * Returns the colors for the light theme version of the preview of a ColorScheme
+ * based on this order:
+ * |-------|
+ * | 0 | 1 |
+ * |---+---|
+ * | 2 | 3 |
+ * |-------|
+ */
+ @ColorInt
+ private fun ColorScheme.getLightColorPreview(): IntArray {
+ return intArrayOf(setAlphaComponent(this.accent1[2], ALPHA_MASK),
+ setAlphaComponent(this.accent1[2], ALPHA_MASK),
+ ColorStateList.valueOf(this.accent3[6]).withLStar(85f).colors[0],
+ setAlphaComponent(this.accent1[6], ALPHA_MASK))
+ }
+
+ /**
+ * Returns the color for the dark theme version of the preview of a ColorScheme
+ * based on this order:
+ * |-------|
+ * | 0 | 1 |
+ * |---+---|
+ * | 2 | 3 |
+ * |-------|
+ */
+ @ColorInt
+ private fun ColorScheme.getDarkColorPreview(): IntArray {
+ return intArrayOf(setAlphaComponent(this.accent1[2], ALPHA_MASK),
+ setAlphaComponent(this.accent1[2], ALPHA_MASK),
+ ColorStateList.valueOf(this.accent3[6]).withLStar(85f).colors[0],
+ setAlphaComponent(this.accent1[6], ALPHA_MASK))
+ }
+
+ private fun ColorScheme.getPresetColorPreview(seed: Int): IntArray {
+ return when(this.style) {
+ Style.FRUIT_SALAD -> intArrayOf(seed, this.accent1[2])
+ Style.TONAL_SPOT -> intArrayOf(this.accentColor, this.accentColor)
+ else -> intArrayOf(this.accent1[2], this.accent1[2])
+ }
+ }
+
+ private suspend fun loadPreset() = withContext(Dispatchers.IO) {
+ val extractor = ColorBundlePreviewExtractor(mContext)
+ val bundles: MutableList<ColorOption> = ArrayList()
+
+ val bundleNames = getItemsFromStub(COLOR_BUNDLES_ARRAY_NAME)
+ // Color option index value starts from 1.
+ var index = 1
+ val maxPresetColors = if (themeStyleEnabled) bundleNames.size else MAX_PRESET_COLORS
+ for (bundleName in bundleNames.take(maxPresetColors)) {
+ val builder = ColorBundle.Builder()
+ builder.title = getItemStringFromStub(COLOR_BUNDLE_NAME_PREFIX, bundleName)
+ builder.setIndex(index)
+ val colorFromStub = getItemColorFromStub(COLOR_BUNDLE_MAIN_COLOR_PREFIX, bundleName)
+ extractor.addPrimaryColor(builder, colorFromStub)
+ extractor.addSecondaryColor(builder, colorFromStub)
+ if (themeStyleEnabled) {
+ val styleName = try {
+ getItemStringFromStub(COLOR_BUNDLE_STYLE_PREFIX, bundleName)
+ } catch (e: Resources.NotFoundException) {
+ null
+ }
+ extractor.addColorStyle(builder, styleName)
+ val style = try {
+ if (styleName != null) Style.valueOf(styleName) else Style.TONAL_SPOT
+ } catch (e: IllegalArgumentException) {
+ Style.TONAL_SPOT
+ }
+
+ val darkColors = ColorScheme(colorFromStub, true, style)
+ .getPresetColorPreview(colorFromStub)
+ val lightColors = ColorScheme(colorFromStub, false, style)
+ .getPresetColorPreview(colorFromStub)
+ builder.setColorPrimaryDark(darkColors[0]).setColorSecondaryDark(darkColors[1])
+ builder.setColorPrimaryLight(lightColors[0]).setColorSecondaryLight(lightColors[1])
+ }
+
+ extractor.addAndroidIconOverlay(builder)
+ bundles.add(builder.build(mContext))
+ index++
+ }
+
+ colorBundles = bundles
+ }
+}
diff --git a/src/com/android/customization/model/color/ColorSectionController.java b/src/com/android/customization/model/color/ColorSectionController.java
new file mode 100644
index 0000000..3b8a927
--- /dev/null
+++ b/src/com/android/customization/model/color/ColorSectionController.java
@@ -0,0 +1,554 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color;
+
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO;
+import static android.view.View.VISIBLE;
+
+import static com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_HOME;
+import static com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_LOCK;
+import static com.android.customization.model.color.ColorOptionsProvider.COLOR_SOURCE_PRESET;
+import static com.android.customization.widget.OptionSelectorController.CheckmarkStyle.CENTER;
+
+import android.app.Activity;
+import android.app.WallpaperColors;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.stats.style.StyleEnums;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.FrameLayout;
+
+import androidx.annotation.Nullable;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.viewpager2.widget.MarginPageTransformer;
+import androidx.viewpager2.widget.ViewPager2;
+
+import com.android.customization.model.CustomizationManager;
+import com.android.customization.model.theme.OverlayManagerCompat;
+import com.android.customization.module.CustomizationInjector;
+import com.android.customization.module.ThemesUserEventLogger;
+import com.android.customization.picker.color.ColorSectionView;
+import com.android.customization.widget.OptionSelectorController;
+import com.android.wallpaper.R;
+import com.android.wallpaper.model.CustomizationSectionController;
+import com.android.wallpaper.model.WallpaperColorsViewModel;
+import com.android.wallpaper.module.InjectorProvider;
+import com.android.wallpaper.module.LargeScreenMultiPanesChecker;
+import com.android.wallpaper.widget.PageIndicator;
+import com.android.wallpaper.widget.SeparatedTabLayout;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+
+/**
+ * Color section view's controller for the logic of color customization.
+ */
+public class ColorSectionController implements CustomizationSectionController<ColorSectionView> {
+
+ private static final String TAG = "ColorSectionController";
+ private static final String KEY_COLOR_TAB_POSITION = "COLOR_TAB_POSITION";
+ private static final String KEY_COLOR_PAGE_POSITION = "COLOR_PAGE_POSITION";
+ private static final String ID_VIEWPAGER = "ColorSectionController_colorSectionViewPager";
+ private static final String ID_ITEMVIEW = "ColorSectionController_itemView";
+ private static final String ID_CONTAINER = "ColorSectionController_container";
+ private static final long MIN_COLOR_APPLY_PERIOD = 500L;
+
+ private static final int WALLPAPER_TAB_INDEX = 0;
+ private static final int PRESET_TAB_INDEX = 1;
+
+ private final ThemesUserEventLogger mEventLogger;
+ private final ColorCustomizationManager mColorManager;
+ private final WallpaperColorsViewModel mWallpaperColorsViewModel;
+ private final LifecycleOwner mLifecycleOwner;
+ private final ColorSectionAdapter mColorSectionAdapter = new ColorSectionAdapter();
+
+ private List<ColorOption> mWallpaperColorOptions = new ArrayList<>();
+ private List<ColorOption> mPresetColorOptions = new ArrayList<>();
+ private ViewPager2 mColorSectionViewPager;
+ private ColorOption mSelectedColor;
+ private SeparatedTabLayout mTabLayout;
+ @Nullable private WallpaperColors mHomeWallpaperColors;
+ @Nullable private WallpaperColors mLockWallpaperColors;
+ // Uses a boolean value to indicate whether wallpaper color is ready because WallpaperColors
+ // maybe be null when it's ready.
+ private boolean mHomeWallpaperColorsReady;
+ private boolean mLockWallpaperColorsReady;
+ private Optional<Integer> mTabPositionToRestore = Optional.empty();
+ private Optional<Integer>[] mPagePositionToRestore =
+ new Optional[]{Optional.empty(), Optional.empty()};
+ private long mLastColorApplyingTime = 0L;
+ private ColorSectionView mColorSectionView;
+ private boolean mIsMultiPane;
+
+ private static int getNumPages(int optionsPerPage, int totalOptions) {
+ return (int) Math.ceil((float) totalOptions / optionsPerPage);
+ }
+
+ public ColorSectionController(Activity activity, WallpaperColorsViewModel viewModel,
+ LifecycleOwner lifecycleOwner, @Nullable Bundle savedInstanceState) {
+ CustomizationInjector injector = (CustomizationInjector) InjectorProvider.getInjector();
+ mEventLogger = (ThemesUserEventLogger) injector.getUserEventLogger(activity);
+ mColorManager = ColorCustomizationManager.getInstance(activity,
+ new OverlayManagerCompat(activity));
+ mWallpaperColorsViewModel = viewModel;
+ mLifecycleOwner = lifecycleOwner;
+ mIsMultiPane = new LargeScreenMultiPanesChecker().isMultiPanesEnabled(activity);
+
+ if (savedInstanceState != null) {
+ if (savedInstanceState.containsKey(KEY_COLOR_TAB_POSITION)) {
+ mTabPositionToRestore = Optional.of(
+ savedInstanceState.getInt(KEY_COLOR_TAB_POSITION));
+ }
+
+ for (int i = 0; i < mPagePositionToRestore.length; i++) {
+ String keyColorPage = getPagePositionKey(i);
+ if (keyColorPage != null && savedInstanceState.containsKey(keyColorPage)) {
+ setPagePositionToRestore(i, savedInstanceState.getInt(keyColorPage));
+ }
+ }
+ }
+ }
+
+ private String getPagePositionKey(int index) {
+ return String.format(Locale.US, "%s_%d", KEY_COLOR_PAGE_POSITION, index);
+ }
+
+ private void setPagePositionToRestore(int pagePositionKeyIndex, int pagePosition) {
+ if (pagePositionKeyIndex >= 0 && pagePositionKeyIndex < mPagePositionToRestore.length) {
+ mPagePositionToRestore[pagePositionKeyIndex] = Optional.of(pagePosition);
+ }
+ }
+
+ private int getPagePositionToRestore(int pagePositionKeyIndex, int defaultPagePosition) {
+ if (pagePositionKeyIndex >= 0 && pagePositionKeyIndex < mPagePositionToRestore.length) {
+ return mPagePositionToRestore[pagePositionKeyIndex].orElse(defaultPagePosition);
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean isAvailable(@Nullable Context context) {
+ return context != null && ColorUtils.isMonetEnabled(context) && mColorManager.isAvailable();
+ }
+
+ @Override
+ public ColorSectionView createView(Context context) {
+ mColorSectionView = (ColorSectionView) LayoutInflater.from(context).inflate(
+ R.layout.color_section_view, /* root= */ null);
+ mColorSectionViewPager = mColorSectionView.findViewById(R.id.color_section_view_pager);
+ mColorSectionViewPager.setAccessibilityDelegate(createAccessibilityDelegate(ID_VIEWPAGER));
+ mColorSectionViewPager.setAdapter(mColorSectionAdapter);
+ mColorSectionViewPager.setUserInputEnabled(false);
+ if (ColorProvider.themeStyleEnabled) {
+ mColorSectionViewPager.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+ }
+ mTabLayout = mColorSectionView.findViewById(R.id.separated_tabs);
+ mColorSectionAdapter.setNumColors(context.getResources().getInteger(
+ R.integer.options_grid_num_columns));
+ // TODO(b/202145216): Use just 2 views when tapping either button on top.
+ mTabLayout.setViewPager(mColorSectionViewPager);
+
+ mWallpaperColorsViewModel.getHomeWallpaperColors().observe(mLifecycleOwner,
+ homeColors -> {
+ mHomeWallpaperColors = homeColors;
+ mHomeWallpaperColorsReady = true;
+ maybeLoadColors();
+ });
+ mWallpaperColorsViewModel.getLockWallpaperColors().observe(mLifecycleOwner,
+ lockColors -> {
+ mLockWallpaperColors = lockColors;
+ mLockWallpaperColorsReady = true;
+ maybeLoadColors();
+ });
+ return mColorSectionView;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle savedInstanceState) {
+ if (mColorSectionViewPager != null) {
+ savedInstanceState.putInt(KEY_COLOR_TAB_POSITION,
+ mColorSectionViewPager.getCurrentItem());
+
+ for (int i = 0; i < mPagePositionToRestore.length; i++) {
+ savedInstanceState.putInt(getPagePositionKey(i), getPagePositionToRestore(i, 0));
+ }
+ }
+ }
+
+ private void maybeLoadColors() {
+ if (mHomeWallpaperColorsReady && mLockWallpaperColorsReady) {
+ mColorManager.setWallpaperColors(mHomeWallpaperColors, mLockWallpaperColors);
+ loadColorOptions(/* reload= */ false);
+ }
+ }
+
+ private void loadColorOptions(boolean reload) {
+ mColorManager.fetchOptions(new CustomizationManager.OptionsFetchedListener<ColorOption>() {
+ @Override
+ public void onOptionsLoaded(List<ColorOption> options) {
+ List<ColorOption> wallpaperColorOptions = new ArrayList<>();
+ List<ColorOption> presetColorOptions = new ArrayList<>();
+ for (ColorOption option : options) {
+ if (option instanceof ColorSeedOption) {
+ wallpaperColorOptions.add(option);
+ } else if (option instanceof ColorBundle) {
+ presetColorOptions.add(option);
+ }
+ }
+ mWallpaperColorOptions = wallpaperColorOptions;
+ mPresetColorOptions = presetColorOptions;
+ mSelectedColor = findActiveColorOption(mWallpaperColorOptions,
+ mPresetColorOptions);
+ mTabLayout.post(()-> setUpColorViewPager());
+ }
+
+ @Override
+ public void onError(@Nullable Throwable throwable) {
+ if (throwable != null) {
+ Log.e(TAG, "Error loading theme bundles", throwable);
+ }
+ }
+ }, reload);
+ }
+
+ private void setUpColorViewPager() {
+ mColorSectionAdapter.notifyDataSetChanged();
+
+ if (mTabLayout != null && mTabLayout.getTabCount() == 0) {
+ mTabLayout.addTab(mTabLayout.newTab().setText(R.string.wallpaper_color_tab),
+ WALLPAPER_TAB_INDEX);
+ mTabLayout.addTab(mTabLayout.newTab().setText(R.string.preset_color_tab),
+ PRESET_TAB_INDEX);
+ }
+
+ if (mWallpaperColorOptions.isEmpty()) {
+ // Select preset tab and disable wallpaper tab.
+ mTabLayout.getTabAt(WALLPAPER_TAB_INDEX).view.setEnabled(false);
+ mColorSectionViewPager.setCurrentItem(PRESET_TAB_INDEX, /* smoothScroll= */ false);
+ return;
+ }
+
+ mColorSectionViewPager.setCurrentItem(
+ mTabPositionToRestore.orElseGet(
+ () -> COLOR_SOURCE_PRESET.equals(mColorManager.getCurrentColorSource())
+ ? PRESET_TAB_INDEX
+ : WALLPAPER_TAB_INDEX),
+ /* smoothScroll= */ false);
+
+ // Disable "wallpaper colors" and "basic colors" swiping for new color style.
+ mColorSectionViewPager.setUserInputEnabled(!ColorProvider.themeStyleEnabled);
+ }
+
+ private void setupColorPages(ViewPager2 container, int colorsPerPage, int sectionPosition,
+ List<ColorOption> options, PageIndicator pageIndicator) {
+ container.setAdapter(new ColorPageAdapter(options, /* pageEnabled= */ true,
+ colorsPerPage));
+ if (ColorProvider.themeStyleEnabled) {
+ // Update page index to show selected items.
+ int selectedIndex = options.indexOf(mSelectedColor);
+ if (colorsPerPage != 0) {
+ int pageIndex = selectedIndex / colorsPerPage;
+ int position = getPagePositionToRestore(sectionPosition, pageIndex);
+ container.setCurrentItem(position, /* smoothScroll= */ false);
+ }
+ pageIndicator.setNumPages(getNumPages(colorsPerPage, options.size()));
+ registerOnPageChangeCallback(sectionPosition, container, pageIndicator);
+ }
+ }
+
+ private void registerOnPageChangeCallback(int sectionPosition, ViewPager2 container,
+ PageIndicator pageIndicator) {
+ container.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
+ @Override
+ public void onPageSelected(int position) {
+ super.onPageSelected(position);
+ if (mColorSectionViewPager.getCurrentItem() == sectionPosition) {
+ pageIndicator.setLocation(getPagePosition(pageIndicator, position));
+ setPagePositionToRestore(sectionPosition, position);
+ }
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset,
+ int positionOffsetPixels) {
+ super.onPageScrolled(position, positionOffset, positionOffsetPixels);
+ if (mColorSectionViewPager.getCurrentItem() == sectionPosition) {
+ pageIndicator.setLocation(getPagePosition(pageIndicator, position));
+ setPagePositionToRestore(sectionPosition, position);
+ }
+ }
+
+ private int getPagePosition(PageIndicator pageIndicator, int position) {
+ return pageIndicator.isLayoutRtl() ? pageIndicator.getChildCount() - 1 - position
+ : position;
+ }
+ });
+ }
+
+ private void setupColorOptions(RecyclerView container, List<ColorOption> colorOptions,
+ boolean pageEnabled, int index, int colorsPerPage) {
+ int totalSize = colorOptions.size();
+ if (totalSize == 0) {
+ return;
+ }
+
+ List<ColorOption> subOptions;
+ if (pageEnabled && ColorProvider.themeStyleEnabled) {
+ subOptions = colorOptions.subList(colorsPerPage * index,
+ Math.min(colorsPerPage * (index + 1), totalSize));
+ } else {
+ subOptions = colorOptions;
+ }
+
+ OptionSelectorController<ColorOption> adaptiveController = new OptionSelectorController<>(
+ container, subOptions, /* useGrid= */ true, CENTER);
+ adaptiveController.initOptions(mColorManager);
+ setUpColorOptionsController(adaptiveController);
+ }
+
+ private ColorOption findActiveColorOption(List<ColorOption> wallpaperColorOptions,
+ List<ColorOption> presetColorOptions) {
+ ColorOption activeColorOption = null;
+ for (ColorOption colorOption : Lists.newArrayList(
+ Iterables.concat(wallpaperColorOptions, presetColorOptions))) {
+ if (colorOption.isActive(mColorManager)) {
+ activeColorOption = colorOption;
+ break;
+ }
+ }
+ // Use the first one option by default. This should not happen as above should have an
+ // active option found.
+ if (activeColorOption == null) {
+ activeColorOption = wallpaperColorOptions.isEmpty()
+ ? presetColorOptions.get(0)
+ : wallpaperColorOptions.get(0);
+ }
+ return activeColorOption;
+ }
+
+ private void setUpColorOptionsController(
+ OptionSelectorController<ColorOption> optionSelectorController) {
+ if (mSelectedColor != null && optionSelectorController.containsOption(mSelectedColor)) {
+ optionSelectorController.setSelectedOption(mSelectedColor);
+ }
+
+ optionSelectorController.addListener(selectedOption -> {
+ ColorOption selectedColor = (ColorOption) selectedOption;
+ if (mSelectedColor.equals(selectedColor)) {
+ return;
+ }
+ mSelectedColor = (ColorOption) selectedOption;
+ // Post with delay for color option to run ripple.
+ new Handler().postDelayed(()-> applyColor(mSelectedColor), /* delayMillis= */ 100);
+ });
+ }
+
+ private void applyColor(ColorOption colorOption) {
+ if (SystemClock.elapsedRealtime() - mLastColorApplyingTime < MIN_COLOR_APPLY_PERIOD) {
+ return;
+ }
+ mLastColorApplyingTime = SystemClock.elapsedRealtime();
+ mColorManager.apply(colorOption, new CustomizationManager.Callback() {
+ @Override
+ public void onSuccess() {
+ mColorSectionView.announceForAccessibility(
+ mColorSectionView.getContext().getString(R.string.color_changed));
+ mEventLogger.logColorApplied(getColorAction(colorOption), colorOption);
+ }
+
+ @Override
+ public void onError(@Nullable Throwable throwable) {
+ Log.w(TAG, "Apply theme with error: " + throwable);
+ }
+ });
+ }
+
+ private int getColorAction(ColorOption colorOption) {
+ int action = StyleEnums.DEFAULT_ACTION;
+ boolean isForBoth = mLockWallpaperColors == null || mLockWallpaperColors.equals(
+ mHomeWallpaperColors);
+
+ if (TextUtils.equals(colorOption.getSource(), COLOR_SOURCE_PRESET)) {
+ action = StyleEnums.COLOR_PRESET_APPLIED;
+ } else if (isForBoth) {
+ action = StyleEnums.COLOR_WALLPAPER_HOME_LOCK_APPLIED;
+ } else {
+ switch (colorOption.getSource()) {
+ case COLOR_SOURCE_HOME:
+ action = StyleEnums.COLOR_WALLPAPER_HOME_APPLIED;
+ break;
+ case COLOR_SOURCE_LOCK:
+ action = StyleEnums.COLOR_WALLPAPER_LOCK_APPLIED;
+ break;
+ }
+ }
+ return action;
+ }
+
+ private View.AccessibilityDelegate createAccessibilityDelegate(String id) {
+ return new View.AccessibilityDelegate() {
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ info.setUniqueId(id);
+ }
+ };
+ }
+
+ private class ColorSectionAdapter extends
+ RecyclerView.Adapter<ColorSectionAdapter.ColorPageViewHolder> {
+
+ private final int mItemCounts = new int[]{WALLPAPER_TAB_INDEX, PRESET_TAB_INDEX}.length;
+ private int mNumColors;
+
+ @Override
+ public int getItemCount() {
+ return mItemCounts;
+ }
+
+ @Override
+ public void onBindViewHolder(ColorPageViewHolder viewHolder, int position) {
+ switch (position) {
+ case WALLPAPER_TAB_INDEX:
+ setupColorPages(viewHolder.mContainer, mNumColors, position,
+ mWallpaperColorOptions, viewHolder.mPageIndicator);
+ break;
+ case PRESET_TAB_INDEX:
+ setupColorPages(viewHolder.mContainer, mNumColors, position,
+ mPresetColorOptions, viewHolder.mPageIndicator);
+ break;
+ default:
+ break;
+ }
+ }
+
+ @Override
+ public ColorPageViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
+ return new ColorPageViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(
+ viewType, viewGroup, false));
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return R.layout.color_pages_view;
+ }
+
+ public void setNumColors(int numColors) {
+ mNumColors = numColors;
+ }
+
+ private class ColorPageViewHolder extends RecyclerView.ViewHolder {
+ private ViewPager2 mContainer;
+ private PageIndicator mPageIndicator;
+
+ ColorPageViewHolder(View itemView) {
+ super(itemView);
+ mContainer = itemView.findViewById(R.id.color_page_container);
+ // Correct scrolling goes under collapsing toolbar while scrolling oclor options.
+ mContainer.getChildAt(0).setNestedScrollingEnabled(false);
+ /**
+ * Sets page transformer with margin to separate color pages and
+ * sets color pages' padding to not scroll to window boundary if multi-pane case
+ */
+ if (mIsMultiPane) {
+ final int padding = itemView.getContext().getResources().getDimensionPixelSize(
+ R.dimen.section_horizontal_padding);
+ mContainer.setPageTransformer(new MarginPageTransformer(padding * 2));
+ mContainer.setPadding(padding, /* top= */ 0, padding, /* bottom= */ 0);
+ }
+ mPageIndicator = itemView.findViewById(R.id.color_page_indicator);
+ if (ColorProvider.themeStyleEnabled) {
+ mPageIndicator.setVisibility(VISIBLE);
+ }
+ itemView.setAccessibilityDelegate(createAccessibilityDelegate(ID_ITEMVIEW));
+ mContainer.setAccessibilityDelegate(createAccessibilityDelegate(ID_CONTAINER));
+ }
+ }
+ }
+
+ private class ColorPageAdapter extends
+ RecyclerView.Adapter<ColorPageAdapter.ColorOptionViewHolder> {
+
+ private final boolean mPageEnabled;
+ private final List<ColorOption> mColorOptions;
+ private final int mColorsPerPage;
+
+ private ColorPageAdapter(List<ColorOption> colorOptions, boolean pageEnabled,
+ int colorsPerPage) {
+ mPageEnabled = pageEnabled;
+ mColorOptions = colorOptions;
+ mColorsPerPage = colorsPerPage;
+ }
+
+ @Override
+ public int getItemCount() {
+ if (!mPageEnabled || !ColorProvider.themeStyleEnabled) {
+ return 1;
+ }
+ // Color page size.
+ return getNumPages(mColorsPerPage, mColorOptions.size());
+ }
+
+ @Override
+ public void onBindViewHolder(ColorOptionViewHolder viewHolder, int position) {
+ setupColorOptions(viewHolder.mContainer, mColorOptions, mPageEnabled, position,
+ mColorsPerPage);
+ }
+
+ @Override
+ public ColorOptionViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
+ return new ColorOptionViewHolder(
+ LayoutInflater.from(viewGroup.getContext()).inflate(viewType, viewGroup,
+ false));
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return R.layout.color_options_view;
+ }
+
+ private class ColorOptionViewHolder extends RecyclerView.ViewHolder {
+ private RecyclerView mContainer;
+
+ ColorOptionViewHolder(View itemView) {
+ super(itemView);
+ mContainer = itemView.findViewById(R.id.color_option_container);
+ // Sets layout with margins for non multi-pane case to separate color options.
+ if (!mIsMultiPane) {
+ final FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
+ mContainer.getLayoutParams());
+ final int margin = itemView.getContext().getResources().getDimensionPixelSize(
+ R.dimen.section_horizontal_padding);
+ layoutParams.setMargins(margin, /* top= */ 0, margin, /* bottom= */ 0);
+ mContainer.setLayoutParams(layoutParams);
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/android/customization/model/color/ColorSeedOption.java b/src/com/android/customization/model/color/ColorSeedOption.java
new file mode 100644
index 0000000..7bddcb0
--- /dev/null
+++ b/src/com/android/customization/model/color/ColorSeedOption.java
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.PorterDuff.Mode;
+import android.view.View;
+import android.widget.ImageView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.customization.model.color.ColorOptionsProvider.ColorSource;
+import com.android.systemui.monet.Style;
+import com.android.wallpaper.R;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Represents a seed color obtained from WallpaperColors, for the user to chose as their theming
+ * option.
+ */
+public class ColorSeedOption extends ColorOption {
+
+ private final PreviewInfo mPreviewInfo;
+ @ColorSource
+ private final String mSource;
+
+ @VisibleForTesting
+ ColorSeedOption(String title, Map<String, String> overlayPackages, boolean isDefault,
+ @ColorSource String source, Style style, int index, PreviewInfo previewInfo) {
+ super(title, overlayPackages, isDefault, style, index);
+ mSource = source;
+ mPreviewInfo = previewInfo;
+ }
+
+ @Override
+ public PreviewInfo getPreviewInfo() {
+ return mPreviewInfo;
+ }
+
+ @Override
+ public String getSource() {
+ return mSource;
+ }
+
+ @Override
+ public int getLayoutResId() {
+ return R.layout.color_option;
+ }
+
+ @Override
+ public void bindThumbnailTile(View view) {
+ Resources res = view.getContext().getResources();
+ @ColorInt int[] colors = mPreviewInfo.resolveColors(res);
+
+ int padding = view.isActivated()
+ ? res.getDimensionPixelSize(R.dimen.color_seed_option_tile_padding_selected)
+ : res.getDimensionPixelSize(R.dimen.color_seed_option_tile_padding);
+ for (int i = 0; i < mPreviewColorIds.length; i++) {
+ ImageView colorPreviewImageView = view.findViewById(mPreviewColorIds[i]);
+ colorPreviewImageView.getDrawable().setColorFilter(colors[i], Mode.SRC);
+ colorPreviewImageView.setPadding(padding, padding, padding, padding);
+ }
+
+ view.setContentDescription(getContentDescription(view.getContext()));
+ }
+
+ @Override
+ protected CharSequence getContentDescription(Context context) {
+ // Override because we want all options with the same description.
+ return context.getString(R.string.wallpaper_color_title);
+ }
+
+ /**
+ * The preview information of {@link ColorOption}
+ */
+ public static class PreviewInfo implements ColorOption.PreviewInfo {
+ @ColorInt public int[] lightColors;
+ @ColorInt public int[] darkColors;
+
+ private PreviewInfo(@ColorInt int[] lightColors, @ColorInt int[] darkColors) {
+ this.lightColors = lightColors;
+ this.darkColors = darkColors;
+ }
+
+ /**
+ * Returns the colors to be applied corresponding with the current
+ * configuration's UI mode.
+ * @return one of {@link #lightColors} or {@link #darkColors}
+ */
+ @ColorInt
+ public int[] resolveColors(Resources res) {
+ boolean night = (res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES;
+ return night ? darkColors : lightColors;
+ }
+ }
+
+ /**
+ * The builder of ColorSeedOption
+ */
+ public static class Builder {
+ protected String mTitle;
+ @ColorInt
+ private int[] mLightColors;
+ @ColorInt
+ private int[] mDarkColors;
+ @ColorSource
+ private String mSource;
+ private boolean mIsDefault;
+ private Style mStyle = Style.TONAL_SPOT;
+ private int mIndex;
+ protected Map<String, String> mPackages = new HashMap<>();
+
+ /**
+ * Builds the ColorSeedOption
+ * @return new {@link ColorOption} object
+ */
+ public ColorSeedOption build() {
+ return new ColorSeedOption(mTitle, mPackages, mIsDefault, mSource, mStyle, mIndex,
+ createPreviewInfo());
+ }
+
+ /**
+ * Creates preview information
+ * @return the {@link PreviewInfo} object
+ */
+ public PreviewInfo createPreviewInfo() {
+ return new PreviewInfo(mLightColors, mDarkColors);
+ }
+
+ public Map<String, String> getPackages() {
+ return Collections.unmodifiableMap(mPackages);
+ }
+
+ /**
+ * Gets title of {@link ColorOption} object
+ * @return title string
+ */
+ public String getTitle() {
+ return mTitle;
+ }
+
+ /**
+ * Sets title of bundle
+ * @param title specified title
+ * @return this of {@link ColorBundle.Builder}
+ */
+ public Builder setTitle(String title) {
+ mTitle = title;
+ return this;
+ }
+
+ /**
+ * Sets the colors for preview in light mode
+ * @param lightColors {@link ColorInt} colors for light mode
+ * @return this of {@link Builder}
+ */
+ public Builder setLightColors(@ColorInt int[] lightColors) {
+ mLightColors = lightColors;
+ return this;
+ }
+
+ /**
+ * Sets the colors for preview in light mode
+ * @param darkColors {@link ColorInt} colors for light mode
+ * @return this of {@link Builder}
+ */
+ public Builder setDarkColors(@ColorInt int[] darkColors) {
+ mDarkColors = darkColors;
+ return this;
+ }
+
+
+ /**
+ * Sets overlay package for bundle
+ * @param category the category of bundle
+ * @param packageName tha name of package in the category
+ * @return this of {@link Builder}
+ */
+ public Builder addOverlayPackage(String category, String packageName) {
+ mPackages.put(category, packageName);
+ return this;
+ }
+
+ /**
+ * Sets the source of this color seed
+ * @param source typically either {@link ColorOptionsProvider#COLOR_SOURCE_HOME} or
+ * {@link ColorOptionsProvider#COLOR_SOURCE_LOCK}
+ * @return this of {@link Builder}
+ */
+ public Builder setSource(@ColorSource String source) {
+ mSource = source;
+ return this;
+ }
+
+ /**
+ * Sets the source of this color seed
+ * @param style color style of {@link Style}
+ * @return this of {@link Builder}
+ */
+ public Builder setStyle(Style style) {
+ mStyle = style;
+ return this;
+ }
+
+ /**
+ * Sets color option index of seed
+ * @param index color option index
+ * @return this of {@link ColorBundle.Builder}
+ */
+ public Builder setIndex(int index) {
+ mIndex = index;
+ return this;
+ }
+
+ /**
+ * Sets as default bundle
+ * @return this of {@link Builder}
+ */
+ public Builder asDefault() {
+ mIsDefault = true;
+ return this;
+ }
+ }
+}
diff --git a/src/com/android/customization/model/color/ColorUtils.kt b/src/com/android/customization/model/color/ColorUtils.kt
new file mode 100644
index 0000000..f07ff31
--- /dev/null
+++ b/src/com/android/customization/model/color/ColorUtils.kt
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color
+
+import android.content.Context
+import android.content.pm.PackageManager
+import android.content.res.Resources
+import android.os.SystemProperties
+import android.util.Log
+import androidx.annotation.ColorInt
+
+/**
+ * Utility to wrap Monet's color extraction
+ */
+object ColorUtils {
+ private const val TAG = "ColorUtils"
+ private const val MONET_FLAG = "flag_monet"
+ private var sSysuiRes: Resources? = null
+ private var sFlagId = 0
+
+ /**
+ * Returns true if color extraction is enabled in systemui.
+ */
+ @JvmStatic
+ fun isMonetEnabled(context: Context): Boolean {
+ var monetEnabled = SystemProperties.getBoolean("persist.systemui.flag_monet", false)
+ if (!monetEnabled) {
+ if (sSysuiRes == null) {
+ try {
+ val pm = context.packageManager
+ val sysUIInfo = pm.getApplicationInfo("com.android.systemui",
+ PackageManager.GET_META_DATA or PackageManager.MATCH_SYSTEM_ONLY)
+ if (sysUIInfo != null) {
+ sSysuiRes = pm.getResourcesForApplication(sysUIInfo)
+ }
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.w(TAG, "Couldn't read color flag, skipping section", e)
+ }
+ }
+ if (sFlagId == 0) {
+ sFlagId = if (sSysuiRes == null) 0 else sSysuiRes!!.getIdentifier(
+ MONET_FLAG, "bool", "com.android.systemui")
+ }
+ if (sFlagId > 0) {
+ monetEnabled = sSysuiRes!!.getBoolean(sFlagId)
+ }
+ }
+ return monetEnabled
+ }
+
+ @JvmStatic
+ fun toColorString(@ColorInt color: Int): String {
+ return String.format("%06X", 0xFFFFFF and color)
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/customization/model/color/WallpaperColorResources.java b/src/com/android/customization/model/color/WallpaperColorResources.java
new file mode 100644
index 0000000..eb8b39b
--- /dev/null
+++ b/src/com/android/customization/model/color/WallpaperColorResources.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package com.android.customization.model.color;
+
+import android.app.WallpaperColors;
+import android.content.Context;
+import android.util.SparseIntArray;
+import android.widget.RemoteViews.ColorResources;
+
+import com.android.systemui.monet.ColorScheme;
+
+import java.util.List;
+
+/** A class to override colors in a {@link Context} with wallpaper colors. */
+public class WallpaperColorResources {
+
+ private final SparseIntArray mColorOverlay = new SparseIntArray();
+
+ public WallpaperColorResources(WallpaperColors wallpaperColors) {
+ ColorScheme wallpaperColorScheme = new ColorScheme(wallpaperColors, /* darkTheme= */ false);
+ addOverlayColor(wallpaperColorScheme.getNeutral1(), android.R.color.system_neutral1_10);
+ addOverlayColor(wallpaperColorScheme.getNeutral2(), android.R.color.system_neutral2_10);
+ addOverlayColor(wallpaperColorScheme.getAccent1(), android.R.color.system_accent1_10);
+ addOverlayColor(wallpaperColorScheme.getAccent2(), android.R.color.system_accent2_10);
+ addOverlayColor(wallpaperColorScheme.getAccent3(), android.R.color.system_accent3_10);
+ }
+
+ /** Applies the wallpaper color resources to the {@code context}. */
+ public void apply(Context context) {
+ ColorResources.create(context, mColorOverlay).apply(context);
+ }
+
+ private void addOverlayColor(List<Integer> colors, int firstResourceColorId) {
+ int resourceColorId = firstResourceColorId;
+ for (int color : colors) {
+ mColorOverlay.put(resourceColorId, color);
+ resourceColorId++;
+ }
+ }
+}
diff --git a/src/com/android/customization/model/grid/GridOptionsManager.java b/src/com/android/customization/model/grid/GridOptionsManager.java
index da1139e..7f15d83 100644
--- a/src/com/android/customization/model/grid/GridOptionsManager.java
+++ b/src/com/android/customization/model/grid/GridOptionsManager.java
@@ -16,11 +16,11 @@
package com.android.customization.model.grid;
import android.content.Context;
-import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.customization.model.CustomizationManager;
@@ -31,12 +31,18 @@
import com.android.wallpaper.util.PreviewUtils;
import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
/**
* {@link CustomizationManager} for interfacing with the launcher to handle {@link GridOption}s.
*/
public class GridOptionsManager implements CustomizationManager<GridOption> {
+ private static final ExecutorService sExecutorService = Executors.newSingleThreadExecutor();
+ private static final String TAG = "GridOptionsManager";
+
private static GridOptionsManager sGridOptionsManager;
private final LauncherGridOptionsProvider mProvider;
@@ -65,7 +71,16 @@
@Override
public boolean isAvailable() {
- return mProvider.areGridsAvailable();
+ int gridOptionSize = 0;
+ try {
+ gridOptionSize = sExecutorService.submit(() -> {
+ List<GridOption> gridOptions = mProvider.fetch(/* reload= */true);
+ return gridOptions == null ? 0 : gridOptions.size();
+ }).get();
+ } catch (InterruptedException | ExecutionException e) {
+ Log.w(TAG, "could not get gridOptionSize", e);
+ }
+ return gridOptionSize > 1 && mProvider.areGridsAvailable();
}
@Override
@@ -81,7 +96,18 @@
@Override
public void fetchOptions(OptionsFetchedListener<GridOption> callback, boolean reload) {
- new FetchTask(mProvider, callback, reload).execute();
+ sExecutorService.submit(() -> {
+ List<GridOption> gridOptions = mProvider.fetch(reload);
+ new Handler(Looper.getMainLooper()).post(() -> {
+ if (callback != null) {
+ if (gridOptions != null && !gridOptions.isEmpty()) {
+ callback.onOptionsLoaded(gridOptions);
+ } else {
+ callback.onError(null);
+ }
+ }
+ });
+ });
}
/** Call through content provider API to render preview */
@@ -89,41 +115,4 @@
PreviewUtils.WorkspacePreviewCallback callback) {
mProvider.renderPreview(gridName, bundle, callback);
}
-
- private static class FetchTask extends AsyncTask<Void, Void, List<GridOption>> {
- private final LauncherGridOptionsProvider mProvider;
- @Nullable private final OptionsFetchedListener<GridOption> mCallback;
- private final boolean mReload;
-
- private FetchTask(@NonNull LauncherGridOptionsProvider provider,
- @Nullable OptionsFetchedListener<GridOption> callback, boolean reload) {
- mCallback = callback;
- mProvider = provider;
- mReload = reload;
- }
-
- @Override
- protected List<GridOption> doInBackground(Void[] params) {
- return mProvider.fetch(mReload);
- }
-
- @Override
- protected void onPostExecute(List<GridOption> gridOptions) {
- if (mCallback != null) {
- if (gridOptions != null && !gridOptions.isEmpty()) {
- mCallback.onOptionsLoaded(gridOptions);
- } else {
- mCallback.onError(null);
- }
- }
- }
-
- @Override
- protected void onCancelled() {
- super.onCancelled();
- if (mCallback != null) {
- mCallback.onError(null);
- }
- }
- }
}
diff --git a/src/com/android/customization/model/grid/GridSectionController.java b/src/com/android/customization/model/grid/GridSectionController.java
index 64a6cce..2f54a1b 100644
--- a/src/com/android/customization/model/grid/GridSectionController.java
+++ b/src/com/android/customization/model/grid/GridSectionController.java
@@ -72,7 +72,7 @@
sectionDescription.setText(R.string.something_went_wrong);
sectionTile.setVisibility(View.GONE);
}
- }, /* reload= */ true);
+ }, /* The result is getting when calling isAvailable(), so reload= */ false);
gridSectionView.setOnClickListener(
v -> mSectionNavigationController.navigateTo(new GridFragment()));
diff --git a/src/com/android/customization/model/theme/DefaultThemeProvider.java b/src/com/android/customization/model/theme/DefaultThemeProvider.java
index 404130f..89067c6 100644
--- a/src/com/android/customization/model/theme/DefaultThemeProvider.java
+++ b/src/com/android/customization/model/theme/DefaultThemeProvider.java
@@ -44,10 +44,6 @@
import com.android.customization.model.theme.custom.CustomTheme;
import com.android.customization.module.CustomizationPreferences;
import com.android.wallpaper.R;
-import com.android.wallpaper.asset.ResourceAsset;
-
-import com.bumptech.glide.request.RequestOptions;
-import com.google.android.apps.wallpaper.asset.ThemeBundleThumbAsset;
import org.json.JSONArray;
import org.json.JSONException;
@@ -425,18 +421,4 @@
private String getOverlayPackage(String prefix, String themeName) {
return getItemStringFromStub(prefix, themeName);
}
-
- private ResourceAsset getDrawableResourceAsset(String prefix, String themeName) {
- int drawableResId = mStubApkResources.getIdentifier(prefix + themeName,
- "drawable", mStubPackageName);
- return drawableResId == 0 ? null : new ResourceAsset(mStubApkResources, drawableResId,
- RequestOptions.fitCenterTransform());
- }
-
- private ThemeBundleThumbAsset getThumbAsset(String prefix, String themeName) {
- int drawableResId = mStubApkResources.getIdentifier(prefix + themeName,
- "drawable", mStubPackageName);
- return drawableResId == 0 ? null : new ThemeBundleThumbAsset(mStubApkResources,
- drawableResId);
- }
}
diff --git a/src/com/android/customization/module/DefaultCustomizationInjector.java b/src/com/android/customization/module/DefaultCustomizationInjector.java
index c906281..220c406 100644
--- a/src/com/android/customization/module/DefaultCustomizationInjector.java
+++ b/src/com/android/customization/module/DefaultCustomizationInjector.java
@@ -70,7 +70,7 @@
@Override
public synchronized ThemesUserEventLogger getUserEventLogger(Context context) {
if (mUserEventLogger == null) {
- mUserEventLogger = new StatsLogUserEventLogger();
+ mUserEventLogger = new StatsLogUserEventLogger(context);
}
return mUserEventLogger;
}
diff --git a/src/com/android/customization/module/StatsLogUserEventLogger.java b/src/com/android/customization/module/StatsLogUserEventLogger.java
index fecf19b..216395d 100644
--- a/src/com/android/customization/module/StatsLogUserEventLogger.java
+++ b/src/com/android/customization/module/StatsLogUserEventLogger.java
@@ -38,16 +38,23 @@
import static com.android.wallpaper.util.LaunchSourceUtils.WALLPAPER_LAUNCH_SOURCE;
import android.app.WallpaperManager;
+import android.content.Context;
import android.content.Intent;
import android.stats.style.StyleEnums;
+import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.android.customization.model.clock.Clockface;
+import com.android.customization.model.color.ColorOption;
import com.android.customization.model.grid.GridOption;
import com.android.customization.model.theme.ThemeBundle;
import com.android.systemui.shared.system.SysUiStatsLog;
+import com.android.wallpaper.module.Injector;
+import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.module.NoOpUserEventLogger;
+import com.android.wallpaper.module.WallpaperPreferences;
+import com.android.wallpaper.module.WallpaperStatusChecker;
import java.util.Map;
import java.util.Objects;
@@ -58,51 +65,63 @@
public class StatsLogUserEventLogger extends NoOpUserEventLogger implements ThemesUserEventLogger {
private static final String TAG = "StatsLogUserEventLogger";
+ private final Context mContext;
+ private final WallpaperPreferences mPreferences;
+ private final WallpaperStatusChecker mWallpaperStatusChecker;
+
+ public StatsLogUserEventLogger(Context appContext) {
+ mContext = appContext;
+ Injector injector = InjectorProvider.getInjector();
+ mPreferences = injector.getPreferences(appContext);
+ mWallpaperStatusChecker = injector.getWallpaperStatusChecker();
+ }
@Override
public void logAppLaunched(Intent launchSource) {
- SysUiStatsLog.write(STYLE_UI_CHANGED, STYLE_UICHANGED__ACTION__APP_LAUNCHED, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, getAppLaunchSource(launchSource));
+ SysUiStatsLog.write(STYLE_UI_CHANGED, STYLE_UICHANGED__ACTION__APP_LAUNCHED,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, getAppLaunchSource(launchSource), 0, 0,
+ 0, 0, 0, 0, 0, 0);
}
@Override
public void logResumed(boolean provisioned, boolean wallpaper) {
- SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.ONRESUME, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0);
+ SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.ONRESUME,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
public void logStopped() {
- SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.ONSTOP, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.ONSTOP,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
public void logActionClicked(String collectionId, int actionLabelResId) {
SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.WALLPAPER_EXPLORE, 0, 0, 0, 0, 0,
- getCollectionIdHashCode(collectionId), 0, 0, 0, 0, 0);
+ getIdHashCode(collectionId), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
public void logIndividualWallpaperSelected(String collectionId) {
SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.WALLPAPER_SELECT, 0, 0, 0, 0, 0,
- getCollectionIdHashCode(collectionId), 0, 0, 0, 0, 0);
+ getIdHashCode(collectionId), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
public void logCategorySelected(String collectionId) {
SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.WALLPAPER_OPEN_CATEGORY,
0, 0, 0, 0, 0,
- getCollectionIdHashCode(collectionId),
- 0, 0, 0, 0, 0);
+ getIdHashCode(collectionId),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
public void logLiveWallpaperInfoSelected(String collectionId, @Nullable String wallpaperId) {
SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.LIVE_WALLPAPER_INFO_SELECT,
0, 0, 0, 0, 0,
- getCollectionIdHashCode(collectionId),
- wallpaperId != null ? wallpaperId.hashCode() : 0,
- 0, 0, 0, 0);
+ getIdHashCode(collectionId),
+ getIdHashCode(wallpaperId),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
@@ -110,18 +129,52 @@
@Nullable String wallpaperId) {
SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.LIVE_WALLPAPER_CUSTOMIZE_SELECT,
0, 0, 0, 0, 0,
- getCollectionIdHashCode(collectionId),
- wallpaperId != null ? wallpaperId.hashCode() : 0,
- 0, 0, 0, 0);
+ getIdHashCode(collectionId),
+ getIdHashCode(wallpaperId),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
- public void logWallpaperSet(String collectionId, @Nullable String wallpaperId) {
+ public void logSnapshot() {
+ final boolean isLockWallpaperSet = mWallpaperStatusChecker.isLockWallpaperSet(mContext);
+ final String homeCollectionId = mPreferences.getHomeWallpaperCollectionId();
+ final String homeRemoteId = mPreferences.getHomeWallpaperRemoteId();
+ String homeWallpaperId = TextUtils.isEmpty(homeRemoteId)
+ ? mPreferences.getHomeWallpaperServiceName() : homeRemoteId;
+ String lockCollectionId = isLockWallpaperSet ? mPreferences.getLockWallpaperCollectionId()
+ : homeCollectionId;
+ String lockWallpaperId = isLockWallpaperSet ? mPreferences.getLockWallpaperRemoteId()
+ : homeWallpaperId;
+
+ SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.SNAPSHOT,
+ 0, 0, 0, 0, 0,
+ getIdHashCode(homeCollectionId),
+ getIdHashCode(homeWallpaperId),
+ 0, 0, 0, 0, 0, 0,
+ getIdHashCode(lockCollectionId),
+ getIdHashCode(lockWallpaperId),
+ mPreferences.getFirstLaunchDateSinceSetup(),
+ mPreferences.getFirstWallpaperApplyDateSinceSetup(),
+ mPreferences.getAppLaunchCount(),
+ 0);
+ }
+
+ @Override
+ public void logWallpaperSet(String collectionId, @Nullable String wallpaperId,
+ @Nullable String effects) {
SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.WALLPAPER_APPLIED,
0, 0, 0, 0, 0,
- getCollectionIdHashCode(collectionId),
- wallpaperId != null ? wallpaperId.hashCode() : 0,
- 0, 0, 0, 0);
+ getIdHashCode(collectionId),
+ getIdHashCode(wallpaperId),
+ 0, 0, 0, 0, 0, effects != null ? effects.hashCode() : 0,
+ 0, 0, 0, 0, 0, 0);
+ }
+
+ @Override
+ public void logEffectApply(String effect, @EffectStatus int status) {
+ SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.WALLPAPER_EFFECT_APPLIED,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, status, effect != null ? effect.hashCode() : 0,
+ 0, 0, 0, 0, 0, 0);
}
@Nullable
@@ -136,7 +189,7 @@
Objects.hashCode(getThemePackage(theme, OVERLAY_CATEGORY_COLOR)),
Objects.hashCode(getThemePackage(theme,OVERLAY_CATEGORY_FONT)),
Objects.hashCode(getThemePackage(theme, OVERLAY_CATEGORY_SHAPE)),
- 0, 0, 0, 0, 0, 0, 0, 0);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
@@ -145,15 +198,15 @@
Objects.hashCode(getThemePackage(theme, OVERLAY_CATEGORY_COLOR)),
Objects.hashCode(getThemePackage(theme,OVERLAY_CATEGORY_FONT)),
Objects.hashCode(getThemePackage(theme, OVERLAY_CATEGORY_SHAPE)),
- 0, 0, 0, 0, 0, 0, 0, 0);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
- public void logColorApplied(int action, int colorIndex) {
+ public void logColorApplied(int action, ColorOption colorOption) {
SysUiStatsLog.write(STYLE_UI_CHANGED, action,
0, 0, 0, 0, 0, 0, 0,
- colorIndex,
- 0, 0, 0);
+ colorOption.getIndex(),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, colorOption.getStyle().ordinal() + 1);
}
@Override
@@ -161,7 +214,7 @@
SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.PICKER_SELECT,
0, 0, 0,
Objects.hashCode(clock.getId()),
- 0, 0, 0, 0, 0, 0, 0);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
@@ -169,7 +222,7 @@
SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.PICKER_APPLIED,
0, 0, 0,
Objects.hashCode(clock.getId()),
- 0, 0, 0, 0, 0, 0, 0);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
@@ -177,7 +230,7 @@
SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.PICKER_SELECT,
0, 0, 0, 0,
grid.cols,
- 0, 0, 0, 0, 0, 0);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
@Override
@@ -185,7 +238,7 @@
SysUiStatsLog.write(STYLE_UI_CHANGED, StyleEnums.PICKER_APPLIED,
0, 0, 0, 0,
grid.cols,
- 0, 0, 0, 0, 0, 0);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
private int getAppLaunchSource(Intent launchSource) {
@@ -217,7 +270,7 @@
}
}
- private int getCollectionIdHashCode(String collectionId) {
- return collectionId != null ? collectionId.hashCode() : 0;
+ private int getIdHashCode(String id) {
+ return id != null ? id.hashCode() : 0;
}
}
diff --git a/src/com/android/customization/module/ThemesUserEventLogger.java b/src/com/android/customization/module/ThemesUserEventLogger.java
index ae26290..3e5bb54 100644
--- a/src/com/android/customization/module/ThemesUserEventLogger.java
+++ b/src/com/android/customization/module/ThemesUserEventLogger.java
@@ -16,6 +16,7 @@
package com.android.customization.module;
import com.android.customization.model.clock.Clockface;
+import com.android.customization.model.color.ColorOption;
import com.android.customization.model.grid.GridOption;
import com.android.customization.model.theme.ThemeBundle;
import com.android.wallpaper.module.UserEventLogger;
@@ -33,9 +34,9 @@
* Logs the color usage while color is applied.
*
* @param action color applied action.
- * @param colorIndex color applied index.
+ * @param colorOption applied color option.
*/
- void logColorApplied(int action, int colorIndex);
+ void logColorApplied(int action, ColorOption colorOption);
void logClockSelected(Clockface clock);
diff --git a/src/com/android/customization/picker/color/ColorSectionView.java b/src/com/android/customization/picker/color/ColorSectionView.java
new file mode 100644
index 0000000..b8ba2e4
--- /dev/null
+++ b/src/com/android/customization/picker/color/ColorSectionView.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package com.android.customization.picker.color;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import androidx.annotation.Nullable;
+
+import com.android.wallpaper.picker.SectionView;
+
+/**
+ * The class inherits from {@link SectionView} as the view representing the color section of the
+ * customization picker.
+ */
+public final class ColorSectionView extends SectionView {
+ public ColorSectionView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+}
diff --git a/src/com/android/customization/picker/grid/GridFragment.java b/src/com/android/customization/picker/grid/GridFragment.java
index cb04fc3..c4029d6 100644
--- a/src/com/android/customization/picker/grid/GridFragment.java
+++ b/src/com/android/customization/picker/grid/GridFragment.java
@@ -18,6 +18,7 @@
import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY_TEXT;
import android.content.Context;
+import android.graphics.Point;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
@@ -29,6 +30,8 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.constraintlayout.widget.ConstraintSet;
import androidx.core.widget.ContentLoadingProgressBar;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
@@ -49,11 +52,13 @@
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.picker.AppbarFragment;
import com.android.wallpaper.util.LaunchUtils;
+import com.android.wallpaper.util.ScreenSizeCalculator;
import com.android.wallpaper.widget.BottomActionBar;
import com.bumptech.glide.Glide;
import java.util.List;
+import java.util.Locale;
/**
* Fragment that contains the UI for selecting and applying a GridOption.
@@ -67,7 +72,7 @@
private OptionSelectorController<GridOption> mOptionsController;
private GridOptionsManager mGridManager;
private ContentLoadingProgressBar mLoading;
- private View mContent;
+ private ConstraintLayout mContent;
private View mError;
private BottomActionBar mBottomActionBar;
private ThemesUserEventLogger mEventLogger;
@@ -117,6 +122,18 @@
// Make Talkback focus won't reset when notifyDataSetChange
mOptionsContainer.setItemAnimator(null);
}
+
+ // Set aspect ratio on the preview card dynamically.
+ Point mScreenSize;
+ ScreenSizeCalculator screenSizeCalculator = ScreenSizeCalculator.getInstance();
+ mScreenSize = screenSizeCalculator.getScreenSize(
+ requireActivity().getWindowManager().getDefaultDisplay());
+ ConstraintSet set = new ConstraintSet();
+ set.clone(mContent);
+ String ratio = String.format(Locale.US, "%d:%d", mScreenSize.x, mScreenSize.y);
+ set.setDimensionRatio(R.id.preview_card_container, ratio);
+ set.applyTo(mContent);
+
mLoading = view.findViewById(R.id.loading_indicator);
mError = view.findViewById(R.id.error_section);
@@ -182,6 +199,8 @@
mBottomActionBar.showActionsOnly(APPLY_TEXT);
mBottomActionBar.setActionClickListener(APPLY_TEXT,
v -> applyGridOption(mGridOptionViewModel.getSelectedOption()));
+ mBottomActionBar.setActionAccessibilityTraversalAfter(APPLY_TEXT,
+ mOptionsContainer.getId());
}
private void applyGridOption(GridOption gridOption) {
diff --git a/src/com/android/customization/picker/grid/GridOptionPreviewer.java b/src/com/android/customization/picker/grid/GridOptionPreviewer.java
index 8de08cf..5cf327e 100644
--- a/src/com/android/customization/picker/grid/GridOptionPreviewer.java
+++ b/src/com/android/customization/picker/grid/GridOptionPreviewer.java
@@ -64,16 +64,17 @@
if (mSurfaceCallback != null) {
mSurfaceCallback.cleanUp();
mSurfaceCallback.resetLastSurface();
+ if (mGridOptionSurface != null) {
+ mGridOptionSurface.getHolder().removeCallback(mSurfaceCallback);
+ }
}
- if (mGridOptionSurface == null) {
- mGridOptionSurface = new SurfaceView(mPreviewContainer.getContext());
- mGridOptionSurface.setLayoutParams(new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
- mGridOptionSurface.setZOrderMediaOverlay(true);
- mSurfaceCallback = new GridOptionSurfaceHolderCallback(mGridOptionSurface,
- mGridOptionSurface.getContext());
- mGridOptionSurface.getHolder().addCallback(mSurfaceCallback);
- }
+ mGridOptionSurface = new SurfaceView(mPreviewContainer.getContext());
+ mGridOptionSurface.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ mGridOptionSurface.setZOrderMediaOverlay(true);
+ mSurfaceCallback = new GridOptionSurfaceHolderCallback(mGridOptionSurface,
+ mGridOptionSurface.getContext());
+ mGridOptionSurface.getHolder().addCallback(mSurfaceCallback);
mPreviewContainer.addView(mGridOptionSurface);
}
diff --git a/src/com/android/customization/widget/OptionSelectorController.java b/src/com/android/customization/widget/OptionSelectorController.java
index 952bc55..a66dd44 100644
--- a/src/com/android/customization/widget/OptionSelectorController.java
+++ b/src/com/android/customization/widget/OptionSelectorController.java
@@ -24,6 +24,7 @@
import android.graphics.drawable.LayerDrawable;
import android.text.TextUtils;
import android.util.DisplayMetrics;
+import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -43,6 +44,7 @@
import com.android.customization.model.CustomizationManager;
import com.android.customization.model.CustomizationOption;
import com.android.wallpaper.R;
+import com.android.wallpaper.widget.GridPaddingDecoration;
import java.util.HashSet;
import java.util.List;
@@ -77,7 +79,7 @@
int CENTER_CHANGE_COLOR_WHEN_NOT_SELECTED = 3;
}
- private static final float LINEAR_LAYOUT_HORIZONTAL_DISPLAY_OPTIONS_MAX = 4.35f;
+ private float mLinearLayoutHorizontalDisplayOptionsMax;
private final RecyclerView mContainer;
private final List<T> mOptions;
@@ -99,6 +101,10 @@
mOptions = options;
mUseGrid = useGrid;
mCheckmarkStyle = checkmarkStyle;
+ TypedValue typedValue = new TypedValue();
+ mContainer.getResources().getValue(R.dimen.linear_layout_horizontal_display_options_max,
+ typedValue, true);
+ mLinearLayoutHorizontalDisplayOptionsMax = typedValue.getFloat();
}
public void addListener(OptionSelectedListener listener) {
@@ -312,6 +318,11 @@
if (mContainer.getLayoutManager() != null) {
((GridLayoutManager) mContainer.getLayoutManager()).setSpanCount(numColumns);
}
+ if (mContainer.getItemDecorationCount() == 0) {
+ mContainer.addItemDecoration(new GridPaddingDecoration(
+ mContainer.getContext().getResources().getDimensionPixelSize(
+ R.dimen.option_tile_grid_padding_horizontal), 0));
+ }
return;
}
@@ -320,12 +331,12 @@
mContainer.setOverScrollMode(View.OVER_SCROLL_NEVER);
}
- if (mAdapter.getItemCount() >= LINEAR_LAYOUT_HORIZONTAL_DISPLAY_OPTIONS_MAX) {
+ if (mAdapter.getItemCount() >= mLinearLayoutHorizontalDisplayOptionsMax) {
int spaceBetweenItems = availableWidth
- - Math.round(widthPerItem * LINEAR_LAYOUT_HORIZONTAL_DISPLAY_OPTIONS_MAX)
+ - Math.round(widthPerItem * mLinearLayoutHorizontalDisplayOptionsMax)
- mContainer.getPaddingLeft();
int itemEndMargin =
- spaceBetweenItems / (int) LINEAR_LAYOUT_HORIZONTAL_DISPLAY_OPTIONS_MAX;
+ spaceBetweenItems / (int) mLinearLayoutHorizontalDisplayOptionsMax;
if (itemEndMargin <= 0) {
itemEndMargin = res.getDimensionPixelOffset(R.dimen.option_tile_margin_horizontal);
}
diff --git a/src/com/google/android/apps/wallpaper/asset/ThemeBundleThumbAsset.java b/src/com/google/android/apps/wallpaper/asset/ThemeBundleThumbAsset.java
deleted file mode 100644
index d941854..0000000
--- a/src/com/google/android/apps/wallpaper/asset/ThemeBundleThumbAsset.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2019 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.google.android.apps.wallpaper.asset;
-
-import android.app.Activity;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.os.AsyncTask;
-
-import androidx.annotation.Nullable;
-
-import com.android.wallpaper.asset.Asset;
-import com.android.wallpaper.module.DrawableLayerResolver;
-import com.android.wallpaper.module.InjectorProvider;
-
-public class ThemeBundleThumbAsset extends Asset {
- private final Resources mRes;
- private final int mResId;
- private final DrawableLayerResolver mLayerResolver;
-
- public ThemeBundleThumbAsset(Resources res, int resId) {
- mRes = res;
- mResId = resId;
- mLayerResolver = InjectorProvider.getInjector().getDrawableLayerResolver();
- }
-
- @Override
- public void decodeBitmap(int targetWidth, int targetHeight, BitmapReceiver receiver) {
- // No scaling is needed, as the thumbnail is already a thumbnail.
- LoadThumbnailTask task = new LoadThumbnailTask(mRes, mResId, mLayerResolver, receiver);
- task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
-
- @Override
- public void decodeBitmapRegion(Rect rect, int targetWidth, int targetHeight,
- boolean shouldAdjustForRtl, BitmapReceiver receiver) {
-
- }
-
- @Override
- public void decodeRawDimensions(@Nullable Activity activity, DimensionsReceiver receiver) {
-
- }
-
- @Override
- public boolean supportsTiling() {
- return false;
- }
-
- /**
- * AsyncTask subclass which loads the live wallpaper's thumbnail bitmap off the main UI thread.
- * Resolves with null if live wallpaper thumbnail is not a bitmap.
- */
- private static class LoadThumbnailTask extends AsyncTask<Void, Void, Bitmap> {
- private final DrawableLayerResolver mLayerResolver;
- private final Resources mResources;
- private final int mResId;
- private BitmapReceiver mReceiver;
-
- public LoadThumbnailTask(Resources res, int resId, DrawableLayerResolver resolver,
- BitmapReceiver receiver) {
- mLayerResolver = resolver;
- mReceiver = receiver;
- mResources = res;
- mResId = resId;
- }
-
- @Override
- protected Bitmap doInBackground(Void... unused) {
- Drawable thumb = mResources.getDrawable(mResId, null);
-
- // Live wallpaper components may or may not specify a thumbnail drawable.
- if (thumb instanceof BitmapDrawable) {
- return ((BitmapDrawable) thumb).getBitmap();
- } else if (thumb instanceof LayerDrawable) {
- Drawable layer = mLayerResolver.resolveLayer((LayerDrawable) thumb);
- if (layer instanceof BitmapDrawable) {
- return ((BitmapDrawable) layer).getBitmap();
- }
- }
-
- // If no thumbnail was specified, return a null bitmap.
- return null;
- }
-
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- mReceiver.onBitmapDecoded(bitmap);
- }
- }
-}
diff --git a/src_override/com/android/wallpaper/module/WallpapersInjector.java b/src_override/com/android/wallpaper/module/WallpapersInjector.java
index f8a4182..9f8fe9c 100755
--- a/src_override/com/android/wallpaper/module/WallpapersInjector.java
+++ b/src_override/com/android/wallpaper/module/WallpapersInjector.java
@@ -24,8 +24,8 @@
import com.android.wallpaper.model.CategoryProvider;
import com.android.wallpaper.model.WallpaperInfo;
import com.android.wallpaper.monitor.PerformanceMonitor;
+import com.android.wallpaper.picker.CustomizationPickerActivity;
import com.android.wallpaper.picker.ImagePreviewFragment;
-import com.android.wallpaper.picker.TopLevelPickerActivity;
/**
* A concrete, real implementation of the dependency provider.
@@ -81,7 +81,7 @@
@Override
public Intent getDeepLinkRedirectIntent(Context context, Uri uri) {
Intent intent = new Intent();
- intent.setClass(context, TopLevelPickerActivity.class);
+ intent.setClass(context, CustomizationPickerActivity.class);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return intent;
diff --git a/tests/src/com/android/customization/testing/TestThemesUserEventLogger.java b/tests/src/com/android/customization/testing/TestThemesUserEventLogger.java
index 9969e6e..9250a86 100644
--- a/tests/src/com/android/customization/testing/TestThemesUserEventLogger.java
+++ b/tests/src/com/android/customization/testing/TestThemesUserEventLogger.java
@@ -1,6 +1,7 @@
package com.android.customization.testing;
import com.android.customization.model.clock.Clockface;
+import com.android.customization.model.color.ColorOption;
import com.android.customization.model.grid.GridOption;
import com.android.customization.model.theme.ThemeBundle;
import com.android.customization.module.ThemesUserEventLogger;
@@ -22,7 +23,7 @@
}
@Override
- public void logColorApplied(int action, int colorIndex) {
+ public void logColorApplied(int action, ColorOption colorOption) {
// Do nothing.
}