Merge "Add support for live wallpapers in theme bundles" into ub-launcher3-qt-dev
diff --git a/res/drawable/ic_check_circle_filled_24px.xml b/res/drawable/ic_check_circle_filled_24px.xml
new file mode 100644
index 0000000..cacf1d8
--- /dev/null
+++ b/res/drawable/ic_check_circle_filled_24px.xml
@@ -0,0 +1,28 @@
+<!--
+     Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="@color/selected_check_background_color"
+      android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10s10,-4.5 10,-10S17.5,2 12,2zM10,17l-4,-4l1.4,-1.4l2.6,2.6l6.6,-6.6L18,9L10,17z"/>
+  <path
+      android:pathData="m8.0085,14.9866 l-1.9939,-1.994 0.6892,-0.6889 0.6892,-0.6889 1.2925,1.2926c0.7109,0.711 1.3035,1.2926 1.3169,1.2926 0.0134,0 1.5034,-1.4789 3.3111,-3.2865l3.2866,-3.2865 0.689,0.689 0.689,0.689 -3.9878,3.9878 -3.9878,3.9878z"
+      android:strokeWidth="0.02439024"
+      android:fillColor="@color/selected_check_color"/>
+</vector>
diff --git a/res/drawable/ic_tune_24px.xml b/res/drawable/ic_tune.xml
similarity index 94%
rename from res/drawable/ic_tune_24px.xml
rename to res/drawable/ic_tune.xml
index abad67c..a6dd634 100644
--- a/res/drawable/ic_tune_24px.xml
+++ b/res/drawable/ic_tune.xml
@@ -14,8 +14,8 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="20dp"
+    android:height="20dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
   <path
diff --git a/res/layout/preview_card_cover_content.xml b/res/layout/preview_card_cover_content.xml
index 408fadc..aa20204 100644
--- a/res/layout/preview_card_cover_content.xml
+++ b/res/layout/preview_card_cover_content.xml
@@ -27,8 +27,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_weight="0"
-        android:layout_marginTop="40dp"
-        android:layout_marginBottom="36dp"
+        android:layout_marginBottom="24dp"
         android:gravity="center|bottom"
         android:orientation="horizontal">
         <FrameLayout
diff --git a/res/layout/theme_preview_card.xml b/res/layout/theme_preview_card.xml
index deccd48..d8cb8a9 100644
--- a/res/layout/theme_preview_card.xml
+++ b/res/layout/theme_preview_card.xml
@@ -32,7 +32,8 @@
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:padding="@dimen/preview_card_padding"
+            android:paddingTop="@dimen/preview_card_padding"
+            android:paddingHorizontal="@dimen/preview_card_padding"
             android:orientation="vertical">
 
             <ViewStub
@@ -42,19 +43,23 @@
                 android:layout_height="wrap_content"
                 android:layout_marginBottom="20dp"/>
 
-            <TextView
+              <TextView
                 android:id="@+id/theme_preview_card_header"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="48dp"
                 android:drawablePadding="10dp"
                 android:textAppearance="@style/CardTitleTextAppearance"/>
 
+            <Space
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_weight="1" />
+
             <FrameLayout
                 android:id="@+id/theme_preview_card_body_container"
                 android:layout_width="match_parent"
-                android:layout_height="0dp"
+                android:layout_height="wrap_content"
                 android:layout_marginHorizontal="8dp"
                 android:layout_weight="1"/>
 
@@ -63,7 +68,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_horizontal"
-                android:drawableStart="@drawable/ic_tune_24px"
+                android:drawableStart="@drawable/ic_tune"
                 android:drawablePadding="8dp"
                 android:gravity="center"
                 android:text="@string/edit_custom_theme_lbl"
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index edd414d..c5e81b2 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -31,6 +31,9 @@
     <color name="tip_dot_color">#81C995</color>
     <color name="tip_dot_line_color">#000000</color>
 
+    <color name="selected_check_color">#000000</color>
+    <color name="selected_check_background_color">#81C995</color>
+
     <color name="toolbar_icon_color">@color/text_color_light</color>
     <color name="toolbar_color">#000000</color>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 8e30525..d45a4d7 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -48,6 +48,9 @@
     <color name="tip_dot_color">#34A853</color>
     <color name="tip_dot_line_color">#FFFFFF</color>
 
+    <color name="selected_check_color">#FFFFFF</color>
+    <color name="selected_check_background_color">#1E8E3E</color>
+
     <color name="toolbar_icon_color">@color/text_color_dark</color>
     <color name="toolbar_color">@color/material_white_100</color>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b36bb13..465a926 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -22,6 +22,8 @@
     <dimen name="tip_dot_size">8dp</dimen>
     <dimen name="tip_dot_line_width">2dp</dimen>
 
+    <dimen name="check_size">12dp</dimen>
+
     <dimen name="preview_indicator_width">16dp</dimen>
     <dimen name="preview_indicator_height">8dp</dimen>
     <dimen name="indicator_container_height">48dp</dimen>
@@ -59,7 +61,7 @@
     <dimen name="theme_option_label_margin">4dp</dimen>
 
     <dimen name="preview_card_corner_radius">8dp</dimen>
-    <dimen name="preview_card_padding">24dp</dimen>
+    <dimen name="preview_card_padding">16dp</dimen>
 
     <dimen name="card_title_text_size">16sp</dimen>
     <dimen name="card_cover_title_text_size">24sp</dimen>
diff --git a/src/com/android/customization/model/theme/ThemeBundle.java b/src/com/android/customization/model/theme/ThemeBundle.java
index 370a72a..414719e 100644
--- a/src/com/android/customization/model/theme/ThemeBundle.java
+++ b/src/com/android/customization/model/theme/ThemeBundle.java
@@ -45,7 +45,6 @@
 
 import com.android.customization.model.CustomizationManager;
 import com.android.customization.model.CustomizationOption;
-import com.android.customization.model.theme.custom.CustomTheme;
 import com.android.customization.widget.DynamicAdaptiveIconDrawable;
 import com.android.wallpaper.R;
 import com.android.wallpaper.asset.Asset;
@@ -109,7 +108,7 @@
                     mPreviewInfo.shapeDrawable);
         }
         if (!mPreviewInfo.icons.isEmpty()) {
-            Drawable icon = mPreviewInfo.icons.get(0).mutate();
+            Drawable icon = mPreviewInfo.icons.get(0).getConstantState().newDrawable().mutate();
             icon.setTint(res.getColor(R.color.icon_thumbnail_color, null));
             ((ImageView) view.findViewById(R.id.theme_option_icon)).setImageDrawable(
                     icon);
diff --git a/src/com/android/customization/picker/theme/ThemeFragment.java b/src/com/android/customization/picker/theme/ThemeFragment.java
index 4deb198..7f6754f 100644
--- a/src/com/android/customization/picker/theme/ThemeFragment.java
+++ b/src/com/android/customization/picker/theme/ThemeFragment.java
@@ -262,6 +262,9 @@
                 // Select the default theme if there is no matching custom enabled theme
                 // TODO(b/124796742): default to custom if there is no matching theme bundle
                 mSelectedTheme = options.get(0);
+            } else {
+                // Only show show checkmark if we found a matching theme
+                mOptionsController.setAppliedOption(mSelectedTheme);
             }
             mOptionsController.setSelectedOption(mSelectedTheme);
         }, false);
@@ -280,6 +283,9 @@
                 // Select the default theme if there is no matching custom enabled theme
                 // TODO(b/124796742): default to custom if there is no matching theme bundle
                 mSelectedTheme = options.get(0);
+            } else {
+                // Only show show checkmark if we found a matching theme
+                mOptionsController.setAppliedOption(mSelectedTheme);
             }
             mOptionsController.setSelectedOption(mSelectedTheme);
         }, true);
@@ -378,7 +384,8 @@
             ViewGroup iconsContainer = card.findViewById(R.id.theme_preview_top_bar_icons);
 
             for (int i = 0; i < iconsContainer.getChildCount() && i < mIcons.size(); i++) {
-                ((ImageView)iconsContainer.getChildAt(i)).setImageDrawable(mIcons.get(i));
+                ((ImageView) iconsContainer.getChildAt(i))
+                        .setImageDrawable(mIcons.get(i).getConstantState().newDrawable().mutate());
             }
 
             ViewGroup body = card.findViewById(R.id.theme_preview_card_body_container);
@@ -497,7 +504,7 @@
                     }
                     for (int i = 0; i < 3 && i < previewInfo.icons.size(); i++) {
                         Drawable icon =
-                                previewInfo.icons.get(i).getConstantState().newDrawable();
+                                previewInfo.icons.get(i).getConstantState().newDrawable().mutate();
                         Drawable bgShape =
                                 previewInfo.shapeDrawable.getConstantState().newDrawable();
                         bgShape.setTint(accentColor);
@@ -542,8 +549,9 @@
                     @Override
                     protected void bindBody(boolean forceRebind) {
                         for (int i = 0; i < mIconIds.length && i < previewInfo.icons.size(); i++) {
-                            ((ImageView) card.findViewById(mIconIds[i])).setImageDrawable(
-                                    previewInfo.icons.get(i));
+                            ((ImageView) card.findViewById(mIconIds[i]))
+                                    .setImageDrawable(previewInfo.icons.get(i)
+                                            .getConstantState().newDrawable().mutate());
                         }
                     }
                 });
@@ -595,10 +603,10 @@
 
                         for (int i = 0; i < mColorTileIds.length && i < previewInfo.icons.size();
                                 i++) {
-                            Drawable icon =
-                                previewInfo.icons.get(i).getConstantState().newDrawable();
+                            Drawable icon = previewInfo.icons.get(i)
+                                    .getConstantState().newDrawable().mutate();
                             Drawable bgShape =
-                                previewInfo.shapeDrawable.getConstantState().newDrawable();
+                                    previewInfo.shapeDrawable.getConstantState().newDrawable();
                             bgShape.setTint(accentColor);
 
                             ImageView bg = card.findViewById(mColorTileIds[i]);
diff --git a/src/com/android/customization/widget/OptionSelectorController.java b/src/com/android/customization/widget/OptionSelectorController.java
index fe04d20..615d7d8 100644
--- a/src/com/android/customization/widget/OptionSelectorController.java
+++ b/src/com/android/customization/widget/OptionSelectorController.java
@@ -16,6 +16,9 @@
 package com.android.customization.widget;
 
 import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -58,6 +61,7 @@
     private final Set<OptionSelectedListener> mListeners = new HashSet<>();
     private RecyclerView.Adapter<TileViewHolder> mAdapter;
     private CustomizationOption mSelectedOption;
+    private CustomizationOption mAppliedOption;
 
     public OptionSelectorController(RecyclerView container, List<T> options) {
         mContainer = container;
@@ -82,6 +86,18 @@
         notifyListeners();
     }
 
+    /**
+     * Mark an option as the one which is currently applied on the device. This will result in a
+     * check being displayed in the lower-right corner of the corresponding ViewHolder.
+     * @param option
+     */
+    public void setAppliedOption(CustomizationOption option) {
+        if (!mOptions.contains(option)) {
+            throw new IllegalArgumentException("Invalid option");
+        }
+        mAppliedOption = option;
+    }
+
     private void updateActivatedStatus(CustomizationOption option, boolean isActivated) {
         int index = mOptions.indexOf(option);
         if (index < 0) {
@@ -115,6 +131,7 @@
                 CustomizationOption option = mOptions.get(position);
                 if (mSelectedOption == null && option.isActive(manager)) {
                     mSelectedOption = option;
+                    mAppliedOption = option;
                 }
                 if (holder.labelView != null) {
                     holder.labelView.setText(option.getTitle());
@@ -122,6 +139,27 @@
                 option.bindThumbnailTile(holder.tileView);
                 holder.itemView.setActivated(option.equals(mSelectedOption));
                 holder.itemView.setOnClickListener(view -> setSelectedOption(option));
+
+                if (option.equals(mAppliedOption)) {
+                    Resources res = mContainer.getContext().getResources();
+                    Drawable checkmark = res.getDrawable(R.drawable.ic_check_circle_filled_24px);
+                    Drawable frame = holder.itemView.getForeground();
+                    Drawable[] layers = {frame, checkmark};
+                    if (frame == null) {
+                        layers = new Drawable[]{checkmark};
+                    }
+                    LayerDrawable checkedFrame = new LayerDrawable(layers);
+
+                    // Position at lower right
+                    int idx = layers.length - 1;
+                    int checkSize = (int) res.getDimension(R.dimen.check_size);
+                    checkedFrame.setLayerGravity(idx, Gravity.BOTTOM | Gravity.RIGHT);
+                    checkedFrame.setLayerWidth(idx, checkSize);
+                    checkedFrame.setLayerHeight(idx, checkSize);
+                    checkedFrame.setLayerInsetBottom(idx, checkSize/2);
+                    checkedFrame.setLayerInsetLeft(idx, checkSize/2);
+                    holder.itemView.setForeground(checkedFrame);
+                }
             }
 
             @Override