blob: 5c2a904b3537989738128feed895dd040eaf6c8e [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;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070035import android.view.LayoutInflater;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070036import android.view.Surface;
37import android.view.SurfaceControlViewHost;
38import android.view.SurfaceHolder;
39import android.view.SurfaceView;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070040import android.view.View;
41import android.view.ViewGroup;
42import android.widget.ImageView;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070043
Chuck Liaofc1b8c92020-05-21 20:54:15 +080044import androidx.annotation.NonNull;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070045import androidx.annotation.Nullable;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070046import androidx.cardview.widget.CardView;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070047import androidx.constraintlayout.widget.ConstraintLayout;
48import androidx.constraintlayout.widget.ConstraintSet;
49import androidx.core.content.ContextCompat;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070050import androidx.fragment.app.FragmentActivity;
51
52import com.android.wallpaper.R;
53import com.android.wallpaper.asset.Asset;
“Chuckffd832c2020-03-22 02:15:58 +080054import com.android.wallpaper.model.WallpaperInfo;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070055import com.android.wallpaper.module.WallpaperPersister.Destination;
56import com.android.wallpaper.module.WallpaperPersister.SetWallpaperCallback;
57import com.android.wallpaper.util.ScreenSizeCalculator;
Santiago Etchebehere53c63432020-05-07 18:55:35 -070058import com.android.wallpaper.util.SizeCalculator;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070059import com.android.wallpaper.util.WallpaperCropUtils;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -070060import com.android.wallpaper.widget.BottomActionBar;
Wesley.CW Wang61c28ec2020-06-19 18:58:50 +080061import com.android.wallpaper.widget.BottomActionBar.AccessibilityCallback;
chihhangchuang287d4b72020-06-25 01:09:09 +080062import com.android.wallpaper.widget.LockScreenPreviewer;
Chuck Liaofc1b8c92020-05-21 20:54:15 +080063import 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
chihhangchuang923e29b2020-07-02 19:09:36 +080071import java.util.Locale;
72
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070073/**
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -080074 * Fragment which displays the UI for previewing an individual static wallpaper and its attribution
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070075 * information.
76 */
77public class ImagePreviewFragment extends PreviewFragment {
78
79 private static final float DEFAULT_WALLPAPER_MAX_ZOOM = 8f;
80
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 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;
chihhangchuang287d4b72020-06-25 01:09:09 +080094 private ViewGroup mLockPreviewContainer;
95 private LockScreenPreviewer mLockScreenPreviewer;
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);
chihhangchuang923e29b2020-07-02 19:09:36 +0800136 String ratio = String.format(Locale.US, "%d:%d", mScreenSize.x, mScreenSize.y);
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700137 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);
chihhangchuang287d4b72020-06-25 01:09:09 +0800144 mLockPreviewContainer = mContainer.findViewById(R.id.lock_screen_preview_container);
145 mLockScreenPreviewer = new LockScreenPreviewer(getLifecycle(), getActivity(),
146 mLockPreviewContainer);
Chuck Liaofc1b8c92020-05-21 20:54:15 +0800147
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700148 mTabs = view.findViewById(R.id.tabs_container);
Wesley.CW Wangf21486b2020-06-02 18:30:32 +0800149 mLock = mTabs.findViewById(R.id.lock);
150 mHome = mTabs.findViewById(R.id.home);
151 mLock.setOnClickListener(v -> updateScreenPreview(/* isHomeSelected= */ false));
152 mHome.setOnClickListener(v -> updateScreenPreview(/* isHomeSelected= */ true));
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700153
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700154 view.measure(makeMeasureSpec(mScreenSize.x, EXACTLY),
155 makeMeasureSpec(mScreenSize.y, EXACTLY));
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700156
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700157 ((CardView) mWorkspaceSurface.getParent())
158 .setRadius(SizeCalculator.getPreviewCornerRadius(
159 activity, mContainer.getMeasuredWidth()));
160 renderImageWallpaper();
161 renderWorkspaceSurface();
Ching-Sung Liba4f1fe2020-06-10 15:59:15 +0800162 updateScreenPreview(/* isHomeSelected= */ mViewAsHome);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700163
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700164 // Trim some memory from Glide to make room for the full-size image in this fragment.
165 Glide.get(activity).setMemoryCategory(MemoryCategory.LOW);
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800166 setUpLoadingIndicator();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700167 return view;
168 }
169
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -0800170 @Override
Chuck Liaofc1b8c92020-05-21 20:54:15 +0800171 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
172 super.onViewCreated(view, savedInstanceState);
chihhangchuang90f902c2020-06-03 16:14:40 +0800173 WallpaperColorsLoader.getWallpaperColors(getContext(),
174 mWallpaper.getThumbAsset(getContext()),
chihhangchuang287d4b72020-06-25 01:09:09 +0800175 mLockScreenPreviewer::setColor);
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -0800176 }
177
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800178 @Override
179 protected boolean isLoaded() {
180 return mFullResImageView != null && mFullResImageView.hasImage();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700181 }
182
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700183 @Override
184 public void onClickOk() {
185 FragmentActivity activity = getActivity();
186 if (activity != null) {
187 activity.finish();
188 }
189 }
190
191 @Override
192 public void onDestroy() {
193 super.onDestroy();
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800194 if (mLoadingProgressBar != null) {
195 mLoadingProgressBar.hide();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700196 }
197 mFullResImageView.recycle();
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700198
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700199 mWallpaperSurfaceCallback.cleanUp();
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700200 mWorkspaceSurfaceCallback.cleanUp();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700201 }
202
203 @Override
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700204 protected void onBottomActionBarReady(BottomActionBar bottomActionBar) {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700205 super.onBottomActionBarReady(bottomActionBar);
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700206
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700207 mWallpaperInfoView = (WallpaperInfoView)
208 LayoutInflater.from(getContext()).inflate(
209 R.layout.wallpaper_info_view, /* root= */null);
210 mBottomActionBar.attachViewToBottomSheetAndBindAction(mWallpaperInfoView, INFORMATION);
211 mBottomActionBar.showActionsOnly(INFORMATION, EDIT, APPLY);
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700212 mBottomActionBar.setActionClickListener(EDIT, v ->
Tracy Zhou16112e32020-05-27 13:13:23 -0700213 setEditingEnabled(mBottomActionBar.isActionSelected(EDIT))
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700214 );
Chihhang Chuangca7c8252020-06-17 17:32:46 +0800215 mBottomActionBar.setActionSelectedListener(EDIT, this::setEditingEnabled);
216 mBottomActionBar.setActionClickListener(APPLY, this::onSetWallpaperClicked);
Wesley.CW Wang61c28ec2020-06-19 18:58:50 +0800217
218 // Update target view's accessibility param since it will be blocked by the bottom sheet
219 // when expanded.
220 mBottomActionBar.setAccessibilityCallback(new AccessibilityCallback() {
221 @Override
222 public void onBottomSheetCollapsed() {
Wesley.CW Wangb8e51a22020-07-02 18:40:31 +0800223 mContainer.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
Wesley.CW Wang61c28ec2020-06-19 18:58:50 +0800224 mTabs.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
225 }
226
227 @Override
228 public void onBottomSheetExpanded() {
Wesley.CW Wangb8e51a22020-07-02 18:40:31 +0800229 mContainer.setImportantForAccessibility(
230 View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
Wesley.CW Wang61c28ec2020-06-19 18:58:50 +0800231 mTabs.setImportantForAccessibility(
232 View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
233 }
234 });
235
Chihhang Chuangca7c8252020-06-17 17:32:46 +0800236 // Will trigger onActionSelected callback to update the editing state.
237 mBottomActionBar.setDefaultSelectedButton(EDIT);
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700238 mBottomActionBar.show();
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700239
chihhangchuang13cb1fe2020-06-30 16:46:59 +0800240 mBottomActionBar.disableActions();
241 mWallpaperAsset.decodeRawDimensions(getActivity(), dimensions -> {
242 if (mBottomActionBar != null) {
243 mBottomActionBar.enableActions();
244 }
245
246 // Don't continue loading the wallpaper if the Fragment is detached.
247 if (getActivity() == null) {
248 return;
249 }
250
251 // Return early and show a dialog if dimensions are null (signaling a decoding error).
252 if (dimensions == null) {
253 showLoadWallpaperErrorDialog();
254 return;
255 }
256
257 mRawWallpaperSize = dimensions;
258
259 setUpExploreIntentAndLabel(ImagePreviewFragment.this::initFullResView);
260 });
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700261 }
262
263 /**
264 * Initializes MosaicView by initializing tiling, setting a fallback page bitmap, and
265 * initializing a zoom-scroll observer and click listener.
266 */
267 private void initFullResView() {
Tracy Zhoudee07892020-06-16 20:14:30 -0700268 // Minimum scale will only be respected under this scale type.
269 mFullResImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM);
270 // When we set a minimum scale bigger than the scale with which the full image is shown,
271 // disallow user to pan outside the view we show the wallpaper in.
272 mFullResImageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700273
274 // Set a solid black "page bitmap" so MosaicView draws a black background while waiting
275 // for the image to load or a transparent one if a thumbnail already loaded.
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700276 Bitmap backgroundBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700277 int preColor = ContextCompat.getColor(getContext(), R.color.fullscreen_preview_background);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700278 int color = (mLowResImageView.getDrawable() == null) ? preColor : Color.TRANSPARENT;
279 backgroundBitmap.setPixel(0, 0, color);
280 mFullResImageView.setImage(ImageSource.bitmap(backgroundBitmap));
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700281
282 // Then set a fallback "page bitmap" to cover the whole MosaicView, which is an actual
283 // (lower res) version of the image to be displayed.
284 Point targetPageBitmapSize = new Point(mRawWallpaperSize);
285 mWallpaperAsset.decodeBitmap(targetPageBitmapSize.x, targetPageBitmapSize.y,
286 pageBitmap -> {
287 // Check that the activity is still around since the decoding task started.
288 if (getActivity() == null) {
289 return;
290 }
291
292 // Some of these may be null depending on if the Fragment is paused, stopped,
293 // or destroyed.
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800294 if (mLoadingProgressBar != null) {
295 mLoadingProgressBar.hide();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700296 }
297 // The page bitmap may be null if there was a decoding error, so show an
298 // error dialog.
299 if (pageBitmap == null) {
300 showLoadWallpaperErrorDialog();
301 return;
302 }
303 if (mFullResImageView != null) {
304 // Set page bitmap.
305 mFullResImageView.setImage(ImageSource.bitmap(pageBitmap));
306
307 setDefaultWallpaperZoomAndScroll();
308 crossFadeInMosaicView();
309 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700310 getActivity().invalidateOptionsMenu();
311
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700312 if (mWallpaperInfoView != null && mWallpaper != null) {
313 mWallpaperInfoView.populateWallpaperInfo(mWallpaper, mActionLabel,
314 mExploreIntent, this::onExploreClicked);
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700315 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700316 });
317 }
318
319 /**
320 * Makes the MosaicView visible with an alpha fade-in animation while fading out the loading
321 * indicator.
322 */
323 private void crossFadeInMosaicView() {
324 long shortAnimationDuration = getResources().getInteger(
325 android.R.integer.config_shortAnimTime);
326
327 mFullResImageView.setAlpha(0f);
328 mFullResImageView.animate()
329 .alpha(1f)
330 .setDuration(shortAnimationDuration)
331 .setListener(new AnimatorListenerAdapter() {
332 @Override
333 public void onAnimationEnd(Animator animation) {
334 // Clear the thumbnail bitmap reference to save memory since it's no longer
335 // visible.
336 if (mLowResImageView != null) {
337 mLowResImageView.setImageBitmap(null);
338 }
339 }
340 });
341
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800342 mLoadingProgressBar.animate()
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700343 .alpha(0f)
344 .setDuration(shortAnimationDuration)
345 .setListener(new AnimatorListenerAdapter() {
346 @Override
347 public void onAnimationEnd(Animator animation) {
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800348 if (mLoadingProgressBar != null) {
349 mLoadingProgressBar.hide();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700350 }
351 }
352 });
353 }
354
355 /**
Michel Comin Escudeb3e1fef2019-11-22 11:41:53 -0800356 * Sets the default wallpaper zoom and scroll position based on a "crop surface" (with extra
357 * width to account for parallax) superimposed on the screen. Shows as much of the wallpaper as
358 * possible on the crop surface and align screen to crop surface such that the default preview
359 * matches what would be seen by the user in the left-most home screen.
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700360 *
361 * <p>This method is called once in the Fragment lifecycle after the wallpaper asset has loaded
362 * and rendered to the layout.
363 */
364 private void setDefaultWallpaperZoomAndScroll() {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700365 // Determine minimum zoom to fit maximum visible area of wallpaper on crop surface.
366 int cropWidth = mWorkspaceSurface.getMeasuredWidth();
367 int cropHeight = mWorkspaceSurface.getMeasuredHeight();
368 Point crop = new Point(cropWidth, cropHeight);
369 Rect visibleRawWallpaperRect =
370 WallpaperCropUtils.calculateVisibleRect(mRawWallpaperSize, crop);
Santiago Etchebeheree95b6d92020-06-08 14:19:46 -0700371
372 final PointF centerPosition = WallpaperCropUtils.calculateDefaultCenter(requireContext(),
373 mRawWallpaperSize, visibleRawWallpaperRect);
374
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700375 Point visibleRawWallpaperSize = new Point(visibleRawWallpaperRect.width(),
376 visibleRawWallpaperRect.height());
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700377
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700378 final float defaultWallpaperZoom = WallpaperCropUtils.calculateMinZoom(
379 visibleRawWallpaperSize, crop);
380 final float minWallpaperZoom = defaultWallpaperZoom;
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700381
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700382
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700383 // Set min wallpaper zoom and max zoom on MosaicView widget.
384 mFullResImageView.setMaxScale(Math.max(DEFAULT_WALLPAPER_MAX_ZOOM, defaultWallpaperZoom));
385 mFullResImageView.setMinScale(minWallpaperZoom);
386
387 // Set center to composite positioning between scaled wallpaper and screen.
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700388 mFullResImageView.setScaleAndCenter(minWallpaperZoom, centerPosition);
389 }
390
391 private Rect calculateCropRect() {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700392 float wallpaperZoom = mFullResImageView.getScale();
Chuck Liao5182a312020-03-04 20:04:18 +0800393 Context context = requireContext().getApplicationContext();
Tracy Zhou67fd7e32020-05-01 18:35:36 -0700394
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700395 Rect visibleFileRect = new Rect();
396 mFullResImageView.visibleFileRect(visibleFileRect);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700397
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700398 int cropWidth = mWorkspaceSurface.getMeasuredWidth();
399 int cropHeight = mWorkspaceSurface.getMeasuredHeight();
400 Point hostViewSize = new Point(cropWidth, cropHeight);
401 Rect cropRect = WallpaperCropUtils.calculateCropRect(context, hostViewSize,
402 hostViewSize, mRawWallpaperSize, visibleFileRect, wallpaperZoom);
403 WallpaperCropUtils.adjustCropRect(context, cropRect, false /* zoomIn */);
404 return cropRect;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700405 }
406
407 @Override
408 protected void setCurrentWallpaper(@Destination int destination) {
409 mWallpaperSetter.setCurrentWallpaper(getActivity(), mWallpaper, mWallpaperAsset,
410 destination, mFullResImageView.getScale(), calculateCropRect(),
411 new SetWallpaperCallback() {
412 @Override
“Chuckffd832c2020-03-22 02:15:58 +0800413 public void onSuccess(WallpaperInfo wallpaperInfo) {
Ching-Sung Lib5e9bd72020-06-15 14:10:55 +0800414 finishActivity(/* success= */ true);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700415 }
416
417 @Override
418 public void onError(@Nullable Throwable throwable) {
419 showSetWallpaperErrorDialog(destination);
420 }
421 });
422 }
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700423
424 private void renderWorkspaceSurface() {
425 mWorkspaceSurface.setZOrderMediaOverlay(true);
426 mWorkspaceSurface.getHolder().addCallback(mWorkspaceSurfaceCallback);
427 }
428
429 private void renderImageWallpaper() {
430 mWallpaperSurface.getHolder().addCallback(mWallpaperSurfaceCallback);
431 }
432
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700433 private class WallpaperSurfaceCallback implements SurfaceHolder.Callback {
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700434
435 private Surface mLastSurface;
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700436 private SurfaceControlViewHost mHost;
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700437
438 @Override
439 public void surfaceCreated(SurfaceHolder holder) {
440 if (mLastSurface != holder.getSurface()) {
441 mLastSurface = holder.getSurface();
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700442 if (mFullResImageView != null) {
443 mFullResImageView.recycle();
444 }
445 View wallpaperPreviewContainer = LayoutInflater.from(getContext()).inflate(
446 R.layout.fullscreen_wallpaper_preview, null);
447 mFullResImageView = wallpaperPreviewContainer.findViewById(R.id.full_res_image);
448 mLowResImageView = wallpaperPreviewContainer.findViewById(R.id.low_res_image);
Chuck Liaoca1d1292020-06-19 01:29:53 +0800449 // Load a low-res placeholder image if there's a thumbnail available from the asset
450 // that can be shown to the user more quickly than the full-sized image.
451 if (mWallpaperAsset.hasLowResDataSource()) {
452 Activity activity = requireActivity();
453 mWallpaperAsset.loadLowResDrawable(activity, mLowResImageView, Color.BLACK,
454 new WallpaperPreviewBitmapTransformation(
455 activity.getApplicationContext(), isRtl()));
456 }
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700457 wallpaperPreviewContainer.measure(
458 makeMeasureSpec(mWallpaperSurface.getWidth(), EXACTLY),
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700459 makeMeasureSpec(mWallpaperSurface.getHeight(), EXACTLY));
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700460 wallpaperPreviewContainer.layout(0, 0, mWallpaperSurface.getWidth(),
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700461 mWallpaperSurface.getHeight());
Ching-Sung Lib9404622020-05-18 22:38:45 +0800462 mTouchForwardingLayout.setTargetView(mFullResImageView);
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700463
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700464 cleanUp();
465 mHost = new SurfaceControlViewHost(getContext(),
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700466 getContext().getDisplay(), mWallpaperSurface.getHostToken());
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700467 mHost.setView(wallpaperPreviewContainer, wallpaperPreviewContainer.getWidth(),
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700468 wallpaperPreviewContainer.getHeight());
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700469 mWallpaperSurface.setChildSurfacePackage(mHost.getSurfacePackage());
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700470 }
471 }
472
473 @Override
474 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
475
476 @Override
477 public void surfaceDestroyed(SurfaceHolder holder) { }
Tracy Zhou4421a3d2020-06-15 14:56:18 -0700478
479 public void cleanUp() {
480 if (mHost != null) {
481 mHost.release();
482 mHost = null;
483 }
484 }
Tracy Zhoua19cbdd2020-04-26 12:12:11 -0700485 };
486
Tracy Zhou67fd7e32020-05-01 18:35:36 -0700487 private void setEditingEnabled(boolean enabled) {
Tracy Zhouecfd6eb2020-05-27 23:56:35 -0700488 mTouchForwardingLayout.setForwardingEnabled(enabled);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700489 }
490
Wesley.CW Wangf21486b2020-06-02 18:30:32 +0800491 private void updateScreenPreview(boolean isHomeSelected) {
492 mHome.setSelected(isHomeSelected);
493 mLock.setSelected(!isHomeSelected);
chihhangchuang287d4b72020-06-25 01:09:09 +0800494 mWorkspaceSurface.setVisibility(isHomeSelected ? View.VISIBLE : View.INVISIBLE);
495 mLockPreviewContainer.setVisibility(isHomeSelected ? View.INVISIBLE : View.VISIBLE);
Tracy Zhou67fd7e32020-05-01 18:35:36 -0700496 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700497}