blob: 4dfadea08f4c497196e5a67f084ecd5b6293e196 [file] [log] [blame]
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.wallpaper.picker;
17
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070018import static android.view.View.MeasureSpec.EXACTLY;
19import static android.view.View.MeasureSpec.makeMeasureSpec;
20
21import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY;
22import static com.android.wallpaper.widget.BottomActionBar.BottomAction.EDIT;
23import static com.android.wallpaper.widget.BottomActionBar.BottomAction.INFORMATION;
24
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070025import android.animation.Animator;
26import android.animation.AnimatorListenerAdapter;
27import android.app.Activity;
28import android.content.Context;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070029import android.graphics.Bitmap;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070030import android.graphics.Color;
31import android.graphics.Point;
32import android.graphics.PointF;
33import android.graphics.Rect;
34import android.os.Bundle;
Tracy Zhouc5a6bad2020-05-20 23:28:22 -070035import android.os.Handler;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070036import android.view.LayoutInflater;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070037import android.view.Surface;
38import android.view.SurfaceControlViewHost;
39import android.view.SurfaceHolder;
40import android.view.SurfaceView;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070041import android.view.View;
42import android.view.ViewGroup;
43import android.widget.ImageView;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070044
Chuck Liaofc1b8c92020-05-21 20:54:15 +080045import androidx.annotation.NonNull;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070046import androidx.annotation.Nullable;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070047import androidx.cardview.widget.CardView;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070048import androidx.constraintlayout.widget.ConstraintLayout;
49import androidx.constraintlayout.widget.ConstraintSet;
50import androidx.core.content.ContextCompat;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070051import androidx.fragment.app.FragmentActivity;
52
53import com.android.wallpaper.R;
54import com.android.wallpaper.asset.Asset;
“Chuckffd832c2020-03-22 02:15:58 +080055import com.android.wallpaper.model.WallpaperInfo;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070056import com.android.wallpaper.module.WallpaperPersister.Destination;
57import com.android.wallpaper.module.WallpaperPersister.SetWallpaperCallback;
58import com.android.wallpaper.util.ScreenSizeCalculator;
Santiago Etchebehere53c63432020-05-07 18:55:35 -070059import com.android.wallpaper.util.SizeCalculator;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070060import com.android.wallpaper.util.WallpaperCropUtils;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070061import com.android.wallpaper.widget.BottomActionBar;
Chuck Liaofc1b8c92020-05-21 20:54:15 +080062import com.android.wallpaper.widget.LockScreenOverlayUpdater;
63import com.android.wallpaper.widget.WallpaperColorsLoader;
Tracy Zhou35997422020-05-01 13:42:06 -070064import com.android.wallpaper.widget.WallpaperInfoView;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070065
66import com.bumptech.glide.Glide;
67import com.bumptech.glide.MemoryCategory;
68import com.davemorrissey.labs.subscaleview.ImageSource;
69import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070070
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070071/**
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -080072 * Fragment which displays the UI for previewing an individual static wallpaper and its attribution
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070073 * information.
74 */
75public class ImagePreviewFragment extends PreviewFragment {
76
77 private static final float DEFAULT_WALLPAPER_MAX_ZOOM = 8f;
78
Tracy Zhouc5a6bad2020-05-20 23:28:22 -070079 private final Handler mHandler = new Handler();
Tracy Zhou4421a3d2020-06-15 14:56:18 -070080 private final WallpaperSurfaceCallback mWallpaperSurfaceCallback =
81 new WallpaperSurfaceCallback();
Tracy Zhouc5a6bad2020-05-20 23:28:22 -070082
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070083 private SubsamplingScaleImageView mFullResImageView;
84 private Asset mWallpaperAsset;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070085 private Point mDefaultCropSurfaceSize;
86 private Point mScreenSize;
87 private Point mRawWallpaperSize; // Native size of wallpaper image.
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070088 private ImageView mLowResImageView;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070089 private TouchForwardingLayout mTouchForwardingLayout;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070090 private ConstraintLayout mContainer;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070091 private SurfaceView mWorkspaceSurface;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070092 private WorkspaceSurfaceHolderCallback mWorkspaceSurfaceCallback;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070093 private SurfaceView mWallpaperSurface;
Chuck Liaofc1b8c92020-05-21 20:54:15 +080094 private View mLockOverlay;
95 private LockScreenOverlayUpdater mLockScreenOverlayUpdater;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070096 private View mTabs;
Tracy Zhou35997422020-05-01 13:42:06 -070097 private WallpaperInfoView mWallpaperInfoView;
Wesley.CW Wangf21486b2020-06-02 18:30:32 +080098 private View mLock;
99 private View mHome;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700100
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700101 @Override
102 public void onCreate(Bundle savedInstanceState) {
103 super.onCreate(savedInstanceState);
104 mWallpaperAsset = mWallpaper.getAsset(requireContext().getApplicationContext());
105 }
106
107 @Override
108 protected int getLayoutResId() {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700109 return R.layout.fragment_image_preview_v2;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700110 }
111
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700112 @Override
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800113 protected int getLoadingIndicatorResId() {
114 return R.id.loading_indicator;
115 }
116
117 @Override
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700118 public View onCreateView(LayoutInflater inflater, ViewGroup container,
Michel Comin Escudeb3e1fef2019-11-22 11:41:53 -0800119 Bundle savedInstanceState) {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700120 View view = super.onCreateView(inflater, container, savedInstanceState);
121
122 Activity activity = requireActivity();
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700123 mScreenSize = ScreenSizeCalculator.getInstance().getScreenSize(
124 activity.getWindowManager().getDefaultDisplay());
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700125
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700126 // TODO: Consider moving some part of this to the base class when live preview is ready.
127 view.findViewById(R.id.low_res_image).setVisibility(View.GONE);
128 view.findViewById(R.id.full_res_image).setVisibility(View.GONE);
129 mLoadingProgressBar.hide();
130 mContainer = view.findViewById(R.id.container);
131 mTouchForwardingLayout = mContainer.findViewById(R.id.touch_forwarding_layout);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700132
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700133 // Set aspect ratio on the preview card dynamically.
134 ConstraintSet set = new ConstraintSet();
135 set.clone(mContainer);
136 String ratio = String.format("%d:%d", mScreenSize.x, mScreenSize.y);
137 set.setDimensionRatio(mTouchForwardingLayout.getId(), ratio);
138 set.applyTo(mContainer);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700139
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700140 mWorkspaceSurface = mContainer.findViewById(R.id.workspace_surface);
141 mWorkspaceSurfaceCallback = new WorkspaceSurfaceHolderCallback(mWorkspaceSurface,
142 getContext());
143 mWallpaperSurface = mContainer.findViewById(R.id.wallpaper_surface);
144 mLockOverlay = mContainer.findViewById(R.id.lock_overlay);
145 mLockScreenOverlayUpdater = new LockScreenOverlayUpdater(
146 getContext(), mLockOverlay, getLifecycle());
147 mLockScreenOverlayUpdater.adjustOverlayLayout(true);
Chuck Liaofc1b8c92020-05-21 20:54:15 +0800148
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700149 mTabs = view.findViewById(R.id.tabs_container);
Wesley.CW Wangf21486b2020-06-02 18:30:32 +0800150 mLock = mTabs.findViewById(R.id.lock);
151 mHome = mTabs.findViewById(R.id.home);
152 mLock.setOnClickListener(v -> updateScreenPreview(/* isHomeSelected= */ false));
153 mHome.setOnClickListener(v -> updateScreenPreview(/* isHomeSelected= */ true));
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700154
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700155 onBottomActionBarReady(mBottomActionBar);
156 view.measure(makeMeasureSpec(mScreenSize.x, EXACTLY),
157 makeMeasureSpec(mScreenSize.y, EXACTLY));
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700158
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700159 ((CardView) mWorkspaceSurface.getParent())
160 .setRadius(SizeCalculator.getPreviewCornerRadius(
161 activity, mContainer.getMeasuredWidth()));
162 renderImageWallpaper();
163 renderWorkspaceSurface();
Ching-Sung Liba4f1fe2020-06-10 15:59:15 +0800164 updateScreenPreview(/* isHomeSelected= */ mViewAsHome);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700165
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700166 // Trim some memory from Glide to make room for the full-size image in this fragment.
167 Glide.get(activity).setMemoryCategory(MemoryCategory.LOW);
168
169 mDefaultCropSurfaceSize = WallpaperCropUtils.getDefaultCropSurfaceSize(
170 getResources(), activity.getWindowManager().getDefaultDisplay());
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700171
172 // Load a low-res placeholder image if there's a thumbnail available from the asset that can
173 // be shown to the user more quickly than the full-sized image.
174 if (mWallpaperAsset.hasLowResDataSource()) {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700175 mHandler.post(() ->
176 mWallpaperAsset.loadLowResDrawable(activity, mLowResImageView, Color.BLACK,
177 new WallpaperPreviewBitmapTransformation(
178 activity.getApplicationContext(), isRtl())));
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700179 }
180
181 mWallpaperAsset.decodeRawDimensions(getActivity(), dimensions -> {
182 // Don't continue loading the wallpaper if the Fragment is detached.
183 if (getActivity() == null) {
184 return;
185 }
186
187 // Return early and show a dialog if dimensions are null (signaling a decoding error).
188 if (dimensions == null) {
189 showLoadWallpaperErrorDialog();
190 return;
191 }
192
193 mRawWallpaperSize = dimensions;
chihhangchuangc687d912020-05-04 14:33:05 +0800194
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700195 setUpExploreIntentAndLabel(ImagePreviewFragment.this::initFullResView);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700196 });
197
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800198 setUpLoadingIndicator();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700199
200 return view;
201 }
202
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -0800203 @Override
Chuck Liaofc1b8c92020-05-21 20:54:15 +0800204 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
205 super.onViewCreated(view, savedInstanceState);
chihhangchuang90f902c2020-06-03 16:14:40 +0800206 WallpaperColorsLoader.getWallpaperColors(getContext(),
207 mWallpaper.getThumbAsset(getContext()),
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700208 mLockScreenOverlayUpdater::setColor);
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -0800209 }
210
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800211 @Override
212 protected boolean isLoaded() {
213 return mFullResImageView != null && mFullResImageView.hasImage();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700214 }
215
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700216 @Override
217 public void onClickOk() {
218 FragmentActivity activity = getActivity();
219 if (activity != null) {
220 activity.finish();
221 }
222 }
223
224 @Override
225 public void onDestroy() {
226 super.onDestroy();
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800227 if (mLoadingProgressBar != null) {
228 mLoadingProgressBar.hide();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700229 }
230 mFullResImageView.recycle();
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700231
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700232 mWallpaperSurfaceCallback.cleanUp();
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700233 mWorkspaceSurfaceCallback.cleanUp();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700234 }
235
236 @Override
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700237 protected void onBottomActionBarReady(BottomActionBar bottomActionBar) {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700238 super.onBottomActionBarReady(bottomActionBar);
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700239
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700240 mWallpaperInfoView = (WallpaperInfoView)
241 LayoutInflater.from(getContext()).inflate(
242 R.layout.wallpaper_info_view, /* root= */null);
243 mBottomActionBar.attachViewToBottomSheetAndBindAction(mWallpaperInfoView, INFORMATION);
244 mBottomActionBar.showActionsOnly(INFORMATION, EDIT, APPLY);
245 mBottomActionBar.bindBackButtonToSystemBackKey(getActivity());
246 mBottomActionBar.setActionClickListener(EDIT, v ->
Tracy Zhou16112e32020-05-27 13:13:23 -0700247 setEditingEnabled(mBottomActionBar.isActionSelected(EDIT))
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700248 );
249 mBottomActionBar.setActionSelectedListener(EDIT,
250 selected -> {
251 if (!selected) {
252 setEditingEnabled(false);
253 }
254 });
255 mBottomActionBar.setActionClickListener(APPLY, v -> onSetWallpaperClicked(v));
256 mBottomActionBar.show();
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700257 }
258
259 @Override
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800260 protected CharSequence getExploreButtonLabel(Context context) {
261 return context.getString(mWallpaper.getActionLabelRes(context));
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700262 }
263
264 /**
265 * Initializes MosaicView by initializing tiling, setting a fallback page bitmap, and
266 * initializing a zoom-scroll observer and click listener.
267 */
268 private void initFullResView() {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700269 setEditingEnabled(false);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700270 mFullResImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
271
272 // Set a solid black "page bitmap" so MosaicView draws a black background while waiting
273 // for the image to load or a transparent one if a thumbnail already loaded.
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700274 Bitmap backgroundBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700275 int preColor = ContextCompat.getColor(getContext(), R.color.fullscreen_preview_background);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700276 int color = (mLowResImageView.getDrawable() == null) ? preColor : Color.TRANSPARENT;
277 backgroundBitmap.setPixel(0, 0, color);
278 mFullResImageView.setImage(ImageSource.bitmap(backgroundBitmap));
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700279
280 // Then set a fallback "page bitmap" to cover the whole MosaicView, which is an actual
281 // (lower res) version of the image to be displayed.
282 Point targetPageBitmapSize = new Point(mRawWallpaperSize);
283 mWallpaperAsset.decodeBitmap(targetPageBitmapSize.x, targetPageBitmapSize.y,
284 pageBitmap -> {
285 // Check that the activity is still around since the decoding task started.
286 if (getActivity() == null) {
287 return;
288 }
289
290 // Some of these may be null depending on if the Fragment is paused, stopped,
291 // or destroyed.
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800292 if (mLoadingProgressBar != null) {
293 mLoadingProgressBar.hide();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700294 }
295 // The page bitmap may be null if there was a decoding error, so show an
296 // error dialog.
297 if (pageBitmap == null) {
298 showLoadWallpaperErrorDialog();
299 return;
300 }
301 if (mFullResImageView != null) {
302 // Set page bitmap.
303 mFullResImageView.setImage(ImageSource.bitmap(pageBitmap));
304
305 setDefaultWallpaperZoomAndScroll();
306 crossFadeInMosaicView();
307 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700308 getActivity().invalidateOptionsMenu();
309
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700310 if (mWallpaperInfoView != null && mWallpaper != null) {
311 mWallpaperInfoView.populateWallpaperInfo(mWallpaper, mActionLabel,
312 mExploreIntent, this::onExploreClicked);
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700313 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700314 });
315 }
316
317 /**
318 * Makes the MosaicView visible with an alpha fade-in animation while fading out the loading
319 * indicator.
320 */
321 private void crossFadeInMosaicView() {
322 long shortAnimationDuration = getResources().getInteger(
323 android.R.integer.config_shortAnimTime);
324
325 mFullResImageView.setAlpha(0f);
326 mFullResImageView.animate()
327 .alpha(1f)
328 .setDuration(shortAnimationDuration)
329 .setListener(new AnimatorListenerAdapter() {
330 @Override
331 public void onAnimationEnd(Animator animation) {
332 // Clear the thumbnail bitmap reference to save memory since it's no longer
333 // visible.
334 if (mLowResImageView != null) {
335 mLowResImageView.setImageBitmap(null);
336 }
337 }
338 });
339
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800340 mLoadingProgressBar.animate()
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700341 .alpha(0f)
342 .setDuration(shortAnimationDuration)
343 .setListener(new AnimatorListenerAdapter() {
344 @Override
345 public void onAnimationEnd(Animator animation) {
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800346 if (mLoadingProgressBar != null) {
347 mLoadingProgressBar.hide();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700348 }
349 }
350 });
351 }
352
353 /**
Michel Comin Escudeb3e1fef2019-11-22 11:41:53 -0800354 * Sets the default wallpaper zoom and scroll position based on a "crop surface" (with extra
355 * width to account for parallax) superimposed on the screen. Shows as much of the wallpaper as
356 * possible on the crop surface and align screen to crop surface such that the default preview
357 * matches what would be seen by the user in the left-most home screen.
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700358 *
359 * <p>This method is called once in the Fragment lifecycle after the wallpaper asset has loaded
360 * and rendered to the layout.
361 */
362 private void setDefaultWallpaperZoomAndScroll() {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700363 // Determine minimum zoom to fit maximum visible area of wallpaper on crop surface.
364 int cropWidth = mWorkspaceSurface.getMeasuredWidth();
365 int cropHeight = mWorkspaceSurface.getMeasuredHeight();
366 Point crop = new Point(cropWidth, cropHeight);
367 Rect visibleRawWallpaperRect =
368 WallpaperCropUtils.calculateVisibleRect(mRawWallpaperSize, crop);
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700369
370 final PointF centerPosition = WallpaperCropUtils.calculateDefaultCenter(requireContext(),
371 mRawWallpaperSize, visibleRawWallpaperRect);
372
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700373 Point visibleRawWallpaperSize = new Point(visibleRawWallpaperRect.width(),
374 visibleRawWallpaperRect.height());
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700375
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700376 final float defaultWallpaperZoom = WallpaperCropUtils.calculateMinZoom(
377 visibleRawWallpaperSize, crop);
378 final float minWallpaperZoom = defaultWallpaperZoom;
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700379
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700380
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700381 // Set min wallpaper zoom and max zoom on MosaicView widget.
382 mFullResImageView.setMaxScale(Math.max(DEFAULT_WALLPAPER_MAX_ZOOM, defaultWallpaperZoom));
383 mFullResImageView.setMinScale(minWallpaperZoom);
384
385 // Set center to composite positioning between scaled wallpaper and screen.
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700386 mFullResImageView.setScaleAndCenter(minWallpaperZoom, centerPosition);
387 }
388
389 private Rect calculateCropRect() {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700390 float wallpaperZoom = mFullResImageView.getScale();
Chuck Liao5182a312020-03-04 20:04:18 +0800391 Context context = requireContext().getApplicationContext();
Tracy Zhou67fd7e32020-05-01 18:35:36 -0700392
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700393 Rect visibleFileRect = new Rect();
394 mFullResImageView.visibleFileRect(visibleFileRect);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700395
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700396 int cropWidth = mWorkspaceSurface.getMeasuredWidth();
397 int cropHeight = mWorkspaceSurface.getMeasuredHeight();
398 Point hostViewSize = new Point(cropWidth, cropHeight);
399 Rect cropRect = WallpaperCropUtils.calculateCropRect(context, hostViewSize,
400 hostViewSize, mRawWallpaperSize, visibleFileRect, wallpaperZoom);
401 WallpaperCropUtils.adjustCropRect(context, cropRect, false /* zoomIn */);
402 return cropRect;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700403 }
404
405 @Override
406 protected void setCurrentWallpaper(@Destination int destination) {
407 mWallpaperSetter.setCurrentWallpaper(getActivity(), mWallpaper, mWallpaperAsset,
408 destination, mFullResImageView.getScale(), calculateCropRect(),
409 new SetWallpaperCallback() {
410 @Override
“Chuckffd832c2020-03-22 02:15:58 +0800411 public void onSuccess(WallpaperInfo wallpaperInfo) {
Ching-Sung Lib5e9bd72020-06-15 14:10:55 +0800412 finishActivity(/* success= */ true);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700413 }
414
415 @Override
416 public void onError(@Nullable Throwable throwable) {
417 showSetWallpaperErrorDialog(destination);
418 }
419 });
420 }
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700421
422 private void renderWorkspaceSurface() {
423 mWorkspaceSurface.setZOrderMediaOverlay(true);
424 mWorkspaceSurface.getHolder().addCallback(mWorkspaceSurfaceCallback);
425 }
426
427 private void renderImageWallpaper() {
428 mWallpaperSurface.getHolder().addCallback(mWallpaperSurfaceCallback);
429 }
430
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700431 private class WallpaperSurfaceCallback implements SurfaceHolder.Callback {
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700432
433 private Surface mLastSurface;
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700434 private SurfaceControlViewHost mHost;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700435
436 @Override
437 public void surfaceCreated(SurfaceHolder holder) {
438 if (mLastSurface != holder.getSurface()) {
439 mLastSurface = holder.getSurface();
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700440 if (mFullResImageView != null) {
441 mFullResImageView.recycle();
442 }
443 View wallpaperPreviewContainer = LayoutInflater.from(getContext()).inflate(
444 R.layout.fullscreen_wallpaper_preview, null);
445 mFullResImageView = wallpaperPreviewContainer.findViewById(R.id.full_res_image);
446 mLowResImageView = wallpaperPreviewContainer.findViewById(R.id.low_res_image);
447 wallpaperPreviewContainer.measure(
448 makeMeasureSpec(mWallpaperSurface.getWidth(), EXACTLY),
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700449 makeMeasureSpec(mWallpaperSurface.getHeight(), EXACTLY));
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700450 wallpaperPreviewContainer.layout(0, 0, mWallpaperSurface.getWidth(),
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700451 mWallpaperSurface.getHeight());
Ching-Sung Lib9404622020-05-18 22:38:45 +0800452 mTouchForwardingLayout.setTargetView(mFullResImageView);
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700453
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700454 cleanUp();
455 mHost = new SurfaceControlViewHost(getContext(),
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700456 getContext().getDisplay(), mWallpaperSurface.getHostToken());
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700457 mHost.setView(wallpaperPreviewContainer, wallpaperPreviewContainer.getWidth(),
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700458 wallpaperPreviewContainer.getHeight());
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700459 mWallpaperSurface.setChildSurfacePackage(mHost.getSurfacePackage());
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700460 }
461 }
462
463 @Override
464 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
465
466 @Override
467 public void surfaceDestroyed(SurfaceHolder holder) { }
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700468
469 public void cleanUp() {
470 if (mHost != null) {
471 mHost.release();
472 mHost = null;
473 }
474 }
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700475 };
476
Tracy Zhou67fd7e32020-05-01 18:35:36 -0700477 private void setEditingEnabled(boolean enabled) {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700478 mTouchForwardingLayout.setForwardingEnabled(enabled);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700479 }
480
Wesley.CW Wangf21486b2020-06-02 18:30:32 +0800481 private void updateScreenPreview(boolean isHomeSelected) {
482 mHome.setSelected(isHomeSelected);
483 mLock.setSelected(!isHomeSelected);
484 mWorkspaceSurface.setVisibility(isHomeSelected ? View.VISIBLE : View.GONE);
485 mLockOverlay.setVisibility(isHomeSelected ? View.GONE : View.VISIBLE);
Tracy Zhou67fd7e32020-05-01 18:35:36 -0700486 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700487}