blob: 84bc95b0523070fd0a3b50d4ffa1a4b4952e8a35 [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;
Wesley.CW Wang61c28ec2020-06-19 18:58:50 +080062import com.android.wallpaper.widget.BottomActionBar.AccessibilityCallback;
Chuck Liaofc1b8c92020-05-21 20:54:15 +080063import com.android.wallpaper.widget.LockScreenOverlayUpdater;
64import com.android.wallpaper.widget.WallpaperColorsLoader;
Tracy Zhou35997422020-05-01 13:42:06 -070065import com.android.wallpaper.widget.WallpaperInfoView;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070066
67import com.bumptech.glide.Glide;
68import com.bumptech.glide.MemoryCategory;
69import com.davemorrissey.labs.subscaleview.ImageSource;
70import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070071
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070072/**
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -080073 * Fragment which displays the UI for previewing an individual static wallpaper and its attribution
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070074 * information.
75 */
76public class ImagePreviewFragment extends PreviewFragment {
77
78 private static final float DEFAULT_WALLPAPER_MAX_ZOOM = 8f;
79
Tracy Zhouc5a6bad2020-05-20 23:28:22 -070080 private final Handler mHandler = new Handler();
Tracy Zhou4421a3d2020-06-15 14:56:18 -070081 private final WallpaperSurfaceCallback mWallpaperSurfaceCallback =
82 new WallpaperSurfaceCallback();
Tracy Zhouc5a6bad2020-05-20 23:28:22 -070083
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070084 private SubsamplingScaleImageView mFullResImageView;
85 private Asset mWallpaperAsset;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070086 private Point mDefaultCropSurfaceSize;
87 private Point mScreenSize;
88 private Point mRawWallpaperSize; // Native size of wallpaper image.
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070089 private ImageView mLowResImageView;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070090 private TouchForwardingLayout mTouchForwardingLayout;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070091 private ConstraintLayout mContainer;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070092 private SurfaceView mWorkspaceSurface;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070093 private WorkspaceSurfaceHolderCallback mWorkspaceSurfaceCallback;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070094 private SurfaceView mWallpaperSurface;
Chuck Liaofc1b8c92020-05-21 20:54:15 +080095 private View mLockOverlay;
96 private LockScreenOverlayUpdater mLockScreenOverlayUpdater;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070097 private View mTabs;
Tracy Zhou35997422020-05-01 13:42:06 -070098 private WallpaperInfoView mWallpaperInfoView;
Wesley.CW Wangf21486b2020-06-02 18:30:32 +080099 private View mLock;
100 private View mHome;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700101
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700102 @Override
103 public void onCreate(Bundle savedInstanceState) {
104 super.onCreate(savedInstanceState);
105 mWallpaperAsset = mWallpaper.getAsset(requireContext().getApplicationContext());
106 }
107
108 @Override
109 protected int getLayoutResId() {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700110 return R.layout.fragment_image_preview_v2;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700111 }
112
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700113 @Override
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800114 protected int getLoadingIndicatorResId() {
115 return R.id.loading_indicator;
116 }
117
118 @Override
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700119 public View onCreateView(LayoutInflater inflater, ViewGroup container,
Michel Comin Escudeb3e1fef2019-11-22 11:41:53 -0800120 Bundle savedInstanceState) {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700121 View view = super.onCreateView(inflater, container, savedInstanceState);
122
123 Activity activity = requireActivity();
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700124 mScreenSize = ScreenSizeCalculator.getInstance().getScreenSize(
125 activity.getWindowManager().getDefaultDisplay());
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700126
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700127 // TODO: Consider moving some part of this to the base class when live preview is ready.
128 view.findViewById(R.id.low_res_image).setVisibility(View.GONE);
129 view.findViewById(R.id.full_res_image).setVisibility(View.GONE);
130 mLoadingProgressBar.hide();
131 mContainer = view.findViewById(R.id.container);
132 mTouchForwardingLayout = mContainer.findViewById(R.id.touch_forwarding_layout);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700133
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700134 // Set aspect ratio on the preview card dynamically.
135 ConstraintSet set = new ConstraintSet();
136 set.clone(mContainer);
137 String ratio = String.format("%d:%d", mScreenSize.x, mScreenSize.y);
138 set.setDimensionRatio(mTouchForwardingLayout.getId(), ratio);
139 set.applyTo(mContainer);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700140
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700141 mWorkspaceSurface = mContainer.findViewById(R.id.workspace_surface);
142 mWorkspaceSurfaceCallback = new WorkspaceSurfaceHolderCallback(mWorkspaceSurface,
143 getContext());
144 mWallpaperSurface = mContainer.findViewById(R.id.wallpaper_surface);
145 mLockOverlay = mContainer.findViewById(R.id.lock_overlay);
146 mLockScreenOverlayUpdater = new LockScreenOverlayUpdater(
147 getContext(), mLockOverlay, getLifecycle());
148 mLockScreenOverlayUpdater.adjustOverlayLayout(true);
Chuck Liaofc1b8c92020-05-21 20:54:15 +0800149
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700150 mTabs = view.findViewById(R.id.tabs_container);
Wesley.CW Wangf21486b2020-06-02 18:30:32 +0800151 mLock = mTabs.findViewById(R.id.lock);
152 mHome = mTabs.findViewById(R.id.home);
153 mLock.setOnClickListener(v -> updateScreenPreview(/* isHomeSelected= */ false));
154 mHome.setOnClickListener(v -> updateScreenPreview(/* isHomeSelected= */ true));
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700155
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700156 onBottomActionBarReady(mBottomActionBar);
157 view.measure(makeMeasureSpec(mScreenSize.x, EXACTLY),
158 makeMeasureSpec(mScreenSize.y, EXACTLY));
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700159
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700160 ((CardView) mWorkspaceSurface.getParent())
161 .setRadius(SizeCalculator.getPreviewCornerRadius(
162 activity, mContainer.getMeasuredWidth()));
163 renderImageWallpaper();
164 renderWorkspaceSurface();
Ching-Sung Liba4f1fe2020-06-10 15:59:15 +0800165 updateScreenPreview(/* isHomeSelected= */ mViewAsHome);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700166
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700167 // Trim some memory from Glide to make room for the full-size image in this fragment.
168 Glide.get(activity).setMemoryCategory(MemoryCategory.LOW);
169
170 mDefaultCropSurfaceSize = WallpaperCropUtils.getDefaultCropSurfaceSize(
171 getResources(), activity.getWindowManager().getDefaultDisplay());
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700172
Chuck Liao97598452020-06-18 23:46:07 +0800173 mBottomActionBar.disableActions();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700174 mWallpaperAsset.decodeRawDimensions(getActivity(), dimensions -> {
Chuck Liao97598452020-06-18 23:46:07 +0800175 if (mBottomActionBar != null) {
176 mBottomActionBar.enableActions();
177 }
178
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700179 // Don't continue loading the wallpaper if the Fragment is detached.
180 if (getActivity() == null) {
181 return;
182 }
183
184 // Return early and show a dialog if dimensions are null (signaling a decoding error).
185 if (dimensions == null) {
186 showLoadWallpaperErrorDialog();
187 return;
188 }
189
190 mRawWallpaperSize = dimensions;
chihhangchuangc687d912020-05-04 14:33:05 +0800191
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700192 setUpExploreIntentAndLabel(ImagePreviewFragment.this::initFullResView);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700193 });
194
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800195 setUpLoadingIndicator();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700196
197 return view;
198 }
199
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -0800200 @Override
Chuck Liaofc1b8c92020-05-21 20:54:15 +0800201 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
202 super.onViewCreated(view, savedInstanceState);
chihhangchuang90f902c2020-06-03 16:14:40 +0800203 WallpaperColorsLoader.getWallpaperColors(getContext(),
204 mWallpaper.getThumbAsset(getContext()),
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700205 mLockScreenOverlayUpdater::setColor);
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -0800206 }
207
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800208 @Override
209 protected boolean isLoaded() {
210 return mFullResImageView != null && mFullResImageView.hasImage();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700211 }
212
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700213 @Override
214 public void onClickOk() {
215 FragmentActivity activity = getActivity();
216 if (activity != null) {
217 activity.finish();
218 }
219 }
220
221 @Override
222 public void onDestroy() {
223 super.onDestroy();
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800224 if (mLoadingProgressBar != null) {
225 mLoadingProgressBar.hide();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700226 }
227 mFullResImageView.recycle();
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700228
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700229 mWallpaperSurfaceCallback.cleanUp();
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700230 mWorkspaceSurfaceCallback.cleanUp();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700231 }
232
233 @Override
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700234 protected void onBottomActionBarReady(BottomActionBar bottomActionBar) {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700235 super.onBottomActionBarReady(bottomActionBar);
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700236
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700237 mWallpaperInfoView = (WallpaperInfoView)
238 LayoutInflater.from(getContext()).inflate(
239 R.layout.wallpaper_info_view, /* root= */null);
240 mBottomActionBar.attachViewToBottomSheetAndBindAction(mWallpaperInfoView, INFORMATION);
241 mBottomActionBar.showActionsOnly(INFORMATION, EDIT, APPLY);
242 mBottomActionBar.bindBackButtonToSystemBackKey(getActivity());
243 mBottomActionBar.setActionClickListener(EDIT, v ->
Tracy Zhou16112e32020-05-27 13:13:23 -0700244 setEditingEnabled(mBottomActionBar.isActionSelected(EDIT))
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700245 );
Chihhang Chuangca7c8252020-06-17 17:32:46 +0800246 mBottomActionBar.setActionSelectedListener(EDIT, this::setEditingEnabled);
247 mBottomActionBar.setActionClickListener(APPLY, this::onSetWallpaperClicked);
Wesley.CW Wang61c28ec2020-06-19 18:58:50 +0800248
249 // Update target view's accessibility param since it will be blocked by the bottom sheet
250 // when expanded.
251 mBottomActionBar.setAccessibilityCallback(new AccessibilityCallback() {
252 @Override
253 public void onBottomSheetCollapsed() {
254 mTabs.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
255 }
256
257 @Override
258 public void onBottomSheetExpanded() {
259 mTabs.setImportantForAccessibility(
260 View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
261 }
262 });
263
Chihhang Chuangca7c8252020-06-17 17:32:46 +0800264 // Will trigger onActionSelected callback to update the editing state.
265 mBottomActionBar.setDefaultSelectedButton(EDIT);
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700266 mBottomActionBar.show();
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700267 }
268
269 @Override
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800270 protected CharSequence getExploreButtonLabel(Context context) {
271 return context.getString(mWallpaper.getActionLabelRes(context));
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700272 }
273
274 /**
275 * Initializes MosaicView by initializing tiling, setting a fallback page bitmap, and
276 * initializing a zoom-scroll observer and click listener.
277 */
278 private void initFullResView() {
Tracy Zhoudee07892020-06-16 20:14:30 -0700279 // Minimum scale will only be respected under this scale type.
280 mFullResImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM);
281 // When we set a minimum scale bigger than the scale with which the full image is shown,
282 // disallow user to pan outside the view we show the wallpaper in.
283 mFullResImageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700284
285 // Set a solid black "page bitmap" so MosaicView draws a black background while waiting
286 // for the image to load or a transparent one if a thumbnail already loaded.
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700287 Bitmap backgroundBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700288 int preColor = ContextCompat.getColor(getContext(), R.color.fullscreen_preview_background);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700289 int color = (mLowResImageView.getDrawable() == null) ? preColor : Color.TRANSPARENT;
290 backgroundBitmap.setPixel(0, 0, color);
291 mFullResImageView.setImage(ImageSource.bitmap(backgroundBitmap));
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700292
293 // Then set a fallback "page bitmap" to cover the whole MosaicView, which is an actual
294 // (lower res) version of the image to be displayed.
295 Point targetPageBitmapSize = new Point(mRawWallpaperSize);
296 mWallpaperAsset.decodeBitmap(targetPageBitmapSize.x, targetPageBitmapSize.y,
297 pageBitmap -> {
298 // Check that the activity is still around since the decoding task started.
299 if (getActivity() == null) {
300 return;
301 }
302
303 // Some of these may be null depending on if the Fragment is paused, stopped,
304 // or destroyed.
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800305 if (mLoadingProgressBar != null) {
306 mLoadingProgressBar.hide();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700307 }
308 // The page bitmap may be null if there was a decoding error, so show an
309 // error dialog.
310 if (pageBitmap == null) {
311 showLoadWallpaperErrorDialog();
312 return;
313 }
314 if (mFullResImageView != null) {
315 // Set page bitmap.
316 mFullResImageView.setImage(ImageSource.bitmap(pageBitmap));
317
318 setDefaultWallpaperZoomAndScroll();
319 crossFadeInMosaicView();
320 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700321 getActivity().invalidateOptionsMenu();
322
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700323 if (mWallpaperInfoView != null && mWallpaper != null) {
324 mWallpaperInfoView.populateWallpaperInfo(mWallpaper, mActionLabel,
325 mExploreIntent, this::onExploreClicked);
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700326 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700327 });
328 }
329
330 /**
331 * Makes the MosaicView visible with an alpha fade-in animation while fading out the loading
332 * indicator.
333 */
334 private void crossFadeInMosaicView() {
335 long shortAnimationDuration = getResources().getInteger(
336 android.R.integer.config_shortAnimTime);
337
338 mFullResImageView.setAlpha(0f);
339 mFullResImageView.animate()
340 .alpha(1f)
341 .setDuration(shortAnimationDuration)
342 .setListener(new AnimatorListenerAdapter() {
343 @Override
344 public void onAnimationEnd(Animator animation) {
345 // Clear the thumbnail bitmap reference to save memory since it's no longer
346 // visible.
347 if (mLowResImageView != null) {
348 mLowResImageView.setImageBitmap(null);
349 }
350 }
351 });
352
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800353 mLoadingProgressBar.animate()
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700354 .alpha(0f)
355 .setDuration(shortAnimationDuration)
356 .setListener(new AnimatorListenerAdapter() {
357 @Override
358 public void onAnimationEnd(Animator animation) {
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800359 if (mLoadingProgressBar != null) {
360 mLoadingProgressBar.hide();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700361 }
362 }
363 });
364 }
365
366 /**
Michel Comin Escudeb3e1fef2019-11-22 11:41:53 -0800367 * Sets the default wallpaper zoom and scroll position based on a "crop surface" (with extra
368 * width to account for parallax) superimposed on the screen. Shows as much of the wallpaper as
369 * possible on the crop surface and align screen to crop surface such that the default preview
370 * matches what would be seen by the user in the left-most home screen.
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700371 *
372 * <p>This method is called once in the Fragment lifecycle after the wallpaper asset has loaded
373 * and rendered to the layout.
374 */
375 private void setDefaultWallpaperZoomAndScroll() {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700376 // Determine minimum zoom to fit maximum visible area of wallpaper on crop surface.
377 int cropWidth = mWorkspaceSurface.getMeasuredWidth();
378 int cropHeight = mWorkspaceSurface.getMeasuredHeight();
379 Point crop = new Point(cropWidth, cropHeight);
380 Rect visibleRawWallpaperRect =
381 WallpaperCropUtils.calculateVisibleRect(mRawWallpaperSize, crop);
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700382
383 final PointF centerPosition = WallpaperCropUtils.calculateDefaultCenter(requireContext(),
384 mRawWallpaperSize, visibleRawWallpaperRect);
385
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700386 Point visibleRawWallpaperSize = new Point(visibleRawWallpaperRect.width(),
387 visibleRawWallpaperRect.height());
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700388
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700389 final float defaultWallpaperZoom = WallpaperCropUtils.calculateMinZoom(
390 visibleRawWallpaperSize, crop);
391 final float minWallpaperZoom = defaultWallpaperZoom;
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700392
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700393
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700394 // Set min wallpaper zoom and max zoom on MosaicView widget.
395 mFullResImageView.setMaxScale(Math.max(DEFAULT_WALLPAPER_MAX_ZOOM, defaultWallpaperZoom));
396 mFullResImageView.setMinScale(minWallpaperZoom);
397
398 // Set center to composite positioning between scaled wallpaper and screen.
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700399 mFullResImageView.setScaleAndCenter(minWallpaperZoom, centerPosition);
400 }
401
402 private Rect calculateCropRect() {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700403 float wallpaperZoom = mFullResImageView.getScale();
Chuck Liao5182a312020-03-04 20:04:18 +0800404 Context context = requireContext().getApplicationContext();
Tracy Zhou67fd7e32020-05-01 18:35:36 -0700405
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700406 Rect visibleFileRect = new Rect();
407 mFullResImageView.visibleFileRect(visibleFileRect);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700408
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700409 int cropWidth = mWorkspaceSurface.getMeasuredWidth();
410 int cropHeight = mWorkspaceSurface.getMeasuredHeight();
411 Point hostViewSize = new Point(cropWidth, cropHeight);
412 Rect cropRect = WallpaperCropUtils.calculateCropRect(context, hostViewSize,
413 hostViewSize, mRawWallpaperSize, visibleFileRect, wallpaperZoom);
414 WallpaperCropUtils.adjustCropRect(context, cropRect, false /* zoomIn */);
415 return cropRect;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700416 }
417
418 @Override
419 protected void setCurrentWallpaper(@Destination int destination) {
420 mWallpaperSetter.setCurrentWallpaper(getActivity(), mWallpaper, mWallpaperAsset,
421 destination, mFullResImageView.getScale(), calculateCropRect(),
422 new SetWallpaperCallback() {
423 @Override
“Chuckffd832c2020-03-22 02:15:58 +0800424 public void onSuccess(WallpaperInfo wallpaperInfo) {
Ching-Sung Lib5e9bd72020-06-15 14:10:55 +0800425 finishActivity(/* success= */ true);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700426 }
427
428 @Override
429 public void onError(@Nullable Throwable throwable) {
430 showSetWallpaperErrorDialog(destination);
431 }
432 });
433 }
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700434
435 private void renderWorkspaceSurface() {
436 mWorkspaceSurface.setZOrderMediaOverlay(true);
437 mWorkspaceSurface.getHolder().addCallback(mWorkspaceSurfaceCallback);
438 }
439
440 private void renderImageWallpaper() {
441 mWallpaperSurface.getHolder().addCallback(mWallpaperSurfaceCallback);
442 }
443
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700444 private class WallpaperSurfaceCallback implements SurfaceHolder.Callback {
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700445
446 private Surface mLastSurface;
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700447 private SurfaceControlViewHost mHost;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700448
449 @Override
450 public void surfaceCreated(SurfaceHolder holder) {
451 if (mLastSurface != holder.getSurface()) {
452 mLastSurface = holder.getSurface();
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700453 if (mFullResImageView != null) {
454 mFullResImageView.recycle();
455 }
456 View wallpaperPreviewContainer = LayoutInflater.from(getContext()).inflate(
457 R.layout.fullscreen_wallpaper_preview, null);
458 mFullResImageView = wallpaperPreviewContainer.findViewById(R.id.full_res_image);
459 mLowResImageView = wallpaperPreviewContainer.findViewById(R.id.low_res_image);
Chuck Liaoca1d1292020-06-19 01:29:53 +0800460 // Load a low-res placeholder image if there's a thumbnail available from the asset
461 // that can be shown to the user more quickly than the full-sized image.
462 if (mWallpaperAsset.hasLowResDataSource()) {
463 Activity activity = requireActivity();
464 mWallpaperAsset.loadLowResDrawable(activity, mLowResImageView, Color.BLACK,
465 new WallpaperPreviewBitmapTransformation(
466 activity.getApplicationContext(), isRtl()));
467 }
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700468 wallpaperPreviewContainer.measure(
469 makeMeasureSpec(mWallpaperSurface.getWidth(), EXACTLY),
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700470 makeMeasureSpec(mWallpaperSurface.getHeight(), EXACTLY));
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700471 wallpaperPreviewContainer.layout(0, 0, mWallpaperSurface.getWidth(),
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700472 mWallpaperSurface.getHeight());
Ching-Sung Lib9404622020-05-18 22:38:45 +0800473 mTouchForwardingLayout.setTargetView(mFullResImageView);
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700474
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700475 cleanUp();
476 mHost = new SurfaceControlViewHost(getContext(),
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700477 getContext().getDisplay(), mWallpaperSurface.getHostToken());
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700478 mHost.setView(wallpaperPreviewContainer, wallpaperPreviewContainer.getWidth(),
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700479 wallpaperPreviewContainer.getHeight());
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700480 mWallpaperSurface.setChildSurfacePackage(mHost.getSurfacePackage());
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700481 }
482 }
483
484 @Override
485 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
486
487 @Override
488 public void surfaceDestroyed(SurfaceHolder holder) { }
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700489
490 public void cleanUp() {
491 if (mHost != null) {
492 mHost.release();
493 mHost = null;
494 }
495 }
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700496 };
497
Tracy Zhou67fd7e32020-05-01 18:35:36 -0700498 private void setEditingEnabled(boolean enabled) {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700499 mTouchForwardingLayout.setForwardingEnabled(enabled);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700500 }
501
Wesley.CW Wangf21486b2020-06-02 18:30:32 +0800502 private void updateScreenPreview(boolean isHomeSelected) {
503 mHome.setSelected(isHomeSelected);
504 mLock.setSelected(!isHomeSelected);
505 mWorkspaceSurface.setVisibility(isHomeSelected ? View.VISIBLE : View.GONE);
506 mLockOverlay.setVisibility(isHomeSelected ? View.GONE : View.VISIBLE);
Tracy Zhou67fd7e32020-05-01 18:35:36 -0700507 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700508}