Use crop hint to render preview

1. Add SmallPreviewConfigViewModel to represent a configuration
   associated with each small preview view, passing it along the
   binders' call path to reach static preview rendering. In
   WallpaperPreviewViewModel keep a reference to the user selected small
   preview configuratiom.
2. Add ScreenOrientation which will be used with new API.
3. Adding cropHints to StaticWallpaperData.
4. Use crop rect of the desired dimension to render static preview,
   center align the preview if there's none.

Flag: ACONFIG com.android.wallpaper.multi_crop_preview_ui_flag DEVELOPMENT
Bug: 303317694
Test: crop and set wallpaper
Change-Id: I1224c41c1d2b1aaa717c8e43b3513ed563822bfc
diff --git a/src/com/android/wallpaper/model/wallpaper/ScreenOrientation.kt b/src/com/android/wallpaper/model/wallpaper/ScreenOrientation.kt
new file mode 100644
index 0000000..071318d
--- /dev/null
+++ b/src/com/android/wallpaper/model/wallpaper/ScreenOrientation.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2023 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.wallpaper.model.wallpaper
+
+import android.graphics.Point
+
+/** Dimensions supported by wallpaper manager to set crop hints. */
+enum class ScreenOrientation {
+    PORTRAIT,
+    LANDSCAPE,
+    UNFOLDED_PORTRAIT,
+    UNFOLDED_LANDSCAPE,
+}
+
+/**
+ * Gets the [ScreenOrientation] based on the display and its size.
+ *
+ * @param displaySize size of the display.
+ * @param foldableDisplay the display of [displaySize] on foldable devices, null for single display
+ *   devices.
+ */
+fun getScreenOrientation(
+    displaySize: Point,
+    foldableDisplay: FoldableDisplay? = null,
+): ScreenOrientation {
+    return if (foldableDisplay == null || foldableDisplay == FoldableDisplay.FOLDED) {
+        if (displaySize.y >= displaySize.x) ScreenOrientation.PORTRAIT
+        else ScreenOrientation.LANDSCAPE
+    } else {
+        if (displaySize.y >= displaySize.x) ScreenOrientation.UNFOLDED_PORTRAIT
+        else ScreenOrientation.UNFOLDED_LANDSCAPE
+    }
+}
diff --git a/src/com/android/wallpaper/model/wallpaper/StaticWallpaperData.kt b/src/com/android/wallpaper/model/wallpaper/StaticWallpaperData.kt
index d4cb304..0eca60f 100644
--- a/src/com/android/wallpaper/model/wallpaper/StaticWallpaperData.kt
+++ b/src/com/android/wallpaper/model/wallpaper/StaticWallpaperData.kt
@@ -16,7 +16,11 @@
 
 package com.android.wallpaper.model.wallpaper
 
+import android.graphics.Rect
 import com.android.wallpaper.asset.Asset
 
 /** Represents set of attributes that are needed for a static wallpaper. */
-data class StaticWallpaperData(val asset: Asset)
+data class StaticWallpaperData(
+    val asset: Asset,
+    val cropHints: Map<ScreenOrientation, Rect>? = null,
+)
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewPagerBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewPagerBinder.kt
index 3a72178..0bd8271 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewPagerBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewPagerBinder.kt
@@ -19,9 +19,12 @@
 import androidx.lifecycle.LifecycleOwner
 import com.android.wallpaper.R
 import com.android.wallpaper.model.wallpaper.FoldableDisplay
+import com.android.wallpaper.model.wallpaper.getScreenOrientation
+import com.android.wallpaper.module.CustomizationSections
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.DualPreviewViewPager
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.adapters.DualPreviewPagerAdapter
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.adapters.DualPreviewPagerAdapter.Companion.LOCK_PREVIEW_POSITION
+import com.android.wallpaper.picker.preview.ui.viewmodel.SmallPreviewConfigViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.picker.wallpaper.utils.DualDisplayAspectRatioLayout
 import com.android.wallpaper.picker.wallpaper.utils.DualDisplayAspectRatioLayout.Companion.getViewId
@@ -38,9 +41,7 @@
         homePreviewUtils: PreviewUtils,
         lockPreviewUtils: PreviewUtils,
         applicationContext: Context,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
         viewLifecycleOwner: LifecycleOwner,
-        isRtl: Boolean,
         mainScope: CoroutineScope,
         displayUtils: DisplayUtils,
         navigate: () -> Unit,
@@ -63,23 +64,30 @@
                 }
 
             FoldableDisplay.entries.forEach { display ->
-                SmallPreviewBinder.bind(
-                    applicationContext = applicationContext,
-                    view = dualDisplayAspectRatioLayout.requireViewById(display.getViewId()),
-                    viewModel = wallpaperPreviewViewModel,
-                    mainScope = mainScope,
-                    viewLifecycleOwner = viewLifecycleOwner,
-                    isSingleDisplayOrUnfoldedHorizontalHinge =
-                        isSingleDisplayOrUnfoldedHorizontalHinge,
-                    isRtl = isRtl,
-                    previewDisplaySize =
-                        checkNotNull(dualDisplayAspectRatioLayout.getPreviewDisplaySize(display)),
-                    previewDisplayId = checkNotNull(previewDisplays[display]).displayId,
-                    previewUtils =
-                        if (position == LOCK_PREVIEW_POSITION) lockPreviewUtils
-                        else homePreviewUtils,
-                    navigate = navigate,
-                )
+                val previewDisplaySize = dualDisplayAspectRatioLayout.getPreviewDisplaySize(display)
+                previewDisplaySize?.let {
+                    SmallPreviewBinder.bind(
+                        applicationContext = applicationContext,
+                        view = dualDisplayAspectRatioLayout.requireViewById(display.getViewId()),
+                        viewModel = wallpaperPreviewViewModel,
+                        smallPreviewConfig =
+                            SmallPreviewConfigViewModel(
+                                previewTab =
+                                    if (position == LOCK_PREVIEW_POSITION)
+                                        CustomizationSections.Screen.LOCK_SCREEN
+                                    else CustomizationSections.Screen.HOME_SCREEN,
+                                displaySize = it,
+                                screenOrientation = getScreenOrientation(it, display),
+                            ),
+                        mainScope = mainScope,
+                        viewLifecycleOwner = viewLifecycleOwner,
+                        previewDisplayId = checkNotNull(previewDisplays[display]).displayId,
+                        previewUtils =
+                            if (position == LOCK_PREVIEW_POSITION) lockPreviewUtils
+                            else homePreviewUtils,
+                        navigate = navigate,
+                    )
+                }
             }
         }
     }
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewSelectorBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewSelectorBinder.kt
index 30ec582..ea29a83 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewSelectorBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/DualPreviewSelectorBinder.kt
@@ -37,9 +37,7 @@
         homePreviewUtils: PreviewUtils,
         lockPreviewUtils: PreviewUtils,
         applicationContext: Context,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
         viewLifecycleOwner: LifecycleOwner,
-        isRtl: Boolean,
         mainScope: CoroutineScope,
         displayUtils: DisplayUtils,
         navigate: () -> Unit,
@@ -56,9 +54,7 @@
             homePreviewUtils,
             lockPreviewUtils,
             applicationContext,
-            isSingleDisplayOrUnfoldedHorizontalHinge,
             viewLifecycleOwner,
-            isRtl,
             mainScope,
             displayUtils,
             navigate,
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt
index 3755432..ca373ef 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/FullWallpaperPreviewBinder.kt
@@ -44,8 +44,6 @@
         previewViewModel: WallpaperPreviewViewModel,
         viewLifecycleOwner: LifecycleOwner,
         @MainDispatcher mainScope: CoroutineScope,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
-        isRtl: Boolean,
         staticPreviewView: View? = null,
     ) {
         viewLifecycleOwner.lifecycleScope.launch {
@@ -53,7 +51,7 @@
                 surfaceView.let { surfaceView ->
                     surfaceView.setCurrentAndTargetDisplaySize(
                         currentSize = surfaceViewModel.currentDisplaySize,
-                        targetSize = surfaceViewModel.previewTransitionViewModel.targetDisplaySize,
+                        targetSize = surfaceViewModel.selectedSmallPreviewConfig.displaySize,
                     )
                     surfaceView.holder.addCallback(
                         object : SurfaceHolder.Callback {
@@ -85,11 +83,10 @@
                                 }
                                 WallpaperPreviewBinder.bind(
                                     applicationContext,
-                                    isSingleDisplayOrUnfoldedHorizontalHinge,
-                                    isRtl,
                                     mainScope,
                                     viewLifecycleOwner,
                                     previewViewModel,
+                                    surfaceViewModel.selectedSmallPreviewConfig,
                                     surfaceView,
                                     staticPreviewView?.requireViewById(R.id.full_res_image),
                                     staticPreviewView?.requireViewById(R.id.low_res_image),
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewPagerBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewPagerBinder.kt
index 3524c2d..1a5b0a6 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewPagerBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewPagerBinder.kt
@@ -21,9 +21,12 @@
 import androidx.lifecycle.LifecycleOwner
 import androidx.viewpager2.widget.ViewPager2
 import com.android.wallpaper.R
+import com.android.wallpaper.model.wallpaper.getScreenOrientation
+import com.android.wallpaper.module.CustomizationSections.Screen
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.adapters.SinglePreviewPagerAdapter
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.adapters.SinglePreviewPagerAdapter.Companion.LOCK_PREVIEW_POSITION
 import com.android.wallpaper.picker.preview.ui.fragment.smallpreview.pagetransformers.PreviewCardPageTransformer
+import com.android.wallpaper.picker.preview.ui.viewmodel.SmallPreviewConfigViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.PreviewUtils
 import kotlinx.coroutines.CoroutineScope
@@ -34,9 +37,7 @@
     @SuppressLint("WrongConstant")
     fun bind(
         applicationContext: Context,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
         viewLifecycleOwner: LifecycleOwner,
-        isRtl: Boolean,
         mainScope: CoroutineScope,
         previewsViewPager: ViewPager2,
         wallpaperPreviewViewModel: WallpaperPreviewViewModel,
@@ -51,12 +52,16 @@
                     applicationContext = applicationContext,
                     view = viewHolder.itemView.requireViewById(R.id.preview),
                     viewModel = wallpaperPreviewViewModel,
+                    smallPreviewConfig =
+                        SmallPreviewConfigViewModel(
+                            previewTab =
+                                if (position == LOCK_PREVIEW_POSITION) Screen.LOCK_SCREEN
+                                else Screen.HOME_SCREEN,
+                            displaySize = previewDisplaySize,
+                            screenOrientation = getScreenOrientation(previewDisplaySize),
+                        ),
                     mainScope = mainScope,
                     viewLifecycleOwner = viewLifecycleOwner,
-                    isSingleDisplayOrUnfoldedHorizontalHinge =
-                        isSingleDisplayOrUnfoldedHorizontalHinge,
-                    isRtl = isRtl,
-                    previewDisplaySize = previewDisplaySize,
                     previewUtils =
                         if (position == LOCK_PREVIEW_POSITION) lockPreviewUtils
                         else homePreviewUtils,
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewSelectorBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewSelectorBinder.kt
index d8f6486..18b68d9 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/PreviewSelectorBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/PreviewSelectorBinder.kt
@@ -33,9 +33,7 @@
         previewDisplaySize: Point,
         wallpaperPreviewViewModel: WallpaperPreviewViewModel,
         applicationContext: Context,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
         viewLifecycleOwner: LifecycleOwner,
-        isRtl: Boolean,
         mainScope: CoroutineScope,
         homePreviewUtils: PreviewUtils,
         lockPreviewUtils: PreviewUtils,
@@ -47,9 +45,7 @@
         // set up previews view pager
         PreviewPagerBinder.bind(
             applicationContext,
-            isSingleDisplayOrUnfoldedHorizontalHinge,
             viewLifecycleOwner,
-            isRtl,
             mainScope,
             previewsViewPager,
             wallpaperPreviewViewModel,
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt
index 0a946de..e472bdf 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SmallPreviewBinder.kt
@@ -16,7 +16,6 @@
 package com.android.wallpaper.picker.preview.ui.binder
 
 import android.content.Context
-import android.graphics.Point
 import android.view.LayoutInflater
 import android.view.SurfaceView
 import android.view.View
@@ -24,40 +23,30 @@
 import com.android.wallpaper.R
 import com.android.wallpaper.dispatchers.MainDispatcher
 import com.android.wallpaper.model.LiveWallpaperInfo
-import com.android.wallpaper.module.CustomizationSections
-import com.android.wallpaper.picker.preview.ui.viewmodel.PreviewTransitionViewModel
+import com.android.wallpaper.picker.preview.ui.viewmodel.SmallPreviewConfigViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.PreviewUtils
 import kotlinx.coroutines.CoroutineScope
 
 object SmallPreviewBinder {
-
     fun bind(
         applicationContext: Context,
         view: View,
         viewModel: WallpaperPreviewViewModel,
+        smallPreviewConfig: SmallPreviewConfigViewModel,
         @MainDispatcher mainScope: CoroutineScope,
         viewLifecycleOwner: LifecycleOwner,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
-        isRtl: Boolean,
-        previewDisplaySize: Point,
         previewUtils: PreviewUtils,
         previewDisplayId: Int? = null,
         navigate: (() -> Unit)? = null,
     ) {
         view.setOnClickListener {
-            // TODO(b/291761856): update preview transition view model from
-            //                    [SmallPreviewFragment].
-            viewModel.previewTransitionViewModel =
-                PreviewTransitionViewModel(
-                    previewTab = CustomizationSections.Screen.HOME_SCREEN,
-                    targetDisplaySize = previewDisplaySize,
-                )
+            viewModel.selectedSmallPreviewConfig = smallPreviewConfig
             navigate?.invoke()
         }
 
         WorkspacePreviewBinder.bind(
-            view.requireViewById<SurfaceView>(R.id.workspace_surface),
+            view.requireViewById(R.id.workspace_surface),
             previewUtils,
             previewDisplayId,
         )
@@ -67,10 +56,9 @@
             applicationContext,
             wallpaperSurface,
             viewModel,
+            smallPreviewConfig,
             viewLifecycleOwner,
             mainScope,
-            isSingleDisplayOrUnfoldedHorizontalHinge,
-            isRtl,
             staticPreviewView =
                 if (checkNotNull(viewModel.editingWallpaper) is LiveWallpaperInfo) {
                     null
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt
index dfc7a2e..5eb9dbd 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/SmallWallpaperPreviewBinder.kt
@@ -23,6 +23,7 @@
 import androidx.lifecycle.LifecycleOwner
 import com.android.wallpaper.R
 import com.android.wallpaper.dispatchers.MainDispatcher
+import com.android.wallpaper.picker.preview.ui.viewmodel.SmallPreviewConfigViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import kotlinx.coroutines.CoroutineScope
 
@@ -32,10 +33,9 @@
         applicationContext: Context,
         wallpaperSurface: SurfaceView,
         viewModel: WallpaperPreviewViewModel,
+        smallPreviewConfig: SmallPreviewConfigViewModel,
         viewLifecycleOwner: LifecycleOwner,
         @MainDispatcher mainScope: CoroutineScope,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
-        isRtl: Boolean,
         staticPreviewView: View? = null,
     ) {
         wallpaperSurface.setZOrderMediaOverlay(true)
@@ -62,11 +62,10 @@
                     }
                     WallpaperPreviewBinder.bind(
                         applicationContext,
-                        isSingleDisplayOrUnfoldedHorizontalHinge,
-                        isRtl,
                         mainScope,
                         viewLifecycleOwner,
                         viewModel,
+                        smallPreviewConfig,
                         wallpaperSurface,
                         staticPreviewView?.requireViewById(R.id.full_res_image),
                         staticPreviewView?.requireViewById(R.id.low_res_image),
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/StaticWallpaperPreviewBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/StaticWallpaperPreviewBinder.kt
index 973cdd1..b7c4b75 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/StaticWallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/StaticWallpaperPreviewBinder.kt
@@ -17,6 +17,7 @@
 
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
+import android.graphics.Point
 import android.graphics.RenderEffect
 import android.graphics.Shader
 import android.view.View
@@ -27,8 +28,10 @@
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
+import com.android.wallpaper.model.wallpaper.ScreenOrientation
 import com.android.wallpaper.picker.preview.ui.util.FullResImageViewUtil
 import com.android.wallpaper.picker.preview.ui.viewmodel.FullResWallpaperViewModel
+import com.android.wallpaper.picker.preview.ui.viewmodel.SmallPreviewConfigViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.StaticWallpaperPreviewViewModel
 import com.android.wallpaper.util.WallpaperSurfaceCallback.LOW_RES_BITMAP_BLUR_RADIUS
 import com.davemorrissey.labs.subscaleview.ImageSource
@@ -44,9 +47,8 @@
         fullResImageView: SubsamplingScaleImageView,
         lowResImageView: ImageView,
         viewModel: StaticWallpaperPreviewViewModel,
+        smallPreviewConfig: SmallPreviewConfigViewModel,
         viewLifecycleOwner: LifecycleOwner,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
-        isRtl: Boolean,
     ) {
         lowResImageView.initLowResImageView()
         fullResImageView.initFullResImageView()
@@ -57,11 +59,7 @@
 
                 launch {
                     viewModel.subsamplingScaleImageViewModel.collect {
-                        fullResImageView.setFullResImage(
-                            it,
-                            isSingleDisplayOrUnfoldedHorizontalHinge,
-                            isRtl,
-                        )
+                        fullResImageView.setFullResImage(it, smallPreviewConfig.screenOrientation)
                         crossFadeInFullResImageView(lowResImageView, fullResImageView)
                     }
                 }
@@ -86,19 +84,15 @@
 
     private fun SubsamplingScaleImageView.setFullResImage(
         viewModel: FullResWallpaperViewModel,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
-        isRtl: Boolean,
+        orientation: ScreenOrientation
     ) {
         // Calculate the scale and the center point for the full res image
         FullResImageViewUtil.getScaleAndCenter(
-                measuredWidth,
-                measuredHeight,
-                viewModel.offsetToStart,
+                Point(measuredWidth, measuredHeight),
                 viewModel.rawWallpaperSize,
-                isSingleDisplayOrUnfoldedHorizontalHinge,
-                isRtl,
+                viewModel.cropHints?.get(orientation),
             )
-            .also { scaleAndCenter ->
+            .let { scaleAndCenter ->
                 minScale = scaleAndCenter.minScale
                 maxScale = scaleAndCenter.maxScale
                 setScaleAndCenter(scaleAndCenter.defaultScale, scaleAndCenter.center)
diff --git a/src/com/android/wallpaper/picker/preview/ui/binder/WallpaperPreviewBinder.kt b/src/com/android/wallpaper/picker/preview/ui/binder/WallpaperPreviewBinder.kt
index 8638d25..aedee0f 100644
--- a/src/com/android/wallpaper/picker/preview/ui/binder/WallpaperPreviewBinder.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/binder/WallpaperPreviewBinder.kt
@@ -22,6 +22,7 @@
 import androidx.lifecycle.lifecycleScope
 import com.android.wallpaper.dispatchers.MainDispatcher
 import com.android.wallpaper.module.WallpaperPersister
+import com.android.wallpaper.picker.preview.ui.viewmodel.SmallPreviewConfigViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.wallpaperconnection.WallpaperConnectionUtils
 import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
@@ -32,11 +33,10 @@
 object WallpaperPreviewBinder {
     fun bind(
         applicationContext: Context,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
-        isRtl: Boolean,
         @MainDispatcher mainScope: CoroutineScope,
         viewLifecycleOwner: LifecycleOwner,
         viewModel: WallpaperPreviewViewModel,
+        smallPreviewConfig: SmallPreviewConfigViewModel,
         wallpaperSurface: SurfaceView,
         fullResImageView: SubsamplingScaleImageView? = null,
         lowResImageView: ImageView? = null,
@@ -47,9 +47,8 @@
                 fullResImageView,
                 checkNotNull(lowResImageView),
                 viewModel.getStaticWallpaperPreviewViewModel(),
+                smallPreviewConfig,
                 viewLifecycleOwner,
-                isSingleDisplayOrUnfoldedHorizontalHinge,
-                isRtl,
             )
         }
         // Bind live wallpaper
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt
index 464e32e..ed9ce0c 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/FullPreviewFragment.kt
@@ -31,7 +31,6 @@
 import com.android.wallpaper.picker.preview.ui.viewmodel.FullPreviewSurfaceViewModel
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.DisplayUtils
-import com.android.wallpaper.util.RtlUtils
 import dagger.hilt.android.AndroidEntryPoint
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -54,29 +53,32 @@
 
         setUpToolbar(view)
 
-        val appContext = requireContext().applicationContext
-        FullWallpaperPreviewBinder.bind(
-            appContext,
-            view.requireViewById(R.id.wallpaper_surface),
-            view.requireViewById(R.id.touch_forwarding_layout),
-            FullPreviewSurfaceViewModel(
-                previewTransitionViewModel =
-                    checkNotNull(wallpaperPreviewViewModel.previewTransitionViewModel),
-                currentDisplaySize = displayUtils.getRealSize(checkNotNull(view.context.display))
-            ),
-            wallpaperPreviewViewModel,
-            viewLifecycleOwner,
-            mainScope,
-            displayUtils.isSingleDisplayOrUnfoldedHorizontalHinge(requireActivity()),
-            RtlUtils.isRtl(requireContext().applicationContext),
-            staticPreviewView =
-                if (checkNotNull(wallpaperPreviewViewModel.editingWallpaper) is LiveWallpaperInfo) {
-                    null
-                } else {
-                    LayoutInflater.from(appContext)
-                        .inflate(R.layout.fullscreen_wallpaper_preview, null)
-                },
-        )
+        wallpaperPreviewViewModel.selectedSmallPreviewConfig?.let {
+            val appContext = requireContext().applicationContext
+            FullWallpaperPreviewBinder.bind(
+                appContext,
+                view.requireViewById(R.id.wallpaper_surface),
+                view.requireViewById(R.id.touch_forwarding_layout),
+                FullPreviewSurfaceViewModel(
+                    selectedSmallPreviewConfig = it,
+                    currentDisplaySize =
+                        displayUtils.getRealSize(checkNotNull(view.context.display))
+                ),
+                wallpaperPreviewViewModel,
+                viewLifecycleOwner,
+                mainScope,
+                staticPreviewView =
+                    if (
+                        checkNotNull(wallpaperPreviewViewModel.editingWallpaper)
+                            is LiveWallpaperInfo
+                    ) {
+                        null
+                    } else {
+                        LayoutInflater.from(appContext)
+                            .inflate(R.layout.fullscreen_wallpaper_preview, null)
+                    },
+            )
+        }
 
         CropWallpaperButtonBinder.bind(
             view.requireViewById(R.id.crop_wallpaper_button),
diff --git a/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt b/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt
index 643b87e..7838c15 100644
--- a/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/fragment/SmallPreviewFragment.kt
@@ -34,7 +34,6 @@
 import com.android.wallpaper.picker.preview.ui.viewmodel.WallpaperPreviewViewModel
 import com.android.wallpaper.util.DisplayUtils
 import com.android.wallpaper.util.PreviewUtils
-import com.android.wallpaper.util.RtlUtils
 import dagger.hilt.android.AndroidEntryPoint
 import dagger.hilt.android.qualifiers.ApplicationContext
 import javax.inject.Inject
@@ -85,11 +84,6 @@
     }
 
     private fun bindScreenPreview(view: View) {
-        val activity = activity ?: return
-        val isSingleDisplayOrUnfoldedHorizontalHinge =
-            displayUtils.isSingleDisplayOrUnfoldedHorizontalHinge(activity)
-        val isRtl = RtlUtils.isRtl(appContext)
-
         if (displayUtils.hasMultiInternalDisplays()) {
             val dualPreviewView: DualPreviewViewPager =
                 view.requireViewById(R.id.dual_preview_pager)
@@ -102,9 +96,7 @@
                 homePreviewUtils,
                 lockPreviewUtils,
                 appContext,
-                isSingleDisplayOrUnfoldedHorizontalHinge,
                 viewLifecycleOwner,
-                isRtl,
                 mainScope,
                 displayUtils,
             ) {
@@ -119,9 +111,7 @@
                 // TODO: pass correct view models for the view pager
                 wallpaperPreviewViewModel,
                 appContext,
-                isSingleDisplayOrUnfoldedHorizontalHinge,
                 viewLifecycleOwner,
-                isRtl,
                 mainScope,
                 homePreviewUtils,
                 lockPreviewUtils,
diff --git a/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtil.kt b/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtil.kt
index 7d352aa..06f02d3 100644
--- a/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtil.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtil.kt
@@ -17,42 +17,33 @@
 
 import android.graphics.Point
 import android.graphics.PointF
+import android.graphics.Rect
 import com.android.wallpaper.util.WallpaperCropUtils
 
 object FullResImageViewUtil {
 
     private const val DEFAULT_WALLPAPER_MAX_ZOOM = 8f
+
     fun getScaleAndCenter(
-        viewWidth: Int,
-        viewHeight: Int,
-        offsetToStart: Boolean,
+        viewSize: Point,
         rawWallpaperSize: Point,
-        isSingleDisplayOrUnfoldedHorizontalHinge: Boolean,
-        isRtl: Boolean,
+        cropRect: Rect?,
     ): ScaleAndCenter {
         // Determine minimum zoom to fit maximum visible area of wallpaper on crop surface.
-        val crop = Point(viewWidth, viewHeight)
         val visibleRawWallpaperRect =
-            WallpaperCropUtils.calculateVisibleRect(rawWallpaperSize, crop)
-        if (offsetToStart && isSingleDisplayOrUnfoldedHorizontalHinge) {
-            if (isRtl) {
-                visibleRawWallpaperRect.offsetTo(
-                    rawWallpaperSize.x - visibleRawWallpaperRect.width(),
-                    visibleRawWallpaperRect.top,
-                )
-            } else {
-                visibleRawWallpaperRect.offsetTo(/* newLeft= */ 0, visibleRawWallpaperRect.top)
-            }
-        }
+            cropRect ?: WallpaperCropUtils.calculateVisibleRect(rawWallpaperSize, viewSize)
         val centerPosition =
             PointF(
                 visibleRawWallpaperRect.centerX().toFloat(),
                 visibleRawWallpaperRect.centerY().toFloat()
             )
-        val visibleRawWallpaperSize =
-            Point(visibleRawWallpaperRect.width(), visibleRawWallpaperRect.height())
         val defaultWallpaperZoom =
-            WallpaperCropUtils.calculateMinZoom(visibleRawWallpaperSize, crop)
+            if (cropRect != null) 1f
+            else
+                WallpaperCropUtils.calculateMinZoom(
+                    Point(visibleRawWallpaperRect.width(), visibleRawWallpaperRect.height()),
+                    viewSize
+                )
 
         return ScaleAndCenter(
             defaultWallpaperZoom,
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullPreviewSurfaceViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullPreviewSurfaceViewModel.kt
index 6d3678e..9aeed85 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullPreviewSurfaceViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullPreviewSurfaceViewModel.kt
@@ -21,8 +21,8 @@
 /** View model for rendering [FullPreviewSurfaceView]. */
 data class FullPreviewSurfaceViewModel(
 
-    /** Data of user's selection on [SmallPreviewFragment]. */
-    val previewTransitionViewModel: PreviewTransitionViewModel,
+    /** Configuration of a user selected small preview on [SmallPreviewFragment]. */
+    val selectedSmallPreviewConfig: SmallPreviewConfigViewModel,
 
     /** Size of the current display rendering the view on screen. */
     val currentDisplaySize: Point,
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullResWallpaperViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullResWallpaperViewModel.kt
index 68fa697..1a921f0 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullResWallpaperViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/FullResWallpaperViewModel.kt
@@ -17,9 +17,11 @@
 
 import android.graphics.Bitmap
 import android.graphics.Point
+import android.graphics.Rect
+import com.android.wallpaper.model.wallpaper.ScreenOrientation
 
 data class FullResWallpaperViewModel(
     val rawWallpaperBitmap: Bitmap,
     val rawWallpaperSize: Point,
-    val offsetToStart: Boolean,
+    val cropHints: Map<ScreenOrientation, Rect>?,
 )
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewTransitionViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/SmallPreviewConfigViewModel.kt
similarity index 66%
rename from src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewTransitionViewModel.kt
rename to src/com/android/wallpaper/picker/preview/ui/viewmodel/SmallPreviewConfigViewModel.kt
index 5d87314..4b657a2 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/PreviewTransitionViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/SmallPreviewConfigViewModel.kt
@@ -16,14 +16,18 @@
 package com.android.wallpaper.picker.preview.ui.viewmodel
 
 import android.graphics.Point
+import com.android.wallpaper.model.wallpaper.ScreenOrientation
 import com.android.wallpaper.module.CustomizationSections.Screen
 
-/** Defines transitional data on [SmallPreviewFragment] when navigating to [FullPreviewFragment]. */
-data class PreviewTransitionViewModel(
+/** Defines configuration associated with a single small preview. */
+data class SmallPreviewConfigViewModel(
 
-    /** [Screen] selected via preview tab to be rendered on next screen. */
+    /** The [Screen] the preview is rendering. */
     val previewTab: Screen,
 
-    /** The display size the full preview is targeting on next screen. */
-    val targetDisplaySize: Point,
+    /** The display size the preview is based on. */
+    val displaySize: Point,
+
+    /** The [ScreenOrientation] the preview is based on. */
+    val screenOrientation: ScreenOrientation,
 )
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt
index b5e569d..b8e6ce1 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/StaticWallpaperPreviewViewModel.kt
@@ -21,10 +21,12 @@
 import android.graphics.BitmapFactory
 import android.graphics.ColorSpace
 import android.graphics.Point
+import android.graphics.Rect
 import com.android.wallpaper.asset.Asset
-import com.android.wallpaper.asset.CurrentWallpaperAsset
 import com.android.wallpaper.dispatchers.BackgroundDispatcher
 import com.android.wallpaper.model.WallpaperInfo
+import com.android.wallpaper.model.wallpaper.ScreenOrientation
+import com.android.wallpaper.model.wallpaper.WallpaperModel.StaticWallpaperModel
 import com.android.wallpaper.module.WallpaperPreferences
 import com.android.wallpaper.picker.preview.ui.WallpaperPreviewActivity
 import dagger.hilt.android.scopes.ViewModelScoped
@@ -55,6 +57,7 @@
     private val _lowResBitmap: MutableStateFlow<Bitmap?> = MutableStateFlow(null)
     val lowResBitmap: Flow<Bitmap> = _lowResBitmap.filterNotNull()
 
+    private val _cropHints: MutableStateFlow<Map<ScreenOrientation, Rect>?> = MutableStateFlow(null)
     private val _cachedWallpaperColors: MutableStateFlow<WallpaperColors?> = MutableStateFlow(null)
     private val croppedBitmap: MutableStateFlow<Bitmap?> = MutableStateFlow(null)
     val wallpaperColors: Flow<WallpaperColors> =
@@ -70,13 +73,13 @@
     // Wallpaper ID is required to cache the wallpaper colors to the preferences
     private var wallpaperId: String? = null
     private val wallpaperAsset: MutableStateFlow<Asset?> = MutableStateFlow(null)
+
     val subsamplingScaleImageViewModel: Flow<FullResWallpaperViewModel> =
         wallpaperAsset
             .filterNotNull()
             .map {
                 val dimensions = it.decodeRawDimensions()
-                val bitmap = it.decodeBitmap(dimensions)
-                if (bitmap != null) {
+                it.decodeBitmap(dimensions)?.let { bitmap ->
                     if (_cachedWallpaperColors.value == null && wallpaperId != null) {
                         // If no cached colors from the preferences, extra colors from the original
                         // bitmap and cache them to the preferences.
@@ -87,10 +90,8 @@
                     FullResWallpaperViewModel(
                         bitmap,
                         dimensions,
-                        offsetToStart = it is CurrentWallpaperAsset,
+                        _cropHints.value,
                     )
-                } else {
-                    null
                 }
             }
             .filterNotNull()
@@ -100,9 +101,14 @@
      * Init function for setting the wallpaper info that is retrieved from the intent bundle when
      * onCreate() in Activity or Fragment.
      */
-    suspend fun initializeViewModel(context: Context, wallpaper: WallpaperInfo) {
+    suspend fun initializeViewModel(
+        context: Context,
+        wallpaper: WallpaperInfo,
+        staticModel: StaticWallpaperModel
+    ) {
         val appContext = context.applicationContext
         if (!initialized) {
+            _cropHints.value = staticModel.staticWallpaperData.cropHints
             val asset: Asset? = wallpaper.getAsset(appContext)
             val id: String? = wallpaper.getStoredWallpaperId(appContext)
             wallpaperAsset.value = asset
diff --git a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewViewModel.kt b/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewViewModel.kt
index 45d097d..5d45343 100644
--- a/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewViewModel.kt
+++ b/src/com/android/wallpaper/picker/preview/ui/viewmodel/WallpaperPreviewViewModel.kt
@@ -20,6 +20,8 @@
 import androidx.lifecycle.viewModelScope
 import com.android.wallpaper.model.WallpaperInfo
 import com.android.wallpaper.model.wallpaper.WallpaperModel
+import com.android.wallpaper.model.wallpaper.WallpaperModel.LiveWallpaperModel
+import com.android.wallpaper.model.wallpaper.WallpaperModel.StaticWallpaperModel
 import com.android.wallpaper.picker.preview.ui.WallpaperPreviewActivity
 import dagger.hilt.android.lifecycle.HiltViewModel
 import javax.inject.Inject
@@ -42,8 +44,8 @@
     /** User selected [WallpaperModel] for editing. */
     var editingWallpaperModel: WallpaperModel? = null
 
-    /** Data used during transition from small to full preview, based on duo preview view pager. */
-    var previewTransitionViewModel: PreviewTransitionViewModel? = null
+    /** User selected small preview configuration. */
+    var selectedSmallPreviewConfig: SmallPreviewConfigViewModel? = null
 
     /** Gets the view model for static wallpaper preview views. */
     fun getStaticWallpaperPreviewViewModel(): StaticWallpaperPreviewViewModel =
@@ -53,8 +55,12 @@
     fun initializeViewModel(context: Context, wallpaper: WallpaperInfo, model: WallpaperModel) {
         editingWallpaper = wallpaper
         editingWallpaperModel = model
-        viewModelScope.launch {
-            staticWallpaperPreviewViewModel.initializeViewModel(context, wallpaper)
+        when (model) {
+            is StaticWallpaperModel ->
+                viewModelScope.launch {
+                    staticWallpaperPreviewViewModel.initializeViewModel(context, wallpaper, model)
+                }
+            is LiveWallpaperModel -> {}
         }
     }
 }
diff --git a/tests/robotests/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtilTest.kt b/tests/robotests/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtilTest.kt
index 0511f99..c6cf8d8 100644
--- a/tests/robotests/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtilTest.kt
+++ b/tests/robotests/src/com/android/wallpaper/picker/preview/ui/util/FullResImageViewUtilTest.kt
@@ -19,12 +19,9 @@
         val wallpaperSize = Point(1080, 1920)
         assertThat(
                 FullResImageViewUtil.getScaleAndCenter(
-                    screenWidth,
-                    screenHeight,
-                    false,
+                    Point(screenWidth, screenHeight),
                     wallpaperSize,
-                    isSingleDisplayOrUnfoldedHorizontalHinge = false,
-                    isRtl = false,
+                    cropRect = null,
                 )
             )
             .isEqualTo(
@@ -44,12 +41,9 @@
         val wallpaperSize = Point(3840, 3840)
         assertThat(
                 FullResImageViewUtil.getScaleAndCenter(
-                    screenWidth,
-                    screenHeight,
-                    false,
+                    Point(screenWidth, screenHeight),
                     wallpaperSize,
-                    isSingleDisplayOrUnfoldedHorizontalHinge = false,
-                    isRtl = false,
+                    cropRect = null,
                 )
             )
             .isEqualTo(
@@ -69,12 +63,9 @@
         val wallpaperSize = Point(960, 960)
         assertThat(
                 FullResImageViewUtil.getScaleAndCenter(
-                    screenWidth,
-                    screenHeight,
-                    false,
+                    Point(screenWidth, screenHeight),
                     wallpaperSize,
-                    isSingleDisplayOrUnfoldedHorizontalHinge = false,
-                    isRtl = false,
+                    cropRect = null,
                 )
             )
             .isEqualTo(