Merging from ub-launcher3-master @ build 6665145 am: 01adf9b8a5

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/ThemePicker/+/12115221

Change-Id: I7e3d0d325ef73f3bd006dd6d007913f20e222b91
diff --git a/res/layout/custom_theme_option.xml b/res/layout/custom_theme_option.xml
index 2805185..aff43a9 100644
--- a/res/layout/custom_theme_option.xml
+++ b/res/layout/custom_theme_option.xml
@@ -15,7 +15,7 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingHorizontal="@dimen/option_padding_horizontal"
     android:paddingBottom="@dimen/option_bottom_margin"
diff --git a/res/layout/grid_option.xml b/res/layout/grid_option.xml
index 286c60b..d06ff60 100644
--- a/res/layout/grid_option.xml
+++ b/res/layout/grid_option.xml
@@ -15,9 +15,9 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingRight="2dp"
+    android:paddingHorizontal="@dimen/option_padding_horizontal"
     android:paddingBottom="@dimen/option_bottom_margin"
     android:clipChildren="false"
     android:clipToPadding="false"
diff --git a/res/layout/theme_component_preview.xml b/res/layout/theme_component_preview.xml
index 43b8bf1..bf3255d 100644
--- a/res/layout/theme_component_preview.xml
+++ b/res/layout/theme_component_preview.xml
@@ -48,6 +48,7 @@
             android:layout_gravity="center_horizontal"
             android:drawablePadding="@dimen/theme_preview_header_drawable_padding"
             android:textAppearance="@style/CardTitleTextAppearance"
+            android:importantForAccessibility="no"
             app:layout_constraintBottom_toTopOf="@id/theme_preview_card_body_container"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintHorizontal_bias="0.5"
@@ -64,6 +65,7 @@
             android:layout_marginHorizontal="8dp"
             android:layout_marginTop="@dimen/preview_theme_content_margin"
             android:clipChildren="false"
+            android:importantForAccessibility="noHideDescendants"
             app:layout_constraintBottom_toTopOf="@+id/guideline"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintHeight_max="@dimen/preview_theme_content_max_height"
diff --git a/res/layout/theme_option.xml b/res/layout/theme_option.xml
index 379c507..bdf82d0 100644
--- a/res/layout/theme_option.xml
+++ b/res/layout/theme_option.xml
@@ -15,7 +15,7 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingHorizontal="@dimen/option_padding_horizontal"
     android:paddingBottom="@dimen/option_bottom_margin"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b4ec835..d12b05e 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -52,6 +52,18 @@
     <!-- Content description of grid preview card. [CHAR_LIMIT=30]-->
     <string name="grid_preview_card_content_description">Grid preview</string>
 
+    <!-- Content description of font preview. [CHAR_LIMIT=30]-->
+    <string name="font_preview_content_description">Font preview</string>
+
+    <!-- Content description of icon preview. [CHAR_LIMIT=30]-->
+    <string name="icon_preview_content_description">Icon preview</string>
+
+    <!-- Content description of color preview. [CHAR_LIMIT=30]-->
+    <string name="color_preview_content_description">Color preview</string>
+
+    <!-- Content description of shape preview. [CHAR_LIMIT=30]-->
+    <string name="shape_preview_content_description">Shape preview</string>
+
     <!-- Content description indicating that the selected option is currently applied to the device. [CHAR_LIMIT=NONE] -->
     <string name="option_applied_description"><xliff:g name="style_name">%1$s</xliff:g>, currently applied</string>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index dd0f2a3..b4e1971 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -103,6 +103,7 @@
         <item name="android:paddingBottom">16dp</item>
         <item name="android:paddingStart">12dp</item>
         <item name="android:paddingEnd">12dp</item>
+        <item name="android:textAlignment">viewStart</item>
         <item name="android:textColor">@color/edittext_text_color</item>
         <item name="android:inputType">text</item>
         <item name="android:maxLength">100</item>
diff --git a/src/com/android/customization/model/theme/ThemeBundle.java b/src/com/android/customization/model/theme/ThemeBundle.java
index 43b07ff..4ede59e 100644
--- a/src/com/android/customization/model/theme/ThemeBundle.java
+++ b/src/com/android/customization/model/theme/ThemeBundle.java
@@ -272,9 +272,9 @@
                 mAppName = appName;
             }
 
-            /** Returns the app icon drawable. */
-            public Drawable getDrawable() {
-                return mIconDrawable;
+            /** Returns a copy of app icon drawable. */
+            public Drawable getDrawableCopy() {
+                return mIconDrawable.getConstantState().newDrawable().mutate();
             }
 
             /** Returns the app name. */
@@ -340,7 +340,7 @@
                 shapeDrawable.setIntrinsicHeight((int) PATH_SIZE);
                 shapeDrawable.setIntrinsicWidth((int) PATH_SIZE);
                 for (ShapeAppIcon icon : mAppIcons) {
-                    Drawable drawable = icon.getDrawable();
+                    Drawable drawable = icon.mIconDrawable;
                     if (drawable instanceof AdaptiveIconDrawable) {
                         AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) drawable;
                         shapeIcons.add(new ShapeAppIcon(
diff --git a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
index 178098c..5922f5c 100644
--- a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
+++ b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
@@ -138,6 +138,9 @@
 
         @Override
         public void bindPreview(ViewGroup container) {
+            container.setContentDescription(
+                    container.getContext().getString(R.string.font_preview_content_description));
+
             bindPreviewHeader(container, R.string.preview_name_font, R.drawable.ic_font);
 
             ViewGroup cardBody = container.findViewById(R.id.theme_preview_card_body_container);
@@ -225,6 +228,9 @@
 
         @Override
         public void bindPreview(ViewGroup container) {
+            container.setContentDescription(
+                    container.getContext().getString(R.string.icon_preview_content_description));
+
             bindPreviewHeader(container, R.string.preview_name_icon, R.drawable.ic_wifi_24px);
 
             ViewGroup cardBody = container.findViewById(R.id.theme_preview_card_body_container);
@@ -355,6 +361,9 @@
 
         @Override
         public void bindPreview(ViewGroup container) {
+            container.setContentDescription(
+                    container.getContext().getString(R.string.color_preview_content_description));
+
             bindPreviewHeader(container, R.string.preview_name_color, R.drawable.ic_colorize_24px);
 
             ViewGroup cardBody = container.findViewById(R.id.theme_preview_card_body_container);
@@ -495,6 +504,9 @@
 
         @Override
         public void bindPreview(ViewGroup container) {
+            container.setContentDescription(
+                    container.getContext().getString(R.string.shape_preview_content_description));
+
             bindPreviewHeader(container, R.string.preview_name_shape, R.drawable.ic_shapes_24px);
 
             ViewGroup cardBody = container.findViewById(R.id.theme_preview_card_body_container);
@@ -504,7 +516,7 @@
             }
             for (int i = 0; i < mShapeIconIds.length && i < mAppIcons.size(); i++) {
                 ImageView iconView = cardBody.findViewById(mShapeIconIds[i]);
-                iconView.setBackground(mAppIcons.get(i).getDrawable());
+                iconView.setBackground(mAppIcons.get(i).getDrawableCopy());
             }
         }
 
diff --git a/src/com/android/customization/picker/theme/ThemeOptionPreviewer.java b/src/com/android/customization/picker/theme/ThemeOptionPreviewer.java
index 7b4d220..5c775dd 100644
--- a/src/com/android/customization/picker/theme/ThemeOptionPreviewer.java
+++ b/src/com/android/customization/picker/theme/ThemeOptionPreviewer.java
@@ -288,7 +288,7 @@
             ShapeAppIcon icon = appIcons.get(i);
             // Set app icon.
             ImageView iconView = mContentView.findViewById(mShapeAppIconIds[i]);
-            iconView.setBackground(icon.getDrawable());
+            iconView.setBackground(icon.getDrawableCopy());
             // Set app name.
             TextView appName = mContentView.findViewById(mShapeIconAppNameIds[i]);
             appName.setText(icon.getAppName());
diff --git a/src/com/android/customization/widget/DynamicAdaptiveIconDrawable.java b/src/com/android/customization/widget/DynamicAdaptiveIconDrawable.java
index 06d8392..afcb27c 100644
--- a/src/com/android/customization/widget/DynamicAdaptiveIconDrawable.java
+++ b/src/com/android/customization/widget/DynamicAdaptiveIconDrawable.java
@@ -3,7 +3,6 @@
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
-import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
@@ -27,8 +26,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
-import com.android.wallpaper.R;
-
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -765,6 +762,8 @@
     }
 
     static class LayerState extends ConstantState {
+        private final DynamicAdaptiveIconDrawable mOwner;
+
         private int[] mThemeAttrs;
 
         final static int N_CHILDREN = 2;
@@ -791,6 +790,7 @@
 
         LayerState(@Nullable LayerState orig, @NonNull DynamicAdaptiveIconDrawable owner,
                 @Nullable Resources res) {
+            mOwner = owner;
             mChildren = new ChildDrawable[N_CHILDREN];
             if (orig != null) {
                 final ChildDrawable[] origChildDrawable = orig.mChildren;
@@ -800,7 +800,7 @@
 
                 for (int i = 0; i < N_CHILDREN; i++) {
                     final ChildDrawable or = origChildDrawable[i];
-                    mChildren[i] = new ChildDrawable(or, owner, res);
+                    mChildren[i] = new ChildDrawable(or, mOwner, res);
                 }
 
                 mCheckedOpacity = orig.mCheckedOpacity;
@@ -842,12 +842,13 @@
 
         @Override
         public Drawable newDrawable() {
-            return new DynamicAdaptiveIconDrawable(this, null, null);
+            return new DynamicAdaptiveIconDrawable(mOwner.getBackground(), mOwner.getForeground(),
+                    mOwner.mOriginalMask);
         }
 
         @Override
         public Drawable newDrawable(@Nullable Resources res) {
-            return new DynamicAdaptiveIconDrawable(this, res, null);
+            return newDrawable();
         }
 
         @Override
diff --git a/src/com/android/customization/widget/OptionSelectorController.java b/src/com/android/customization/widget/OptionSelectorController.java
index 49dfb82..db09aa6 100644
--- a/src/com/android/customization/widget/OptionSelectorController.java
+++ b/src/com/android/customization/widget/OptionSelectorController.java
@@ -228,9 +228,14 @@
             }
         };
 
-        mContainer.setLayoutManager(new LinearLayoutManager(mContainer.getContext(),
-                LinearLayoutManager.HORIZONTAL, false));
         Resources res = mContainer.getContext().getResources();
+        if (mUseGrid) {
+            mContainer.setLayoutManager(new GridLayoutManager(mContainer.getContext(),
+                    res.getInteger(R.integer.options_grid_num_columns)));
+        } else {
+            mContainer.setLayoutManager(new LinearLayoutManager(mContainer.getContext(),
+                    LinearLayoutManager.HORIZONTAL, false));
+        }
 
         mContainer.setAdapter(mAdapter);
 
@@ -250,14 +255,18 @@
 
         if (mUseGrid) {
             int numColumns = res.getInteger(R.integer.options_grid_num_columns);
-            int widthPerItem = totalWidth / mAdapter.getItemCount();
+            int widthPerItem = res.getDimensionPixelOffset(R.dimen.option_tile_width);
             int extraSpace = availableWidth - widthPerItem * numColumns;
             while (extraSpace < 0) {
                 numColumns -= 1;
                 extraSpace = availableWidth - widthPerItem * numColumns;
             }
-            int containerSidePadding = extraSpace / (numColumns + 1);
-            mContainer.setLayoutManager(new GridLayoutManager(mContainer.getContext(), numColumns));
+
+            if (mContainer.getLayoutManager() != null) {
+                ((GridLayoutManager) mContainer.getLayoutManager()).setSpanCount(numColumns);
+            }
+
+            int containerSidePadding = (extraSpace / (numColumns + 1)) / 2;
             mContainer.setPaddingRelative(containerSidePadding, 0, containerSidePadding, 0);
             mContainer.setOverScrollMode(View.OVER_SCROLL_NEVER);
             return;
diff --git a/src/com/android/customization/widget/ThemeInfoView.java b/src/com/android/customization/widget/ThemeInfoView.java
index a733a40..b21b96f 100644
--- a/src/com/android/customization/widget/ThemeInfoView.java
+++ b/src/com/android/customization/widget/ThemeInfoView.java
@@ -72,7 +72,7 @@
 
             if (previewInfo.shapeAppIcons.get(SHAPE_PREVIEW_INDEX) != null) {
                 mAppPreviewImageView.setBackground(
-                        previewInfo.shapeAppIcons.get(SHAPE_PREVIEW_INDEX).getDrawable());
+                        previewInfo.shapeAppIcons.get(SHAPE_PREVIEW_INDEX).getDrawableCopy());
             }
 
             if (previewInfo.shapeDrawable != null) {