Merge tag 'android-platform-12.1.0_r8' of https://android.googlesource.com/platform//packages/apps/Launcher3 into arcadia-next

Android Platform 12.1.0 Release 8 (8968309)

Change-Id: Id2406325233d727d26df55b4b9f69e03b2f7da03

# gpg verification failed.
diff --git a/Android.bp b/Android.bp
index bab994a..db8f5b7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -100,6 +100,13 @@
     min_sdk_version: min_launcher3_sdk_version,
 }
 
+java_import {
+    name: "libGoogleFeed",
+    jars: [
+        "libs/libGoogleFeed.jar",
+    ],
+}
+
 // Library with all the dependencies for building Launcher3
 android_library {
     name: "Launcher3ResLib",
@@ -117,6 +124,9 @@
         "androidx.cardview_cardview",
         "com.google.android.material_material",
         "iconloader_base",
+        "libGoogleFeed",
+        "colorkt",
+        "themelib",
     ],
     manifest: "AndroidManifest-common.xml",
     sdk_version: "current",
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index eee6db5..530b9ca 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -49,13 +49,11 @@
     -->
     <permission
         android:name="${packageName}.permission.READ_SETTINGS"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="signatureOrSystem"
         android:label="@string/permlab_read_settings"
         android:description="@string/permdesc_read_settings"/>
     <permission
         android:name="${packageName}.permission.WRITE_SETTINGS"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="signatureOrSystem"
         android:label="@string/permlab_write_settings"
         android:description="@string/permdesc_write_settings"/>
@@ -135,7 +133,9 @@
         <provider
             android:name="com.android.launcher3.graphics.GridCustomizationsProvider"
             android:authorities="${packageName}.grid_control"
-            android:exported="true" />
+            android:exported="true"
+            android:writePermission="${packageName}.permission.WRITE_SETTINGS"
+            android:readPermission="${packageName}.permission.READ_SETTINGS" />
 
         <!--
         The settings activity. To extend point settings_fragment_name to appropriate fragment class
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b838a51..63180e8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -44,7 +44,7 @@
         attributes and intent filters the same
         -->
         <activity
-            android:name="com.android.launcher3.Launcher"
+            android:name="com.android.launcher3.CustomLauncher"
             android:launchMode="singleTask"
             android:clearTaskOnLaunch="true"
             android:stateNotNeeded="true"
@@ -66,6 +66,9 @@
             <meta-data
                 android:name="com.android.launcher3.grid.control"
                 android:value="${packageName}.grid_control" />
+            <meta-data
+                android:name="com.android.launcher3.themedicon.option"
+                android:value="${packageName}.grid_control" />
         </activity>
 
     </application>
diff --git a/libs/libGoogleFeed.jar b/libs/libGoogleFeed.jar
new file mode 100644
index 0000000..158b76d
--- /dev/null
+++ b/libs/libGoogleFeed.jar
Binary files differ
diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml
index 53910e3..0c0eac7 100644
--- a/quickstep/AndroidManifest-launcher.xml
+++ b/quickstep/AndroidManifest-launcher.xml
@@ -43,7 +43,7 @@
         attributes and intent filters the same
         -->
         <activity
-            android:name="com.android.launcher3.uioverrides.QuickstepLauncher"
+            android:name="com.android.launcher3.CustomLauncher"
             android:launchMode="singleTask"
             android:clearTaskOnLaunch="true"
             android:stateNotNeeded="true"
@@ -65,6 +65,9 @@
             <meta-data
                 android:name="com.android.launcher3.grid.control"
                 android:value="${packageName}.grid_control" />
+            <meta-data
+                android:name="com.android.launcher3.themedicon.option"
+                android:value="${packageName}.grid_control" />
         </activity>
 
     </application>
diff --git a/quickstep/res/drawable/task_menu_item_bg.xml b/quickstep/res/drawable/task_menu_item_bg.xml
index 16c13eb..bd863f2 100644
--- a/quickstep/res/drawable/task_menu_item_bg.xml
+++ b/quickstep/res/drawable/task_menu_item_bg.xml
@@ -15,8 +15,13 @@
      limitations under the License.
 -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <solid android:color="?androidprv:attr/colorSurface" />
-    <corners android:radius="@dimen/task_menu_item_corner_radius" />
-</shape>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+     android:color="?android:attr/colorControlHighlight">
+     <item>
+          <shape>
+              <solid android:color="?androidprv:attr/colorSurface" />
+              <corners android:radius="@dimen/task_menu_item_corner_radius" />
+          </shape>
+     </item>
+</ripple>
diff --git a/quickstep/src/com/android/launcher3/CustomLauncher.java b/quickstep/src/com/android/launcher3/CustomLauncher.java
new file mode 100644
index 0000000..1e41f42
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/CustomLauncher.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 Paranoid Android
+ *
+ * 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.launcher3;
+
+import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.systemui.plugins.shared.LauncherOverlayManager;
+
+public class CustomLauncher extends QuickstepLauncher {
+
+    @Override
+    protected LauncherOverlayManager getDefaultOverlay() {
+        return new OverlayCallbackImpl(this);
+    }
+
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index bec717d..c4ca2b3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -226,9 +226,10 @@
         boolean isTaskBarEnabled =
                 FeatureFlags.ENABLE_TASKBAR.get() && dp != null && dp.isTaskbarPresent;
 
+        SystemUiProxy sysui = SystemUiProxy.INSTANCE.get(mContext);
+        sysui.setTaskbarEnabled(isTaskBarEnabled);
         if (!isTaskBarEnabled) {
-            SystemUiProxy.INSTANCE.get(mContext)
-                    .notifyTaskbarStatus(/* visible */ false, /* stashed */ false);
+            sysui.notifyTaskbarStatus(/* visible */ false, /* stashed */ false);
             return;
         }
 
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 67e7f88..f301ebc 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -427,6 +427,18 @@
     }
 
     @Override
+    public void setTaskbarEnabled(boolean enabled) {
+        if (mSystemUiProxy != null) {
+            try {
+                mSystemUiProxy.setTaskbarEnabled(enabled);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call setTaskbarEnabled with arg: " +
+                        enabled, e);
+            }
+        }
+    }
+
+    @Override
     public void notifyTaskbarStatus(boolean visible, boolean stashed) {
         if (mSystemUiProxy != null) {
             try {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 7218cd7..053f144 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -3268,7 +3268,9 @@
             return;
         }
         mActionsView.setSplitButtonVisible(
-                mActivity.getDeviceProfile().overviewShowAsGrid && getTaskViewCount() > 1);
+                mActivity.getDeviceProfile().overviewShowAsGrid &&
+                        mActivity.getDeviceProfile().isTablet &&
+                        getTaskViewCount() > 1);
     }
 
     /**
diff --git a/res/color-night-v31/all_apps_tab_text.xml b/res/color-night-v31/all_apps_tab_text.xml
index 83237b4..eaac621 100644
--- a/res/color-night-v31/all_apps_tab_text.xml
+++ b/res/color-night-v31/all_apps_tab_text.xml
@@ -14,6 +14,6 @@
      limitations under the License.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_50" android:state_selected="true"/>
-    <item android:color="@android:color/system_neutral2_700"/>
-</selector>
\ No newline at end of file
+    <item android:color="?android:textColorPrimaryInverse" android:state_selected="true"/>
+    <item android:color="?android:textColorSecondary"/>
+</selector>
diff --git a/res/color-night-v31/all_apps_tabs_background.xml b/res/color-night-v31/all_apps_tabs_background.xml
new file mode 100644
index 0000000..fc8a4d7
--- /dev/null
+++ b/res/color-night-v31/all_apps_tabs_background.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@android:color/system_neutral1_800" />
+</selector>
diff --git a/res/color-v31/all_apps_tab_text.xml b/res/color-v31/all_apps_tab_text.xml
index c3520a7..d133a31 100644
--- a/res/color-v31/all_apps_tab_text.xml
+++ b/res/color-v31/all_apps_tab_text.xml
@@ -14,6 +14,6 @@
      limitations under the License.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_900" android:state_selected="true"/>
-    <item android:color="@android:color/system_neutral2_700"/>
-</selector>
\ No newline at end of file
+    <item android:color="?android:textColorPrimary" android:state_selected="true"/>
+    <item android:color="?android:textColorSecondary"/>
+</selector>
diff --git a/res/drawable/all_apps_search_hint.xml b/res/drawable/all_apps_search_hint.xml
index b2ff7a4..c0e6811 100644
--- a/res/drawable/all_apps_search_hint.xml
+++ b/res/drawable/all_apps_search_hint.xml
@@ -16,5 +16,5 @@
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:color="@android:color/transparent" android:state_focused="true" />
-    <item android:color="?android:attr/colorAccent"/>
-</selector>
\ No newline at end of file
+    <item android:color="?android:attr/textColorSecondary" android:alpha="?android:attr/disabledAlpha" />
+</selector>
diff --git a/res/drawable/bg_all_apps_searchbox.xml b/res/drawable/bg_all_apps_searchbox.xml
index c324927..2d02238 100644
--- a/res/drawable/bg_all_apps_searchbox.xml
+++ b/res/drawable/bg_all_apps_searchbox.xml
@@ -14,6 +14,6 @@
      limitations under the License.
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
-    <solid android:color="?attr/popupColorPrimary" />
-    <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+     <solid android:color="?attr/allappsHeaderProtectionColor" />
+     <corners android:radius="58dp" />
+</shape>
diff --git a/res/layout/search_container_all_apps.xml b/res/layout/search_container_all_apps.xml
index e1646ba..5ebf9c8 100644
--- a/res/layout/search_container_all_apps.xml
+++ b/res/layout/search_container_all_apps.xml
@@ -21,17 +21,17 @@
     android:layout_centerHorizontal="true"
     android:layout_gravity="top|center_horizontal"
     android:background="@drawable/bg_all_apps_searchbox"
-    android:elevation="1dp"
+    android:elevation="0dp"
     android:focusableInTouchMode="true"
-    android:gravity="center"
     android:hint="@string/all_apps_search_bar_hint"
     android:imeOptions="actionSearch|flagNoExtractUi"
     android:inputType="text|textNoSuggestions|textCapWords"
     android:maxLines="1"
     android:padding="8dp"
+    android:paddingStart="16dp"
     android:saveEnabled="false"
     android:scrollHorizontally="true"
     android:singleLine="true"
     android:textColor="?android:attr/textColorSecondary"
     android:textColorHint="@drawable/all_apps_search_hint"
-    android:textSize="16sp" />
\ No newline at end of file
+    android:textSize="20sp" />
diff --git a/res/layout/secondary_launcher.xml b/res/layout/secondary_launcher.xml
index b15a320..131de00 100644
--- a/res/layout/secondary_launcher.xml
+++ b/res/layout/secondary_launcher.xml
@@ -105,9 +105,8 @@
             android:layout_centerHorizontal="true"
             android:layout_gravity="top|center_horizontal"
             android:background="@drawable/bg_all_apps_searchbox"
-            android:elevation="1dp"
+            android:elevation="0dp"
             android:focusableInTouchMode="true"
-            android:gravity="center"
             android:hint="@string/all_apps_search_bar_hint"
             android:imeOptions="actionSearch|flagNoExtractUi"
             android:inputType="text|textNoSuggestions|textCapWords"
@@ -118,8 +117,8 @@
             android:singleLine="true"
             android:textColor="?android:attr/textColorSecondary"
             android:textColorHint="@drawable/all_apps_search_hint"
-            android:textSize="16sp" />
+            android:textSize="20sp" />
 
         <include layout="@layout/all_apps_fast_scroller" />
     </com.android.launcher3.allapps.AllAppsContainerView>
-</com.android.launcher3.secondarydisplay.SecondaryDragLayer>
\ No newline at end of file
+</com.android.launcher3.secondarydisplay.SecondaryDragLayer>
diff --git a/res/values-ldrtl/custom_strings.xml b/res/values-ldrtl/custom_strings.xml
new file mode 100644
index 0000000..ee4208e
--- /dev/null
+++ b/res/values-ldrtl/custom_strings.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2016 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources>
+
+    <!-- Settings title to show Google Now at -1 screen on launcher. [CHAR LIMIT=50] -->
+    <string name="title_show_google_app">Show Google App</string>
+    <!-- Settings message explaining when the -1 screen is available on an LTR device. [CHAR LIMIT=100] -->
+    <string name="msg_minus_one_on_left">When you swipe left from main Home screen</string>
+    <!-- Settings message explaining when the -1 screen is available on an RTL device. [CHAR LIMIT=100] -->
+    <string name="msg_minus_one_on_right">When you swipe right from main Home screen</string>
+    <string name="pref_show_google_now_summary" translatable="false">@string/msg_minus_one_on_right</string>
+
+</resources>
diff --git a/res/values-v31/colors.xml b/res/values-v31/colors.xml
index 7bbdbd1..85a6678 100644
--- a/res/values-v31/colors.xml
+++ b/res/values-v31/colors.xml
@@ -19,7 +19,7 @@
 <resources  xmlns:android="http://schemas.android.com/apk/res/android">
     <color name="popup_color_primary_light">@android:color/system_accent2_50</color>
     <color name="popup_color_secondary_light">@android:color/system_neutral2_100</color>
-    <color name="popup_color_tertiary_light">@android:color/system_neutral2_300</color>
+    <color name="popup_color_tertiary_light">@android:color/system_neutral2_100</color>
     <color name="popup_color_neutral_dark">@android:color/system_neutral1_1000</color>
     <color name="popup_color_primary_dark">@android:color/system_neutral2_800</color>
     <color name="popup_color_secondary_dark">@android:color/system_neutral1_900</color>
diff --git a/res/values/custom_strings.xml b/res/values/custom_strings.xml
new file mode 100644
index 0000000..edb1aee
--- /dev/null
+++ b/res/values/custom_strings.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2016 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources>
+
+    <!-- Settings title to show Google Now at -1 screen on launcher. [CHAR LIMIT=50] -->
+    <string name="title_show_google_app">Swipe to access Google app</string>
+    <!-- Settings message explaining when the -1 screen is available on an LTR device. [CHAR LIMIT=100] -->
+    <string name="msg_minus_one_on_left">When you swipe left from main Home screen</string>
+    <!-- Settings message explaining when the -1 screen is available on an RTL device. [CHAR LIMIT=100] -->
+    <string name="msg_minus_one_on_right">When you swipe right from main Home screen</string>
+    <string name="pref_show_google_now_summary" translatable="false">@string/msg_minus_one_on_left</string>
+
+    <string name="pref_suggestions_title">Suggestions</string>
+    <string name="pref_suggestions_summary">For all apps and Home screen</string>
+
+    <string name="pref_allow_phone_taskbar">Use taskbar</string>
+    <string name="pref_allow_phone_taskbar_desc">For opening and switching apps anywhere</string>
+
+    <string name="pref_allow_phone_overview_grid">Show grid of recent apps</string>
+    <string name="pref_allow_phone_overview_grid_desc">More recent apps in Overview</string>
+
+</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 818a032..090419b 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -99,6 +99,7 @@
         <item name="android:colorControlHighlight">#19FFFFFF</item>
         <item name="android:colorPrimary">#FF212121</item>
         <item name="allAppsScrimColor">?android:attr/colorBackgroundFloating</item>
+        <item name="allappsHeaderProtectionColor">@color/popup_color_tertiary_dark</item>
         <item name="allAppsNavBarScrimColor">#80000000</item>
         <item name="allAppsTheme">@style/AllAppsTheme.Dark</item>
         <item name="popupColorPrimary">@color/popup_color_primary_dark</item>
diff --git a/res/xml/default_workspace_2x2.xml b/res/xml/default_workspace_2x2.xml
new file mode 100644
index 0000000..a4cf881
--- /dev/null
+++ b/res/xml/default_workspace_2x2.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
+
+    <!-- Smartspace Widget -->
+    <appwidget
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:spanX="2"
+        launcher:spanY="1"
+        launcher:packageName="com.google.android.googlequicksearchbox"
+        launcher:className="com.google.android.apps.gsa.staticplugins.smartspace.widget.SmartspaceWidgetProvider" />
+
+    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+    <!-- Messaging, Dialer -->
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
+        <favorite launcher:uri="sms:" />
+        <favorite launcher:uri="smsto:" />
+        <favorite launcher:uri="mms:" />
+        <favorite launcher:uri="mmsto:" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="2"
+        launcher:x="2"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
+        <favorite launcher:uri="tel:123" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
+    </resolve>
+
+    <!-- Bottom row -->
+    <resolve
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />
+        <favorite launcher:uri="mailto:" />
+    </resolve>
+
+    <resolve
+        launcher:screen="0"
+        launcher:x="1"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />
+        <favorite launcher:uri="#Intent;type=images/*;end" />
+    </resolve>
+
+</favorites>
diff --git a/res/xml/default_workspace_3x3.xml b/res/xml/default_workspace_3x3.xml
index 31376e1..0a22f98 100644
--- a/res/xml/default_workspace_3x3.xml
+++ b/res/xml/default_workspace_3x3.xml
@@ -16,6 +16,16 @@
 
 <favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
 
+    <!-- Smartspace Widget -->
+    <appwidget
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:spanX="3"
+        launcher:spanY="1"
+        launcher:packageName="com.google.android.googlequicksearchbox"
+        launcher:className="com.google.android.apps.gsa.staticplugins.smartspace.widget.SmartspaceWidgetProvider" />
+
     <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
     <!-- Messaging, [All Apps], Dialer -->
 
diff --git a/res/xml/default_workspace_4x4.xml b/res/xml/default_workspace_4x4.xml
index bf3c62c..dfde7de 100644
--- a/res/xml/default_workspace_4x4.xml
+++ b/res/xml/default_workspace_4x4.xml
@@ -16,6 +16,16 @@
 
 <favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
 
+    <!-- Smartspace Widget -->
+    <appwidget
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:spanX="4"
+        launcher:spanY="1"
+        launcher:packageName="com.google.android.googlequicksearchbox"
+        launcher:className="com.google.android.apps.gsa.staticplugins.smartspace.widget.SmartspaceWidgetProvider" />
+
     <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
     <!-- Dialer, Messaging, Browser, Camera -->
     <resolve
diff --git a/res/xml/default_workspace_5x5.xml b/res/xml/default_workspace_5x5.xml
index b4ac8f6..7cba7ac 100644
--- a/res/xml/default_workspace_5x5.xml
+++ b/res/xml/default_workspace_5x5.xml
@@ -16,8 +16,18 @@
 
 <favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
 
+    <!-- Smartspace Widget -->
+    <appwidget
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:spanX="5"
+        launcher:spanY="1"
+        launcher:packageName="com.google.android.googlequicksearchbox"
+        launcher:className="com.google.android.apps.gsa.staticplugins.smartspace.widget.SmartspaceWidgetProvider" />
+
     <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
-    <!-- Dialer, Messaging, [Maps/Music], Browser, Camera -->
+    <!-- Dialer, Messaging, [Maps/Music/Settings], Browser, Camera -->
     <resolve
         launcher:container="-101"
         launcher:screen="0"
@@ -47,6 +57,7 @@
         launcher:y="0" >
         <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;end" />
         <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MUSIC;end" />
+        <favorite launcher:uri="#Intent;action=android.settings.SETTINGS;end" />
     </resolve>
 
     <resolve
diff --git a/res/xml/default_workspace_5x6.xml b/res/xml/default_workspace_5x6.xml
new file mode 100644
index 0000000..6a6a556
--- /dev/null
+++ b/res/xml/default_workspace_5x6.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
+
+    <!-- Smartspace Widget -->
+    <appwidget
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:spanX="5"
+        launcher:spanY="1"
+        launcher:packageName="com.google.android.googlequicksearchbox"
+        launcher:className="com.google.android.apps.gsa.staticplugins.smartspace.widget.SmartspaceWidgetProvider" />
+
+    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+    <!-- Dialer, Messaging, [Maps/Music/Settings], Browser, Camera -->
+    <resolve
+        launcher:container="-101"
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
+        <favorite launcher:uri="tel:123" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="1"
+        launcher:x="1"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
+        <favorite launcher:uri="sms:" />
+        <favorite launcher:uri="smsto:" />
+        <favorite launcher:uri="mms:" />
+        <favorite launcher:uri="mmsto:" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="2"
+        launcher:x="2"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;end" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MUSIC;end" />
+        <favorite launcher:uri="#Intent;action=android.settings.SETTINGS;end" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="3"
+        launcher:x="3"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
+        <favorite launcher:uri="http://www.example.com/" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="4"
+        launcher:x="4"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
+    </resolve>
+
+    <!-- Bottom row -->
+    <resolve
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />
+        <favorite launcher:uri="mailto:" />
+    </resolve>
+
+    <resolve
+        launcher:screen="0"
+        launcher:x="1"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />
+        <favorite launcher:uri="#Intent;type=images/*;end" />
+    </resolve>
+
+    <resolve
+        launcher:screen="0"
+        launcher:x="4"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MARKET;end" />
+        <favorite launcher:uri="market://details?id=com.android.launcher" />
+    </resolve>
+
+</favorites>
diff --git a/res/xml/default_workspace_5x7.xml b/res/xml/default_workspace_5x7.xml
new file mode 100644
index 0000000..6a6a556
--- /dev/null
+++ b/res/xml/default_workspace_5x7.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
+
+    <!-- Smartspace Widget -->
+    <appwidget
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:spanX="5"
+        launcher:spanY="1"
+        launcher:packageName="com.google.android.googlequicksearchbox"
+        launcher:className="com.google.android.apps.gsa.staticplugins.smartspace.widget.SmartspaceWidgetProvider" />
+
+    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+    <!-- Dialer, Messaging, [Maps/Music/Settings], Browser, Camera -->
+    <resolve
+        launcher:container="-101"
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
+        <favorite launcher:uri="tel:123" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="1"
+        launcher:x="1"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
+        <favorite launcher:uri="sms:" />
+        <favorite launcher:uri="smsto:" />
+        <favorite launcher:uri="mms:" />
+        <favorite launcher:uri="mmsto:" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="2"
+        launcher:x="2"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;end" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MUSIC;end" />
+        <favorite launcher:uri="#Intent;action=android.settings.SETTINGS;end" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="3"
+        launcher:x="3"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
+        <favorite launcher:uri="http://www.example.com/" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="4"
+        launcher:x="4"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
+    </resolve>
+
+    <!-- Bottom row -->
+    <resolve
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />
+        <favorite launcher:uri="mailto:" />
+    </resolve>
+
+    <resolve
+        launcher:screen="0"
+        launcher:x="1"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />
+        <favorite launcher:uri="#Intent;type=images/*;end" />
+    </resolve>
+
+    <resolve
+        launcher:screen="0"
+        launcher:x="4"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MARKET;end" />
+        <favorite launcher:uri="market://details?id=com.android.launcher" />
+    </resolve>
+
+</favorites>
diff --git a/res/xml/default_workspace_6x6.xml b/res/xml/default_workspace_6x6.xml
new file mode 100644
index 0000000..0666feb
--- /dev/null
+++ b/res/xml/default_workspace_6x6.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
+
+    <!-- Smartspace Widget -->
+    <appwidget
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:spanX="6"
+        launcher:spanY="1"
+        launcher:packageName="com.google.android.googlequicksearchbox"
+        launcher:className="com.google.android.apps.gsa.staticplugins.smartspace.widget.SmartspaceWidgetProvider" />
+
+    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+    <!-- Dialer, Messaging, [Maps/Music/Settings], Browser, Camera -->
+    <resolve
+        launcher:container="-101"
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
+        <favorite launcher:uri="tel:123" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="1"
+        launcher:x="1"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
+        <favorite launcher:uri="sms:" />
+        <favorite launcher:uri="smsto:" />
+        <favorite launcher:uri="mms:" />
+        <favorite launcher:uri="mmsto:" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="2"
+        launcher:x="2"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;end" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MUSIC;end" />
+        <favorite launcher:uri="#Intent;action=android.settings.SETTINGS;end" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="3"
+        launcher:x="3"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
+        <favorite launcher:uri="http://www.example.com/" />
+    </resolve>
+
+    <resolve
+        launcher:container="-101"
+        launcher:screen="4"
+        launcher:x="4"
+        launcher:y="0" >
+        <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
+        <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
+    </resolve>
+
+    <!-- Bottom row -->
+    <resolve
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />
+        <favorite launcher:uri="mailto:" />
+    </resolve>
+
+    <resolve
+        launcher:screen="0"
+        launcher:x="1"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />
+        <favorite launcher:uri="#Intent;type=images/*;end" />
+    </resolve>
+
+    <resolve
+        launcher:screen="0"
+        launcher:x="4"
+        launcher:y="-1" >
+        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MARKET;end" />
+        <favorite launcher:uri="market://details?id=com.android.launcher" />
+    </resolve>
+
+</favorites>
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
index 08698e7..91bf271 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -18,6 +18,34 @@
 <profiles xmlns:launcher="http://schemas.android.com/apk/res-auto" >
 
     <grid-option
+        launcher:name="2_by_2"
+        launcher:numRows="2"
+        launcher:numColumns="2"
+        launcher:numFolderRows="2"
+        launcher:numFolderColumns="2"
+        launcher:numHotseatIcons="2"
+        launcher:dbFile="launcher_2_by_2.db"
+        launcher:defaultLayoutId="@xml/default_workspace_2x2" >
+
+        <display-option
+            launcher:name="Super Short Stubby"
+            launcher:minWidthDps="200"
+            launcher:minHeightDps="200"
+            launcher:iconImageSize="48"
+            launcher:iconTextSize="12.0"
+            launcher:canBeDefault="true" />
+
+        <display-option
+            launcher:name="Shorter Stubby"
+            launcher:minWidthDps="200"
+            launcher:minHeightDps="300"
+            launcher:iconImageSize="48"
+            launcher:iconTextSize="12.0"
+            launcher:canBeDefault="true" />
+
+    </grid-option>
+
+    <grid-option
         launcher:name="3_by_3"
         launcher:numRows="3"
         launcher:numColumns="3"
@@ -33,7 +61,7 @@
             launcher:minWidthDps="255"
             launcher:minHeightDps="300"
             launcher:iconImageSize="48"
-            launcher:iconTextSize="13.0"
+            launcher:iconTextSize="12.0"
             launcher:canBeDefault="true" />
 
         <display-option
@@ -41,7 +69,7 @@
             launcher:minWidthDps="255"
             launcher:minHeightDps="400"
             launcher:iconImageSize="48"
-            launcher:iconTextSize="13.0"
+            launcher:iconTextSize="12.0"
             launcher:canBeDefault="true" />
 
     </grid-option>
@@ -62,7 +90,7 @@
             launcher:minWidthDps="275"
             launcher:minHeightDps="420"
             launcher:iconImageSize="48"
-            launcher:iconTextSize="13.0"
+            launcher:iconTextSize="12.0"
             launcher:canBeDefault="true" />
 
         <display-option
@@ -70,7 +98,7 @@
             launcher:minWidthDps="255"
             launcher:minHeightDps="450"
             launcher:iconImageSize="48"
-            launcher:iconTextSize="13.0"
+            launcher:iconTextSize="12.0"
             launcher:canBeDefault="true" />
 
         <display-option
@@ -78,7 +106,7 @@
             launcher:minWidthDps="296"
             launcher:minHeightDps="491.33"
             launcher:iconImageSize="48"
-            launcher:iconTextSize="13.0"
+            launcher:iconTextSize="12.0"
             launcher:canBeDefault="true" />
 
         <display-option
@@ -86,7 +114,7 @@
             launcher:minWidthDps="359"
             launcher:minHeightDps="567"
             launcher:iconImageSize="54"
-            launcher:iconTextSize="13.0"
+            launcher:iconTextSize="12.0"
             launcher:canBeDefault="true" />
 
         <display-option
@@ -94,7 +122,7 @@
             launcher:minWidthDps="335"
             launcher:minHeightDps="567"
             launcher:iconImageSize="54"
-            launcher:iconTextSize="13.0"
+            launcher:iconTextSize="12.0"
             launcher:canBeDefault="true" />
 
     </grid-option>
@@ -115,7 +143,7 @@
             launcher:minWidthDps="406"
             launcher:minHeightDps="694"
             launcher:iconImageSize="56"
-            launcher:iconTextSize="14.4"
+            launcher:iconTextSize="12.0"
             launcher:canBeDefault="true" />
 
         <display-option
@@ -123,7 +151,7 @@
             launcher:minWidthDps="406"
             launcher:minHeightDps="694"
             launcher:iconImageSize="56"
-            launcher:iconTextSize="14.4"
+            launcher:iconTextSize="12.0"
             launcher:canBeDefault="true" />
 
         <display-option
@@ -131,7 +159,49 @@
             launcher:minWidthDps="255"
             launcher:minHeightDps="400"
             launcher:iconImageSize="48"
-            launcher:iconTextSize="13.0"
+            launcher:iconTextSize="12.0"
+            launcher:canBeDefault="true" />
+
+    </grid-option>
+
+    <grid-option
+        launcher:name="5_by_6"
+        launcher:numRows="6"
+        launcher:numColumns="5"
+        launcher:numFolderRows="5"
+        launcher:numFolderColumns="4"
+        launcher:numHotseatIcons="5"
+        launcher:dbFile="launcher_5_by_6.db"
+        launcher:defaultLayoutId="@xml/default_workspace_5x6"
+        launcher:deviceCategory="phone|multi_display" >
+
+        <display-option
+            launcher:name="Large Phone"
+            launcher:minWidthDps="406"
+            launcher:minHeightDps="694"
+            launcher:iconImageSize="56"
+            launcher:iconTextSize="12.0"
+            launcher:canBeDefault="true" />
+
+    </grid-option>
+
+    <grid-option
+        launcher:name="5_by_7"
+        launcher:numRows="7"
+        launcher:numColumns="5"
+        launcher:numFolderRows="6"
+        launcher:numFolderColumns="4"
+        launcher:numHotseatIcons="5"
+        launcher:dbFile="launcher_5_by_7.db"
+        launcher:defaultLayoutId="@xml/default_workspace_5x7"
+        launcher:deviceCategory="phone|multi_display" >
+
+        <display-option
+            launcher:name="Large Phone"
+            launcher:minWidthDps="406"
+            launcher:minHeightDps="694"
+            launcher:iconImageSize="56"
+            launcher:iconTextSize="12.0"
             launcher:canBeDefault="true" />
 
     </grid-option>
@@ -164,4 +234,25 @@
 
     </grid-option>
 
-</profiles>
\ No newline at end of file
+    <grid-option
+        launcher:name="6_by_6"
+        launcher:numRows="6"
+        launcher:numColumns="6"
+        launcher:numFolderRows="5"
+        launcher:numFolderColumns="5"
+        launcher:numHotseatIcons="6"
+        launcher:dbFile="launcher_6_by_6.db"
+        launcher:defaultLayoutId="@xml/default_workspace_6x6"
+        launcher:deviceCategory="phone|multi_display" >
+
+        <display-option
+            launcher:name="Large Phone"
+            launcher:minWidthDps="406"
+            launcher:minHeightDps="694"
+            launcher:iconImageSize="48"
+            launcher:iconTextSize="12.0"
+            launcher:canBeDefault="true" />
+
+    </grid-option>
+
+</profiles>
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 90de498..5d3c9b0 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -50,6 +50,32 @@
         launcher:logIdOn="615"
         launcher:logIdOff="616" />
 
+    <SwitchPreference
+        android:key="pref_allow_phone_taskbar"
+        android:title="@string/pref_allow_phone_taskbar"
+        android:summary="@string/pref_allow_phone_taskbar_desc" />
+
+    <SwitchPreference
+        android:key="pref_allow_phone_overview_grid"
+        android:title="@string/pref_allow_phone_overview_grid"
+        android:summary="@string/pref_allow_phone_overview_grid_desc" />
+
+    <SwitchPreference
+        android:defaultValue="true"
+        android:key="pref_enable_minus_one"
+        android:summary="@string/pref_show_google_now_summary"
+        android:title="@string/title_show_google_app"/>
+
+    <androidx.preference.PreferenceScreen
+        android:key="pref_suggestions"
+        android:persistent="false"
+        android:title="@string/pref_suggestions_title"
+        android:summary="@string/pref_suggestions_summary">
+
+        <intent android:action="android.settings.ACTION_CONTENT_SUGGESTIONS_SETTINGS" />
+
+    </androidx.preference.PreferenceScreen>
+
     <androidx.preference.PreferenceScreen
         android:key="pref_developer_options"
         android:persistent="false"
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index d2b9dfe..4f020c9 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -23,6 +23,7 @@
 
 import android.annotation.SuppressLint;
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Path;
@@ -48,6 +49,9 @@
 @SuppressLint("NewApi")
 public class DeviceProfile {
 
+    public static final String KEY_PHONE_TASKBAR = "pref_allow_phone_taskbar";
+    public static final String KEY_PHONE_OVERVIEW_GRID = "pref_allow_phone_overview_grid";
+
     private static final int DEFAULT_DOT_SIZE = 100;
     // Ratio of empty space, qsb should take up to appear visually centered.
     private static final float QSB_CENTER_FACTOR = .325f;
@@ -270,7 +274,9 @@
         }
 
         hotseatQsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
-        isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
+        SharedPreferences prefs = Utilities.getPrefs(context);
+        boolean allowPhoneTaskbar = prefs.getBoolean(KEY_PHONE_TASKBAR, false);
+        isTaskbarPresent = (isTablet || allowPhoneTaskbar) && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
                 && FeatureFlags.ENABLE_TASKBAR.get();
         if (isTaskbarPresent) {
             taskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_size);
@@ -355,7 +361,9 @@
                 ? res.getDimensionPixelSize(R.dimen.scalable_grid_qsb_bottom_margin)
                 : 0;
 
-        overviewShowAsGrid = isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get();
+        boolean allowPhoneOverviewGrid = prefs.getBoolean(KEY_PHONE_OVERVIEW_GRID, false);
+        overviewShowAsGrid = (isTablet || allowPhoneOverviewGrid) &&
+                FeatureFlags.ENABLE_OVERVIEW_GRID.get();
         overviewTaskMarginPx = overviewShowAsGrid
                 ? res.getDimensionPixelSize(R.dimen.overview_task_margin_focused)
                 : res.getDimensionPixelSize(R.dimen.overview_task_margin);
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index ff7a90c..49d697d 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -26,6 +26,7 @@
 import android.appwidget.AppWidgetHostView;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -55,6 +56,7 @@
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.WindowBounds;
 
+import com.android.quickstep.SystemUiProxy;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -66,7 +68,7 @@
 import java.util.Collections;
 import java.util.List;
 
-public class InvariantDeviceProfile {
+public class InvariantDeviceProfile implements SharedPreferences.OnSharedPreferenceChangeListener {
 
     public static final String TAG = "IDP";
     // We do not need any synchronization for this variable as its only written on UI thread.
@@ -167,6 +169,7 @@
     public Rect defaultWidgetPadding;
 
     private final ArrayList<OnIDPChangeListener> mChangeListeners = new ArrayList<>();
+    private Context mContext;
 
     @VisibleForTesting
     public InvariantDeviceProfile() {
@@ -187,6 +190,23 @@
                         onConfigChanged(displayContext);
                     }
                 });
+
+        mContext = context;
+        Utilities.getPrefs(context).registerOnSharedPreferenceChangeListener(this);
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+        if (DeviceProfile.KEY_PHONE_TASKBAR.equals(key)) {
+            // Create the illusion of this taking effect immediately
+            // Also needed because TaskbarManager inits before SystemUiProxy on start
+            boolean enabled = Utilities.getPrefs(mContext).getBoolean(DeviceProfile.KEY_PHONE_TASKBAR, false);
+            SystemUiProxy.INSTANCE.get(mContext).setTaskbarEnabled(enabled);
+
+            onConfigChanged(mContext, true);
+        } else if (DeviceProfile.KEY_PHONE_OVERVIEW_GRID.equals(key)) {
+            onConfigChanged(mContext, false);
+        }
     }
 
     /**
@@ -398,6 +418,10 @@
     }
 
     private void onConfigChanged(Context context) {
+        onConfigChanged(context, false);
+    }
+
+    private void onConfigChanged(Context context, boolean taskbarChanged) {
         Object[] oldState = toModelState();
 
         // Re-init grid
@@ -406,7 +430,7 @@
 
         boolean modelPropsChanged = !Arrays.equals(oldState, toModelState());
         for (OnIDPChangeListener listener : mChangeListeners) {
-            listener.onIdpChanged(modelPropsChanged);
+            listener.onIdpChanged(modelPropsChanged, taskbarChanged);
         }
     }
 
@@ -654,7 +678,7 @@
         /**
          * Called when the device provide changes
          */
-        void onIdpChanged(boolean modelPropertiesChanged);
+        void onIdpChanged(boolean modelPropertiesChanged, boolean taskbarChanged);
     }
 
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 87eb222..777c5a7 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -380,6 +380,8 @@
     protected InstanceId mAllAppsSessionLogId;
     private LauncherState mPrevLauncherState;
 
+    private boolean mPendingRestart;
+
     @Override
     @TargetApi(Build.VERSION_CODES.S)
     protected void onCreate(Bundle savedInstanceState) {
@@ -591,7 +593,7 @@
     public void onConfigurationChanged(Configuration newConfig) {
         int diff = newConfig.diff(mOldConfig);
         if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
-            onIdpChanged(false);
+            onIdpChanged(false, false);
         }
 
         mOldConfig.setTo(newConfig);
@@ -599,7 +601,11 @@
     }
 
     @Override
-    public void onIdpChanged(boolean modelPropertiesChanged) {
+    public void onIdpChanged(boolean modelPropertiesChanged, boolean taskbarChanged) {
+        if (taskbarChanged) {
+            mPendingRestart = true;
+        }
+
         initDeviceProfile(mDeviceProfile.inv);
         dispatchDeviceProfileChanged();
         reapplyUi();
@@ -1145,6 +1151,10 @@
         }
 
         TraceHelper.INSTANCE.endSection(traceToken);
+
+        if (mPendingRestart) {
+            System.exit(0);
+        }
     }
 
     @Override
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 10023b4..adbb36b 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -83,7 +83,7 @@
         Log.v(Launcher.TAG, "LauncherAppState initiated");
         Preconditions.assertUIThread();
 
-        mInvariantDeviceProfile.addOnChangeListener(modelPropertiesChanged -> {
+        mInvariantDeviceProfile.addOnChangeListener((modelPropertiesChanged, taskbarChanged) -> {
             if (modelPropertiesChanged) {
                 refreshAndReloadLauncher();
             }
diff --git a/src/com/android/launcher3/LauncherFiles.java b/src/com/android/launcher3/LauncherFiles.java
index e59eac8..9845d88 100644
--- a/src/com/android/launcher3/LauncherFiles.java
+++ b/src/com/android/launcher3/LauncherFiles.java
@@ -16,7 +16,10 @@
     private static final String XML = ".xml";
 
     public static final String LAUNCHER_DB = "launcher.db";
+    public static final String LAUNCHER_6_BY_6_DB = "launcher_6_by_6.db";
     public static final String LAUNCHER_6_BY_5_DB = "launcher_6_by_5.db";
+    public static final String LAUNCHER_5_BY_7_DB = "launcher_5_by_7.db";
+    public static final String LAUNCHER_5_BY_6_DB = "launcher_5_by_6.db";
     public static final String LAUNCHER_4_BY_5_DB = "launcher_4_by_5.db";
     public static final String LAUNCHER_4_BY_4_DB = "launcher_4_by_4.db";
     public static final String LAUNCHER_3_BY_3_DB = "launcher_3_by_3.db";
@@ -33,7 +36,10 @@
 
     public static final List<String> GRID_DB_FILES = Collections.unmodifiableList(Arrays.asList(
             LAUNCHER_DB,
+            LAUNCHER_6_BY_6_DB,
             LAUNCHER_6_BY_5_DB,
+            LAUNCHER_5_BY_7_DB,
+            LAUNCHER_5_BY_6_DB,
             LAUNCHER_4_BY_5_DB,
             LAUNCHER_4_BY_4_DB,
             LAUNCHER_3_BY_3_DB,
diff --git a/src/com/android/launcher3/OverlayCallbackImpl.java b/src/com/android/launcher3/OverlayCallbackImpl.java
new file mode 100644
index 0000000..8d8609b
--- /dev/null
+++ b/src/com/android/launcher3/OverlayCallbackImpl.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.Utilities;
+import com.android.systemui.plugins.shared.LauncherOverlayManager;
+import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlay;
+
+import com.google.android.libraries.gsa.launcherclient.LauncherClient;
+import com.google.android.libraries.gsa.launcherclient.LauncherClientCallbacks;
+
+import java.io.PrintWriter;
+
+/**
+ * Implements {@link LauncherOverlay} and passes all the corresponding events to {@link
+ * LauncherClient}. {@see setClient}
+ *
+ * <p>Implements {@link LauncherClientCallbacks} and sends all the corresponding callbacks to {@link
+ * Launcher}.
+ */
+public class OverlayCallbackImpl
+        implements LauncherOverlay, LauncherClientCallbacks, LauncherOverlayManager,
+        OnSharedPreferenceChangeListener {
+
+    public static final String KEY_ENABLE_MINUS_ONE = "pref_enable_minus_one";
+
+    private final Launcher mLauncher;
+    private final LauncherClient mClient;
+
+    private LauncherOverlayCallbacks mLauncherOverlayCallbacks;
+    private boolean mWasOverlayAttached = false;
+
+    public OverlayCallbackImpl(Launcher launcher) {
+        SharedPreferences prefs = Utilities.getPrefs(launcher);
+
+        mLauncher = launcher;
+        mClient = new LauncherClient(mLauncher, this, getClientOptions(prefs));
+        prefs.registerOnSharedPreferenceChangeListener(this);
+    }
+
+    @Override
+    public void onDeviceProvideChanged() {
+        mClient.reattachOverlay();
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        mClient.onAttachedToWindow();
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        mClient.onDetachedFromWindow();
+    }
+
+    @Override
+    public void dump(String prefix, PrintWriter w) {
+        mClient.dump(prefix, w);
+    }
+
+    @Override
+    public void openOverlay() {
+        mClient.showOverlay(true);
+    }
+
+    @Override
+    public void hideOverlay(boolean animate) {
+        mClient.hideOverlay(animate);
+    }
+
+    @Override
+    public void hideOverlay(int duration) {
+        mClient.hideOverlay(duration);
+    }
+
+    @Override
+    public boolean startSearch(byte[] config, Bundle extras) {
+        return false;
+    }
+
+    @Override
+    public void onActivityCreated(Activity activity, Bundle bundle) {
+        // Not called
+    }
+
+    @Override
+    public void onActivityStarted(Activity activity) {
+        mClient.onStart();
+    }
+
+    @Override
+    public void onActivityResumed(Activity activity) {
+        mClient.onResume();
+    }
+
+    @Override
+    public void onActivityPaused(Activity activity) {
+        mClient.onPause();
+    }
+
+    @Override
+    public void onActivityStopped(Activity activity) {
+        mClient.onStop();
+    }
+
+    @Override
+    public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { }
+
+    @Override
+    public void onActivityDestroyed(Activity activity) {
+        mClient.onDestroy();
+        mLauncher.getSharedPrefs().unregisterOnSharedPreferenceChangeListener(this);
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+        if (KEY_ENABLE_MINUS_ONE.equals(key)) {
+            mClient.setClientOptions(getClientOptions(prefs));
+        }
+    }
+
+    @Override
+    public void onServiceStateChanged(boolean overlayAttached, boolean hotwordActive) {
+        if (overlayAttached != mWasOverlayAttached) {
+            mWasOverlayAttached = overlayAttached;
+            mLauncher.setLauncherOverlay(overlayAttached ? this : null);
+        }
+    }
+
+    @Override
+    public void onOverlayScrollChanged(float progress) {
+        if (mLauncherOverlayCallbacks != null) {
+            mLauncherOverlayCallbacks.onScrollChanged(progress);
+        }
+    }
+
+    @Override
+    public void onScrollInteractionBegin() {
+        mClient.startMove();
+    }
+
+    @Override
+    public void onScrollInteractionEnd() {
+        mClient.endMove();
+    }
+
+    @Override
+    public void onScrollChange(float progress, boolean rtl) {
+        mClient.updateMove(progress);
+    }
+
+    @Override
+    public void setOverlayCallbacks(LauncherOverlayCallbacks callbacks) {
+        mLauncherOverlayCallbacks = callbacks;
+    }
+
+
+    private LauncherClient.ClientOptions getClientOptions(SharedPreferences prefs) {
+        return new LauncherClient.ClientOptions(
+                prefs.getBoolean(KEY_ENABLE_MINUS_ONE, true),
+                true, /* enableHotword */
+                true /* enablePrewarming */
+        );
+    }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 3ba6ea4..a796d13 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -760,6 +760,7 @@
         if (headerColor != mHeaderColor || mTabsProtectionAlpha != tabsAlpha) {
             mHeaderColor = headerColor;
             mTabsProtectionAlpha = tabsAlpha;
+            getSearchView().setBackgroundResource(R.drawable.bg_all_apps_searchbox);
             invalidateHeader();
         }
         if (mSearchUiManager.getEditText() != null) {
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 85ee636..44ec71c 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -314,7 +314,7 @@
 
         mTabLayout.setTranslationY(mTranslationY);
 
-        int clipHeight = mHeaderTopPadding - getPaddingBottom();
+        int clipHeight = mHeaderTopPadding - getPaddingBottom() * 2;
         mRVClip.top = mTabsHidden ? clipHeight : 0;
         mHeaderClip.top = clipHeight;
         // clipping on a draw might cause additional redraw
@@ -441,7 +441,7 @@
         if (mTabsHidden || !mHeaderCollapsed) {
             return 0;
         }
-        return Math.max(getHeight() - getPaddingTop() + mTranslationY, 0);
+        return Math.max(getHeight() - getPaddingTop() + mTranslationY + getPaddingBottom(), 0);
     }
 }
 
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index 4c5a9e6..77ed796 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -79,7 +79,6 @@
 
         mSearchQueryBuilder = new SpannableStringBuilder();
         Selection.setSelection(mSearchQueryBuilder, 0);
-        setHint(prefixTextWithIcon(getContext(), R.drawable.ic_allapps_search, getHint()));
 
         mContentOverlap =
                 getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_field_height) / 2;
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 2d31aa4..186e36c 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -40,7 +40,7 @@
     private FeatureFlags() { }
 
     public static boolean showFlagTogglerUi(Context context) {
-        return Utilities.IS_DEBUG_DEVICE && Utilities.isDevelopersOptionsEnabled(context);
+        return Utilities.isDevelopersOptionsEnabled(context);
     }
 
     /**
@@ -52,7 +52,7 @@
      * Enable moving the QSB on the 0th screen of the workspace. This is not a configuration feature
      * and should be modified at a project level.
      */
-    public static final boolean QSB_ON_FIRST_SCREEN = true;
+    public static final boolean QSB_ON_FIRST_SCREEN = false;
 
     /**
      * Feature flag to handle define config changes dynamically instead of killing the process.
@@ -74,7 +74,7 @@
 
     // TODO: b/206508141: Long pressing on some icons on home screen cause launcher to crash.
     public static final BooleanFlag ENABLE_LOCAL_COLOR_POPUPS = getDebugFlag(
-            "ENABLE_LOCAL_COLOR_POPUPS", false, "Enable local color extraction for popups.");
+            "ENABLE_LOCAL_COLOR_POPUPS", true, "Enable local color extraction for popups.");
 
     public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(
             "KEYGUARD_ANIMATION", false, "Enable animation for keyguard going away on wallpaper");
@@ -209,7 +209,7 @@
             "Uses two panel on home screen. Only applicable on large screen devices.");
 
     public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(
-            "ENABLE_SCRIM_FOR_APP_LAUNCH", false,
+            "ENABLE_SCRIM_FOR_APP_LAUNCH", true,
             "Enables scrim during app launch animation.");
 
     public static final BooleanFlag ENABLE_SPLIT_SELECT = getDebugFlag(
@@ -334,8 +334,6 @@
     }
 
     private static BooleanFlag getDebugFlag(String key, boolean defaultValue, String description) {
-        return Utilities.IS_DEBUG_DEVICE
-                ? new DebugFlag(key, defaultValue, description)
-                : new BooleanFlag(key, defaultValue);
+        return new DebugFlag(key, defaultValue, description);
     }
 }
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 0c39632..1305479 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -20,8 +20,12 @@
 
 import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;
 
+import static com.android.launcher3.OverlayCallbackImpl.KEY_ENABLE_MINUS_ONE;
+
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.view.MenuItem;
@@ -63,9 +67,8 @@
         SharedPreferences.OnSharedPreferenceChangeListener{
 
     /** List of fragments that can be hosted by this activity. */
-    private static final List<String> VALID_PREFERENCE_FRAGMENTS =
-            !Utilities.IS_DEBUG_DEVICE ? Collections.emptyList()
-                    : Collections.singletonList(DeveloperOptionsFragment.class.getName());
+    private static final List<String> VALID_PREFERENCE_FRAGMENTS = Collections.singletonList(
+            DeveloperOptionsFragment.class.getName());
 
     private static final String DEVELOPER_OPTIONS_KEY = "pref_developer_options";
     private static final String FLAGS_PREFERENCE_KEY = "flag_toggler";
@@ -189,6 +192,10 @@
         private boolean mPreferenceHighlighted = false;
         private Preference mDeveloperOptionPref;
 
+        protected static final String GSA_PACKAGE = "com.google.android.googlequicksearchbox";
+
+        private Preference mShowGoogleAppPref;
+
         @Override
         public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
             final Bundle args = getArguments();
@@ -270,6 +277,11 @@
                 case DEVELOPER_OPTIONS_KEY:
                     mDeveloperOptionPref = preference;
                     return updateDeveloperOption();
+
+                case KEY_ENABLE_MINUS_ONE:
+                    mShowGoogleAppPref = preference;
+                    updateIsGoogleAppEnabled();
+                    return true;
             }
 
             return true;
@@ -293,6 +305,20 @@
             return showPreference;
         }
 
+        public static boolean isGSAEnabled(Context context) {
+            try {
+                return context.getPackageManager().getApplicationInfo(GSA_PACKAGE, 0).enabled;
+            } catch (PackageManager.NameNotFoundException e) {
+                return false;
+            }
+        }
+
+        private void updateIsGoogleAppEnabled() {
+            if (mShowGoogleAppPref != null) {
+                mShowGoogleAppPref.setEnabled(isGSAEnabled(getContext()));
+            }
+        }
+
         @Override
         public void onResume() {
             super.onResume();
@@ -308,6 +334,7 @@
                     requestAccessibilityFocus(getListView());
                 }
             }
+            updateIsGoogleAppEnabled();
         }
 
         private PreferenceHighlighter createHighlighter() {
diff --git a/src/org/protonaosp/launcher3/ThemedLocalColorExtractor.java b/src/org/protonaosp/launcher3/ThemedLocalColorExtractor.java
new file mode 100644
index 0000000..955a72e
--- /dev/null
+++ b/src/org/protonaosp/launcher3/ThemedLocalColorExtractor.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR condITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.protonaosp.launcher3;
+
+import android.app.WallpaperColors;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.provider.Settings;
+import android.util.SparseIntArray;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.widget.LocalColorExtractor;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import dev.kdrag0n.colorkt.Color;
+import dev.kdrag0n.colorkt.cam.Zcam;
+import dev.kdrag0n.colorkt.data.Illuminants;
+import dev.kdrag0n.colorkt.rgb.Srgb;
+import dev.kdrag0n.colorkt.tristimulus.CieXyzAbs;
+import dev.kdrag0n.colorkt.ucs.lab.CieLab;
+import dev.kdrag0n.monet.theme.ColorScheme;
+import dev.kdrag0n.monet.theme.DynamicColorScheme;
+import dev.kdrag0n.monet.theme.MaterialYouTargets;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class ThemedLocalColorExtractor extends LocalColorExtractor implements
+        WallpaperManager.LocalWallpaperColorConsumer {
+    private static final String KEY_COLOR_SOURCE = "android.theme.customization.color_source";
+
+    // Shade number -> color resource ID maps
+    private static final SparseIntArray ACCENT1_RES = new SparseIntArray(13);
+    private static final SparseIntArray ACCENT2_RES = new SparseIntArray(13);
+    private static final SparseIntArray ACCENT3_RES = new SparseIntArray(13);
+    private static final SparseIntArray NEUTRAL1_RES = new SparseIntArray(13);
+    private static final SparseIntArray NEUTRAL2_RES = new SparseIntArray(13);
+
+    // Viewing conditions and targets for theme generation
+    private final Zcam.ViewingConditions cond = new Zcam.ViewingConditions(
+            /* surroundFactor */ Zcam.ViewingConditions.SURROUND_AVERAGE,
+            /* adaptingLuminance */ 0.4 * CieXyzAbs.DEFAULT_SDR_WHITE_LUMINANCE,
+            /* backgroundLuminance */ new CieLab(50.0, 0.0, 0.0, Illuminants.D65)
+                    .toXyz().getY() * CieXyzAbs.DEFAULT_SDR_WHITE_LUMINANCE,
+            /* referenceWhite */ CieXyzAbs.fromRel(Illuminants.D65,
+                    CieXyzAbs.DEFAULT_SDR_WHITE_LUMINANCE)
+    );
+    private final ColorScheme targets = new MaterialYouTargets(1.0, false, cond);
+
+    private final WallpaperManager wallpaperManager;
+    private Listener listener;
+
+    private boolean applyOverlay = true;
+
+    // For calculating and returning bounds
+    private final float[] tempFloatArray = new float[4];
+    private final Rect tempRect = new Rect();
+    private final RectF tempRectF = new RectF();
+
+    static {
+        ACCENT1_RES.put(   0, android.R.color.system_accent1_0);
+        ACCENT1_RES.put(  10, android.R.color.system_accent1_10);
+        ACCENT1_RES.put(  50, android.R.color.system_accent1_50);
+        ACCENT1_RES.put( 100, android.R.color.system_accent1_100);
+        ACCENT1_RES.put( 200, android.R.color.system_accent1_200);
+        ACCENT1_RES.put( 300, android.R.color.system_accent1_300);
+        ACCENT1_RES.put( 400, android.R.color.system_accent1_400);
+        ACCENT1_RES.put( 500, android.R.color.system_accent1_500);
+        ACCENT1_RES.put( 600, android.R.color.system_accent1_600);
+        ACCENT1_RES.put( 700, android.R.color.system_accent1_700);
+        ACCENT1_RES.put( 800, android.R.color.system_accent1_800);
+        ACCENT1_RES.put( 900, android.R.color.system_accent1_900);
+        ACCENT1_RES.put(1000, android.R.color.system_accent1_1000);
+
+        ACCENT2_RES.put(   0, android.R.color.system_accent2_0);
+        ACCENT2_RES.put(  10, android.R.color.system_accent2_10);
+        ACCENT2_RES.put(  50, android.R.color.system_accent2_50);
+        ACCENT2_RES.put( 100, android.R.color.system_accent2_100);
+        ACCENT2_RES.put( 200, android.R.color.system_accent2_200);
+        ACCENT2_RES.put( 300, android.R.color.system_accent2_300);
+        ACCENT2_RES.put( 400, android.R.color.system_accent2_400);
+        ACCENT2_RES.put( 500, android.R.color.system_accent2_500);
+        ACCENT2_RES.put( 600, android.R.color.system_accent2_600);
+        ACCENT2_RES.put( 700, android.R.color.system_accent2_700);
+        ACCENT2_RES.put( 800, android.R.color.system_accent2_800);
+        ACCENT2_RES.put( 900, android.R.color.system_accent2_900);
+        ACCENT2_RES.put(1000, android.R.color.system_accent2_1000);
+
+        ACCENT3_RES.put(   0, android.R.color.system_accent3_0);
+        ACCENT3_RES.put(  10, android.R.color.system_accent3_10);
+        ACCENT3_RES.put(  50, android.R.color.system_accent3_50);
+        ACCENT3_RES.put( 100, android.R.color.system_accent3_100);
+        ACCENT3_RES.put( 200, android.R.color.system_accent3_200);
+        ACCENT3_RES.put( 300, android.R.color.system_accent3_300);
+        ACCENT3_RES.put( 400, android.R.color.system_accent3_400);
+        ACCENT3_RES.put( 500, android.R.color.system_accent3_500);
+        ACCENT3_RES.put( 600, android.R.color.system_accent3_600);
+        ACCENT3_RES.put( 700, android.R.color.system_accent3_700);
+        ACCENT3_RES.put( 800, android.R.color.system_accent3_800);
+        ACCENT3_RES.put( 900, android.R.color.system_accent3_900);
+        ACCENT3_RES.put(1000, android.R.color.system_accent3_1000);
+
+        NEUTRAL1_RES.put(   0, android.R.color.system_neutral1_0);
+        NEUTRAL1_RES.put(  10, android.R.color.system_neutral1_10);
+        NEUTRAL1_RES.put(  50, android.R.color.system_neutral1_50);
+        NEUTRAL1_RES.put( 100, android.R.color.system_neutral1_100);
+        NEUTRAL1_RES.put( 200, android.R.color.system_neutral1_200);
+        NEUTRAL1_RES.put( 300, android.R.color.system_neutral1_300);
+        NEUTRAL1_RES.put( 400, android.R.color.system_neutral1_400);
+        NEUTRAL1_RES.put( 500, android.R.color.system_neutral1_500);
+        NEUTRAL1_RES.put( 600, android.R.color.system_neutral1_600);
+        NEUTRAL1_RES.put( 700, android.R.color.system_neutral1_700);
+        NEUTRAL1_RES.put( 800, android.R.color.system_neutral1_800);
+        NEUTRAL1_RES.put( 900, android.R.color.system_neutral1_900);
+        NEUTRAL1_RES.put(1000, android.R.color.system_neutral1_1000);
+
+        NEUTRAL2_RES.put(   0, android.R.color.system_neutral2_0);
+        NEUTRAL2_RES.put(  10, android.R.color.system_neutral2_10);
+        NEUTRAL2_RES.put(  50, android.R.color.system_neutral2_50);
+        NEUTRAL2_RES.put( 100, android.R.color.system_neutral2_100);
+        NEUTRAL2_RES.put( 200, android.R.color.system_neutral2_200);
+        NEUTRAL2_RES.put( 300, android.R.color.system_neutral2_300);
+        NEUTRAL2_RES.put( 400, android.R.color.system_neutral2_400);
+        NEUTRAL2_RES.put( 500, android.R.color.system_neutral2_500);
+        NEUTRAL2_RES.put( 600, android.R.color.system_neutral2_600);
+        NEUTRAL2_RES.put( 700, android.R.color.system_neutral2_700);
+        NEUTRAL2_RES.put( 800, android.R.color.system_neutral2_800);
+        NEUTRAL2_RES.put( 900, android.R.color.system_neutral2_900);
+        NEUTRAL2_RES.put(1000, android.R.color.system_neutral2_1000);
+    }
+
+    public ThemedLocalColorExtractor(Context context) {
+        wallpaperManager = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
+
+        try {
+            String json = Settings.Secure.getString(context.getContentResolver(),
+                    Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES);
+            if (json != null && !json.isEmpty()) {
+                JSONObject packages = new JSONObject(json);
+                applyOverlay = !"preset".equals(packages.getString(KEY_COLOR_SOURCE));
+            }
+        } catch (JSONException e) {
+            // Ignore: enabled by default
+        }
+    }
+
+    private static void addColorsToArray(Map<Integer, Color> swatch,
+            SparseIntArray resMap, SparseIntArray array) {
+        for (Map.Entry<Integer, Color> entry : swatch.entrySet()) {
+            int shade = entry.getKey();
+            int resId = resMap.get(shade, -1);
+            if (resId != -1) {
+                Srgb color = (Srgb) entry.getValue();
+                array.put(resId, 0xff000000 | color.toRgb8());
+            }
+        }
+    }
+
+    @Override
+    public void setListener(Listener listener) {
+        this.listener = listener;
+    }
+
+    @Override
+    public void setWorkspaceLocation(Rect pos, View child, int screenId) {
+        Launcher launcher = ActivityContext.lookupContext(child.getContext());
+        getExtractedRectForViewRect(launcher, screenId, pos, tempRectF);
+
+        // Refresh listener
+        wallpaperManager.removeOnColorsChangedListener(this);
+        wallpaperManager.addOnColorsChangedListener(this, Collections.singletonList(tempRectF));
+    }
+
+    @Override
+    public SparseIntArray generateColorsOverride(WallpaperColors colors) {
+        if (!applyOverlay) {
+            return null;
+        }
+
+        SparseIntArray colorRes = new SparseIntArray(5 * 13);
+        Color color = new Srgb(colors.getPrimaryColor().toArgb());
+        ColorScheme colorScheme = new DynamicColorScheme(targets, color, 1.0, cond, true);
+
+        addColorsToArray(colorScheme.getAccent1(), ACCENT1_RES, colorRes);
+        addColorsToArray(colorScheme.getAccent2(), ACCENT2_RES, colorRes);
+        addColorsToArray(colorScheme.getAccent3(), ACCENT3_RES, colorRes);
+        addColorsToArray(colorScheme.getNeutral1(), NEUTRAL1_RES, colorRes);
+        addColorsToArray(colorScheme.getNeutral2(), NEUTRAL2_RES, colorRes);
+
+        return colorRes;
+    }
+
+    @Override
+    public void applyColorsOverride(Context base, WallpaperColors colors) {
+        if (!applyOverlay) {
+            return;
+        }
+
+        RemoteViews.ColorResources res = RemoteViews.ColorResources.create(base, generateColorsOverride(colors));
+        if (res != null) {
+            res.apply(base);
+        }
+    }
+
+    private void getExtractedRectForViewRect(Launcher launcher, int pageId, Rect rectInDragLayer,
+            RectF colorExtractionRectOut) {
+        // If the view hasn't been measured and laid out, we cannot do this.
+        if (rectInDragLayer.isEmpty()) {
+            colorExtractionRectOut.setEmpty();
+            return;
+        }
+
+        Resources res = launcher.getResources();
+        DeviceProfile dp = launcher.getDeviceProfile().inv.getDeviceProfile(launcher);
+        float screenWidth = dp.widthPx;
+        float screenHeight = dp.heightPx;
+        int numScreens = launcher.getWorkspace().getNumPagesForWallpaperParallax();
+        pageId = Utilities.isRtl(res) ? numScreens - pageId - 1 : pageId;
+        float relativeScreenWidth = 1f / numScreens;
+
+        int[] dragLayerBounds = new int[2];
+        launcher.getDragLayer().getLocationOnScreen(dragLayerBounds);
+        // Translate from drag layer coordinates to screen coordinates.
+        int screenLeft = rectInDragLayer.left + dragLayerBounds[0];
+        int screenTop = rectInDragLayer.top + dragLayerBounds[1];
+        int screenRight = rectInDragLayer.right + dragLayerBounds[0];
+        int screenBottom = rectInDragLayer.bottom + dragLayerBounds[1];
+
+        // This is the position of the view relative to the wallpaper, as expected by the
+        // local color extraction of the WallpaperManager.
+        // The coordinate system is such that, on the horizontal axis, each screen has a
+        // distinct range on the [0,1] segment. So if there are 3 screens, they will have the
+        // ranges [0, 1/3], [1/3, 2/3] and [2/3, 1]. The position on the subrange should be
+        // the position of the view relative to the screen. For the vertical axis, this is
+        // simply the location of the view relative to the screen.
+        // Translate from drag layer coordinates to screen coordinates
+        colorExtractionRectOut.left = (screenLeft / screenWidth + pageId) * relativeScreenWidth;
+        colorExtractionRectOut.right = (screenRight / screenWidth + pageId) * relativeScreenWidth;
+        colorExtractionRectOut.top = screenTop / screenHeight;
+        colorExtractionRectOut.bottom = screenBottom / screenHeight;
+
+        if (colorExtractionRectOut.left < 0
+                || colorExtractionRectOut.right > 1
+                || colorExtractionRectOut.top < 0
+                || colorExtractionRectOut.bottom > 1) {
+            colorExtractionRectOut.setEmpty();
+        }
+    }
+
+    @Override
+    public void onColorsChanged(RectF area, WallpaperColors colors) {
+        if (listener != null) {
+            listener.onColorsChanged(generateColorsOverride(colors));
+        }
+    }
+}