Add full preview for theme picker

Video: https://drive.google.com/file/d/1UoAZxxjJEKwq9ZYJ3MWca8ygEX97vhBz/view?usp=sharing

Test: Manually
Bug: 151286773
Change-Id: Ib94425fa716a58f0cf3b43ca3d2c05cccf4a52ec
diff --git a/res/layout/fragment_theme_full_preview.xml b/res/layout/fragment_theme_full_preview.xml
new file mode 100644
index 0000000..7573c5b
--- /dev/null
+++ b/res/layout/fragment_theme_full_preview.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include layout="@layout/section_header"/>
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:paddingTop="@dimen/full_preview_page_default_padding_top"
+        android:paddingBottom="@dimen/full_preview_page_default_padding_bottom"
+        android:clipToPadding="false"
+        android:background="@color/fullscreen_preview_background">
+
+        <include layout="@layout/theme_preview_card_v2"/>
+    </FrameLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/src/com/android/customization/model/theme/DefaultThemeProvider.java b/src/com/android/customization/model/theme/DefaultThemeProvider.java
index 1528c0d..c0937b4 100644
--- a/src/com/android/customization/model/theme/DefaultThemeProvider.java
+++ b/src/com/android/customization/model/theme/DefaultThemeProvider.java
@@ -324,6 +324,13 @@
         }
     }
 
+    @Nullable
+    @Override
+    public ThemeBundle.Builder parseThemeBundle(String serializedTheme) throws JSONException {
+        return parseCustomTheme(serializedTheme);
+    }
+
+    @Nullable
     @Override
     public CustomTheme.Builder parseCustomTheme(String serializedTheme) throws JSONException {
         JSONObject theme = new JSONObject(serializedTheme);
diff --git a/src/com/android/customization/model/theme/ThemeBundleProvider.java b/src/com/android/customization/model/theme/ThemeBundleProvider.java
index fac11cd..34342b3 100644
--- a/src/com/android/customization/model/theme/ThemeBundleProvider.java
+++ b/src/com/android/customization/model/theme/ThemeBundleProvider.java
@@ -43,6 +43,8 @@
 
     void removeCustomTheme(CustomTheme theme);
 
+    @Nullable ThemeBundle.Builder parseThemeBundle(String serializedTheme) throws JSONException;
+
     @Nullable CustomTheme.Builder parseCustomTheme(String serializedTheme) throws JSONException;
 
     ThemeBundle findEquivalent(ThemeBundle other);
diff --git a/src/com/android/customization/picker/ViewOnlyFullPreviewActivity.java b/src/com/android/customization/picker/ViewOnlyFullPreviewActivity.java
index 19324da..2afbc16 100644
--- a/src/com/android/customization/picker/ViewOnlyFullPreviewActivity.java
+++ b/src/com/android/customization/picker/ViewOnlyFullPreviewActivity.java
@@ -15,9 +15,12 @@
  */
 package com.android.customization.picker;
 
+import static com.android.customization.picker.theme.ThemeFullPreviewFragment.EXTRA_THEME_OPTION_TITLE;
+
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.text.TextUtils;
 
 import androidx.annotation.IntDef;
 import androidx.annotation.Nullable;
@@ -25,6 +28,7 @@
 import androidx.fragment.app.FragmentActivity;
 
 import com.android.customization.picker.grid.GridFullPreviewFragment;
+import com.android.customization.picker.theme.ThemeFullPreviewFragment;
 import com.android.wallpaper.R;
 import com.android.wallpaper.widget.BottomActionBar;
 import com.android.wallpaper.widget.BottomActionBar.BottomActionBarHost;
@@ -63,8 +67,15 @@
         @Section final int section = intent.getIntExtra(EXTRA_PREVIEW_SECTION, 0);
         final Bundle bundle = intent.getBundleExtra(EXTRA_PREVIEW_BUNDLE);
         if (section == SECTION_GRID) {
-            showFragment(
-                    GridFullPreviewFragment.newInstance(getString(R.string.grid_title), bundle));
+            showFragment(GridFullPreviewFragment.newInstance(
+                    getString(R.string.grid_title), bundle));
+        } else if (section == SECTION_STYLE) {
+            final String themeTitle = bundle.getString(EXTRA_THEME_OPTION_TITLE);
+            showFragment(ThemeFullPreviewFragment.newInstance(
+                    TextUtils.isEmpty(themeTitle)
+                            ? getString(R.string.theme_title)
+                            : themeTitle,
+                    bundle));
         }
     }
 
diff --git a/src/com/android/customization/picker/theme/ThemeFragment.java b/src/com/android/customization/picker/theme/ThemeFragment.java
index bc7796b..1ab3329 100644
--- a/src/com/android/customization/picker/theme/ThemeFragment.java
+++ b/src/com/android/customization/picker/theme/ThemeFragment.java
@@ -15,6 +15,12 @@
  */
 package com.android.customization.picker.theme;
 
+import static android.app.Activity.RESULT_OK;
+
+import static com.android.customization.picker.ViewOnlyFullPreviewActivity.SECTION_STYLE;
+import static com.android.customization.picker.theme.ThemeFullPreviewFragment.EXTRA_THEME_OPTION;
+import static com.android.customization.picker.theme.ThemeFullPreviewFragment.EXTRA_THEME_OPTION_TITLE;
+import static com.android.customization.picker.theme.ThemeFullPreviewFragment.EXTRA_WALLPAPER_INFO;
 import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY;
 
 import android.app.Activity;
@@ -56,6 +62,7 @@
 import com.android.customization.module.ThemesUserEventLogger;
 import com.android.customization.picker.BasePreviewAdapter;
 import com.android.customization.picker.TimeTicker;
+import com.android.customization.picker.ViewOnlyFullPreviewActivity;
 import com.android.customization.picker.WallpaperPreviewer;
 import com.android.customization.picker.theme.ThemePreviewPage.ThemeCoverPage;
 import com.android.customization.picker.theme.ThemePreviewPage.TimeContainer;
@@ -80,6 +87,7 @@
 
     private static final String TAG = "ThemeFragment";
     private static final String KEY_SELECTED_THEME = "ThemeFragment.SelectedThemeBundle";
+    private static final int FULL_PREVIEW_REQUEST_CODE = 1000;
 
     private static final boolean USE_NEW_PREVIEW = false;
 
@@ -141,11 +149,17 @@
         if (USE_NEW_PREVIEW) {
             mPreviewPager.setVisibility(View.GONE);
             view.findViewById(R.id.preview_card_container).setVisibility(View.VISIBLE);
+            // Set Wallpaper background.
             mWallpaperPreviewer = new WallpaperPreviewer(
                     getLifecycle(),
                     getActivity(),
                     view.findViewById(R.id.wallpaper_preview_image),
                     view.findViewById(R.id.wallpaper_preview_surface));
+            mCurrentWallpaperFactory.createCurrentWallpaperInfos(
+                    (homeWallpaper, lockWallpaper, presentationMode) -> {
+                        mCurrentHomeWallpaper = homeWallpaper;
+                        mWallpaperPreviewer.setWallpaper(mCurrentHomeWallpaper);
+                    }, false);
             view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
                 @Override
                 public void onLayoutChange(View v, int left, int top, int right, int bottom,
@@ -154,10 +168,13 @@
                     view.removeOnLayoutChangeListener(this);
                 }
             });
+
+            ViewGroup previewContainer = view.findViewById(R.id.theme_preview_container);
+            previewContainer.setOnClickListener(v -> showFullPreview());
             mThemeOptionPreviewer = new ThemeOptionPreviewer(
                     getLifecycle(),
                     getContext(),
-                    view.findViewById(R.id.theme_preview_container));
+                    previewContainer);
         }
         return view;
     }
@@ -206,9 +223,11 @@
     @Override
     public void onResume() {
         super.onResume();
-        mTicker = TimeTicker.registerNewReceiver(getContext(), this::updateTime);
-        reloadWallpaper();
-        updateTime();
+        if (!USE_NEW_PREVIEW) {
+            mTicker = TimeTicker.registerNewReceiver(getContext(), this::updateTime);
+            reloadWallpaper();
+            updateTime();
+        }
     }
 
     private void updateTime() {
@@ -220,7 +239,7 @@
     @Override
     public void onPause() {
         super.onPause();
-        if (getContext() != null) {
+        if (getContext() != null && !USE_NEW_PREVIEW) {
             getContext().unregisterReceiver(mTicker);
         }
     }
@@ -251,6 +270,8 @@
                     reloadOptions();
                 }
             }
+        } else if (requestCode == FULL_PREVIEW_REQUEST_CODE && resultCode == RESULT_OK) {
+            applyTheme();
         }
         super.onActivityResult(requestCode, resultCode, data);
     }
@@ -259,15 +280,11 @@
         mCurrentWallpaperFactory.createCurrentWallpaperInfos(
                 (homeWallpaper, lockWallpaper, presentationMode) -> {
                     mCurrentHomeWallpaper = homeWallpaper;
-                    if (USE_NEW_PREVIEW) {
-                        mWallpaperPreviewer.setWallpaper(mCurrentHomeWallpaper);
-                    } else {
-                        mCurrentWallpaperThumbAsset = new BitmapCachingAsset(getContext(),
-                                mCurrentHomeWallpaper.getThumbAsset(getContext()));
-                        if (mSelectedTheme != null && mAdapter != null) {
-                            mAdapter.setWallpaperAsset(mCurrentWallpaperThumbAsset);
-                            mAdapter.rebindWallpaperIfAvailable();
-                        }
+                    mCurrentWallpaperThumbAsset = new BitmapCachingAsset(getContext(),
+                            mCurrentHomeWallpaper.getThumbAsset(getContext()));
+                    if (mSelectedTheme != null && mAdapter != null) {
+                        mAdapter.setWallpaperAsset(mCurrentWallpaperThumbAsset);
+                        mAdapter.rebindWallpaperIfAvailable();
                     }
         }, false);
     }
@@ -401,6 +418,15 @@
         startActivityForResult(intent, CustomThemeActivity.REQUEST_CODE_CUSTOM_THEME);
     }
 
+    private void showFullPreview() {
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(EXTRA_WALLPAPER_INFO, mCurrentHomeWallpaper);
+        bundle.putString(EXTRA_THEME_OPTION, mSelectedTheme.getSerializedPackages());
+        bundle.putString(EXTRA_THEME_OPTION_TITLE, mSelectedTheme.getTitle());
+        Intent intent = ViewOnlyFullPreviewActivity.newIntent(getContext(), SECTION_STYLE, bundle);
+        startActivityForResult(intent, FULL_PREVIEW_REQUEST_CODE);
+    }
+
     /**
      * Adapter class for mPreviewPager.
      * This is a ViewPager as it allows for a nice pagination effect (ie, pages snap on swipe,
diff --git a/src/com/android/customization/picker/theme/ThemeFullPreviewFragment.java b/src/com/android/customization/picker/theme/ThemeFullPreviewFragment.java
new file mode 100644
index 0000000..9181daa
--- /dev/null
+++ b/src/com/android/customization/picker/theme/ThemeFullPreviewFragment.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.customization.picker.theme;
+
+import static android.app.Activity.RESULT_OK;
+
+import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.customization.model.theme.DefaultThemeProvider;
+import com.android.customization.model.theme.ThemeBundle;
+import com.android.customization.model.theme.ThemeBundleProvider;
+import com.android.customization.module.CustomizationInjector;
+import com.android.customization.picker.WallpaperPreviewer;
+import com.android.wallpaper.R;
+import com.android.wallpaper.model.WallpaperInfo;
+import com.android.wallpaper.module.InjectorProvider;
+import com.android.wallpaper.picker.AppbarFragment;
+import com.android.wallpaper.widget.BottomActionBar;
+
+import com.bumptech.glide.Glide;
+
+import org.json.JSONException;
+
+/** A Fragment for theme full preview page. */
+public class ThemeFullPreviewFragment extends AppbarFragment {
+    private static final String TAG = "ThemeFullPreviewFragment";
+
+    public static final String EXTRA_THEME_OPTION_TITLE = "theme_option_title";
+    protected static final String EXTRA_THEME_OPTION = "theme_option";
+    protected static final String EXTRA_WALLPAPER_INFO = "wallpaper_info";
+
+    private WallpaperInfo mWallpaper;
+    private ThemeBundle mThemeBundle;
+
+    /**
+     * Returns a new {@link ThemeFullPreviewFragment} with the provided title and bundle arguments
+     * set.
+     */
+    public static ThemeFullPreviewFragment newInstance(CharSequence title, Bundle intentBundle) {
+        ThemeFullPreviewFragment fragment = new ThemeFullPreviewFragment();
+        Bundle bundle = new Bundle();
+        bundle.putAll(AppbarFragment.createArguments(title));
+        bundle.putAll(intentBundle);
+        fragment.setArguments(bundle);
+        return fragment;
+    }
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mWallpaper = getArguments().getParcelable(EXTRA_WALLPAPER_INFO);
+        CustomizationInjector injector = (CustomizationInjector) InjectorProvider.getInjector();
+        ThemeBundleProvider themeProvider = new DefaultThemeProvider(
+                getContext(), injector.getCustomizationPreferences(getContext()));
+        try {
+            ThemeBundle.Builder builder = themeProvider.parseThemeBundle(
+                    getArguments().getString(EXTRA_THEME_OPTION));
+            if (builder != null) {
+                builder.setTitle(getArguments().getString(EXTRA_THEME_OPTION_TITLE));
+                mThemeBundle = builder.build(getContext());
+            }
+        } catch (JSONException e) {
+            Log.w(TAG, "Couldn't parse provided custom theme, will override it");
+            // TODO(chihhangchuang): Handle the error case.
+        }
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+                             @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(
+                R.layout.fragment_theme_full_preview, container, /* attachToRoot */ false);
+        setUpToolbar(view);
+        Glide.get(getContext()).clearMemory();
+
+        // Set wallpaper background.
+        final WallpaperPreviewer wallpaperPreviewer = new WallpaperPreviewer(
+                getLifecycle(),
+                getActivity(),
+                view.findViewById(R.id.wallpaper_preview_image),
+                view.findViewById(R.id.wallpaper_preview_surface));
+        wallpaperPreviewer.setWallpaper(mWallpaper);
+        view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                                       int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                wallpaperPreviewer.updatePreviewCardRadius();
+                view.removeOnLayoutChangeListener(this);
+            }
+        });
+
+        // Set theme option.
+        final ThemeOptionPreviewer themeOptionPreviewer = new ThemeOptionPreviewer(
+                getLifecycle(),
+                getContext(),
+                view.findViewById(R.id.theme_preview_container));
+        themeOptionPreviewer.setThemeBundle(mThemeBundle);
+        return view;
+    }
+
+    @Override
+    protected void onBottomActionBarReady(BottomActionBar bottomActionBar) {
+        bottomActionBar.showActionsOnly(APPLY);
+        bottomActionBar.setActionClickListener(APPLY, v -> finishActivityWithResultOk());
+        bottomActionBar.show();
+    }
+
+    private void finishActivityWithResultOk() {
+        Activity activity = requireActivity();
+        activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
+        Intent intent = new Intent();
+        activity.setResult(RESULT_OK, intent);
+        activity.finish();
+    }
+}