summaryrefslogtreecommitdiffstats
path: root/src/com/android/wallpaper/picker
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/wallpaper/picker')
-rwxr-xr-xsrc/com/android/wallpaper/picker/ImagePreviewFragment.java464
-rw-r--r--src/com/android/wallpaper/picker/LivePreviewFragment.java655
-rwxr-xr-xsrc/com/android/wallpaper/picker/PreviewFragment.java689
-rwxr-xr-xsrc/com/android/wallpaper/picker/StartRotationDialogFragment.java25
-rwxr-xr-xsrc/com/android/wallpaper/picker/individual/IndividualPickerActivity.java36
-rwxr-xr-xsrc/com/android/wallpaper/picker/individual/IndividualPickerFragment.java119
6 files changed, 1311 insertions, 677 deletions
diff --git a/src/com/android/wallpaper/picker/ImagePreviewFragment.java b/src/com/android/wallpaper/picker/ImagePreviewFragment.java
new file mode 100755
index 0000000..87e29c5
--- /dev/null
+++ b/src/com/android/wallpaper/picker/ImagePreviewFragment.java
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2019 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.picker;
+
+import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.view.ContextThemeWrapper;
+import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.wallpaper.R;
+import com.android.wallpaper.asset.Asset;
+import com.android.wallpaper.module.WallpaperPersister.Destination;
+import com.android.wallpaper.module.WallpaperPersister.SetWallpaperCallback;
+import com.android.wallpaper.util.ScreenSizeCalculator;
+import com.android.wallpaper.util.WallpaperCropUtils;
+import com.android.wallpaper.widget.MaterialProgressDrawable;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.MemoryCategory;
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+
+import java.util.List;
+
+/**
+ * Fragment which displays the UI for previewing an individual static wallpaper and its attribution
+ * information.
+ */
+public class ImagePreviewFragment extends PreviewFragment {
+
+ private static final float DEFAULT_WALLPAPER_MAX_ZOOM = 8f;
+
+ private SubsamplingScaleImageView mFullResImageView;
+ private Asset mWallpaperAsset;
+ private TextView mAttributionTitle;
+ private TextView mAttributionSubtitle1;
+ private TextView mAttributionSubtitle2;
+ private Button mExploreButton;
+ private Button mSetWallpaperButton;
+
+ private Point mDefaultCropSurfaceSize;
+ private Point mScreenSize;
+ private Point mRawWallpaperSize; // Native size of wallpaper image.
+ private ImageView mLoadingIndicator;
+ private MaterialProgressDrawable mProgressDrawable;
+ private ImageView mLowResImageView;
+ private View mSpacer;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mWallpaperAsset = mWallpaper.getAsset(requireContext().getApplicationContext());
+ }
+
+ @Override
+ protected int getLayoutResId() {
+ return R.layout.fragment_image_preview;
+ }
+
+ @Override
+ protected int getBottomSheetResId() {
+ return R.id.bottom_sheet;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = super.onCreateView(inflater, container, savedInstanceState);
+
+ Activity activity = requireActivity();
+ // Set toolbar as the action bar.
+
+ mFullResImageView = view.findViewById(R.id.full_res_image);
+ mLoadingIndicator = view.findViewById(R.id.loading_indicator);
+
+ mAttributionTitle = view.findViewById(R.id.preview_attribution_pane_title);
+ mAttributionSubtitle1 = view.findViewById(R.id.preview_attribution_pane_subtitle1);
+ mAttributionSubtitle2 = view.findViewById(R.id.preview_attribution_pane_subtitle2);
+ mExploreButton = view.findViewById(R.id.preview_attribution_pane_explore_button);
+ mSetWallpaperButton = view.findViewById(R.id.preview_attribution_pane_set_wallpaper_button);
+
+ mLowResImageView = view.findViewById(R.id.low_res_image);
+ mSpacer = view.findViewById(R.id.spacer);
+
+ // Trim some memory from Glide to make room for the full-size image in this fragment.
+ Glide.get(activity).setMemoryCategory(MemoryCategory.LOW);
+
+ mDefaultCropSurfaceSize = WallpaperCropUtils.getDefaultCropSurfaceSize(
+ getResources(), activity.getWindowManager().getDefaultDisplay());
+ mScreenSize = ScreenSizeCalculator.getInstance().getScreenSize(
+ activity.getWindowManager().getDefaultDisplay());
+
+ // Load a low-res placeholder image if there's a thumbnail available from the asset that can
+ // be shown to the user more quickly than the full-sized image.
+ if (mWallpaperAsset.hasLowResDataSource()) {
+ mWallpaperAsset.loadLowResDrawable(activity, mLowResImageView, Color.BLACK,
+ new WallpaperPreviewBitmapTransformation(activity.getApplicationContext(),
+ isRtl()));
+ }
+
+ mWallpaperAsset.decodeRawDimensions(getActivity(), dimensions -> {
+ // Don't continue loading the wallpaper if the Fragment is detached.
+ if (getActivity() == null) {
+ return;
+ }
+
+ // Return early and show a dialog if dimensions are null (signaling a decoding error).
+ if (dimensions == null) {
+ showLoadWallpaperErrorDialog();
+ return;
+ }
+
+ mRawWallpaperSize = dimensions;
+ setUpExploreIntent(ImagePreviewFragment.this::initFullResView);
+ });
+
+ // Configure loading indicator with a MaterialProgressDrawable.
+ setUpLoadingIndicator();
+
+ return view;
+ }
+
+ @Override
+ protected void setUpBottomSheetView(ViewGroup bottomSheet) {
+ // Nothing needed here.
+ }
+
+ private void setUpLoadingIndicator() {
+ Context context = requireContext();
+ mProgressDrawable = new MaterialProgressDrawable(context.getApplicationContext(),
+ mLoadingIndicator);
+ mProgressDrawable.setAlpha(255);
+ mProgressDrawable.setBackgroundColor(getResources().getColor(R.color.material_white_100,
+ context.getTheme()));
+ mProgressDrawable.setColorSchemeColors(getAttrColor(
+ new ContextThemeWrapper(context, getDeviceDefaultTheme()),
+ android.R.attr.colorAccent));
+ mProgressDrawable.updateSizes(MaterialProgressDrawable.LARGE);
+ mLoadingIndicator.setImageDrawable(mProgressDrawable);
+
+ // We don't want to show the spinner every time we load an image if it loads quickly;
+ // instead, only start showing the spinner if loading the image has taken longer than half
+ // of a second.
+ mLoadingIndicator.postDelayed(() -> {
+ if (mFullResImageView != null && !mFullResImageView.hasImage()
+ && !mTestingModeEnabled) {
+ mLoadingIndicator.setVisibility(View.VISIBLE);
+ mLoadingIndicator.setAlpha(1f);
+ if (mProgressDrawable != null) {
+ mProgressDrawable.start();
+ }
+ }
+ }, 500);
+ }
+
+ @Override
+ public void onClickOk() {
+ FragmentActivity activity = getActivity();
+ if (activity != null) {
+ activity.finish();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mProgressDrawable != null) {
+ mProgressDrawable.stop();
+ }
+ mFullResImageView.recycle();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ final BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(mBottomSheet);
+ outState.putInt(KEY_BOTTOM_SHEET_STATE, bottomSheetBehavior.getState());
+ }
+
+ @Override
+ protected void setBottomSheetContentAlpha(float alpha) {
+ mExploreButton.setAlpha(alpha);
+ mAttributionTitle.setAlpha(alpha);
+ mAttributionSubtitle1.setAlpha(alpha);
+ mAttributionSubtitle2.setAlpha(alpha);
+ }
+
+ private void populateAttributionPane() {
+ final Context context = getContext();
+
+ final BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(mBottomSheet);
+
+ List<String> attributions = mWallpaper.getAttributions(context);
+ if (attributions.size() > 0 && attributions.get(0) != null) {
+ mAttributionTitle.setText(attributions.get(0));
+ }
+
+ if (attributions.size() > 1 && attributions.get(1) != null) {
+ mAttributionSubtitle1.setVisibility(View.VISIBLE);
+ mAttributionSubtitle1.setText(attributions.get(1));
+ }
+
+ if (attributions.size() > 2 && attributions.get(2) != null) {
+ mAttributionSubtitle2.setVisibility(View.VISIBLE);
+ mAttributionSubtitle2.setText(attributions.get(2));
+ }
+
+ setUpSetWallpaperButton(mSetWallpaperButton);
+
+ setUpExploreButton(mExploreButton);
+
+ if (mExploreButton.getVisibility() == View.VISIBLE
+ && mSetWallpaperButton.getVisibility() == View.VISIBLE) {
+ mSpacer.setVisibility(View.VISIBLE);
+ } else {
+ mSpacer.setVisibility(View.GONE);
+ }
+
+ mBottomSheet.setVisibility(View.VISIBLE);
+
+ // Initialize the state of the BottomSheet based on the current state because if the initial
+ // and current state are the same, the state change listener won't fire and set the correct
+ // arrow asset and text alpha.
+ if (bottomSheetBehavior.getState() == STATE_EXPANDED) {
+ setPreviewChecked(false);
+ mAttributionTitle.setAlpha(1f);
+ mAttributionSubtitle1.setAlpha(1f);
+ mAttributionSubtitle2.setAlpha(1f);
+ } else {
+ setPreviewChecked(true);
+ mAttributionTitle.setAlpha(0f);
+ mAttributionSubtitle1.setAlpha(0f);
+ mAttributionSubtitle2.setAlpha(0f);
+ }
+
+ // Let the state change listener take care of animating a state change to the initial state
+ // if there's a state change.
+ bottomSheetBehavior.setState(mBottomSheetInitialState);
+ }
+
+ /**
+ * Initializes MosaicView by initializing tiling, setting a fallback page bitmap, and
+ * initializing a zoom-scroll observer and click listener.
+ */
+ private void initFullResView() {
+ mFullResImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
+
+ // Set a solid black "page bitmap" so MosaicView draws a black background while waiting
+ // for the image to load or a transparent one if a thumbnail already loaded.
+ Bitmap blackBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
+ int color = (mLowResImageView.getDrawable() == null) ? Color.BLACK : Color.TRANSPARENT;
+ blackBitmap.setPixel(0, 0, color);
+ mFullResImageView.setImage(ImageSource.bitmap(blackBitmap));
+
+ // Then set a fallback "page bitmap" to cover the whole MosaicView, which is an actual
+ // (lower res) version of the image to be displayed.
+ Point targetPageBitmapSize = new Point(mRawWallpaperSize);
+ mWallpaperAsset.decodeBitmap(targetPageBitmapSize.x, targetPageBitmapSize.y,
+ pageBitmap -> {
+ // Check that the activity is still around since the decoding task started.
+ if (getActivity() == null) {
+ return;
+ }
+
+ // Some of these may be null depending on if the Fragment is paused, stopped,
+ // or destroyed.
+ if (mLoadingIndicator != null) {
+ mLoadingIndicator.setVisibility(View.GONE);
+ }
+ // The page bitmap may be null if there was a decoding error, so show an
+ // error dialog.
+ if (pageBitmap == null) {
+ showLoadWallpaperErrorDialog();
+ return;
+ }
+ if (mFullResImageView != null) {
+ // Set page bitmap.
+ mFullResImageView.setImage(ImageSource.bitmap(pageBitmap));
+
+ setDefaultWallpaperZoomAndScroll();
+ crossFadeInMosaicView();
+ }
+ if (mProgressDrawable != null) {
+ mProgressDrawable.stop();
+ }
+ getActivity().invalidateOptionsMenu();
+
+ populateAttributionPane();
+ });
+ }
+
+ /**
+ * Makes the MosaicView visible with an alpha fade-in animation while fading out the loading
+ * indicator.
+ */
+ private void crossFadeInMosaicView() {
+ long shortAnimationDuration = getResources().getInteger(
+ android.R.integer.config_shortAnimTime);
+
+ mFullResImageView.setAlpha(0f);
+ mFullResImageView.animate()
+ .alpha(1f)
+ .setDuration(shortAnimationDuration)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Clear the thumbnail bitmap reference to save memory since it's no longer
+ // visible.
+ if (mLowResImageView != null) {
+ mLowResImageView.setImageBitmap(null);
+ }
+ }
+ });
+
+ mLoadingIndicator.animate()
+ .alpha(0f)
+ .setDuration(shortAnimationDuration)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mLoadingIndicator != null) {
+ mLoadingIndicator.setVisibility(View.GONE);
+ }
+ }
+ });
+ }
+
+ /**
+ * Sets the default wallpaper zoom and scroll position based on a "crop surface"
+ * (with extra width to account for parallax) superimposed on the screen. Shows as much of the
+ * wallpaper as possible on the crop surface and align screen to crop surface such that the
+ * default preview matches what would be seen by the user in the left-most home screen.
+ *
+ * <p>This method is called once in the Fragment lifecycle after the wallpaper asset has loaded
+ * and rendered to the layout.
+ */
+ private void setDefaultWallpaperZoomAndScroll() {
+ // Determine minimum zoom to fit maximum visible area of wallpaper on crop surface.
+ float defaultWallpaperZoom =
+ WallpaperCropUtils.calculateMinZoom(mRawWallpaperSize, mDefaultCropSurfaceSize);
+ float minWallpaperZoom =
+ WallpaperCropUtils.calculateMinZoom(mRawWallpaperSize, mScreenSize);
+
+ Point screenToCropSurfacePosition = WallpaperCropUtils.calculateCenterPosition(
+ mDefaultCropSurfaceSize, mScreenSize, true /* alignStart */, isRtl());
+ Point zoomedWallpaperSize = new Point(
+ Math.round(mRawWallpaperSize.x * defaultWallpaperZoom),
+ Math.round(mRawWallpaperSize.y * defaultWallpaperZoom));
+ Point cropSurfaceToWallpaperPosition = WallpaperCropUtils.calculateCenterPosition(
+ zoomedWallpaperSize, mDefaultCropSurfaceSize, false /* alignStart */, isRtl());
+
+ // Set min wallpaper zoom and max zoom on MosaicView widget.
+ mFullResImageView.setMaxScale(Math.max(DEFAULT_WALLPAPER_MAX_ZOOM, defaultWallpaperZoom));
+ mFullResImageView.setMinScale(minWallpaperZoom);
+
+ // Set center to composite positioning between scaled wallpaper and screen.
+ PointF centerPosition = new PointF(
+ mRawWallpaperSize.x / 2f,
+ mRawWallpaperSize.y / 2f);
+ centerPosition.offset(-(screenToCropSurfacePosition.x + cropSurfaceToWallpaperPosition.x),
+ -(screenToCropSurfacePosition.y + cropSurfaceToWallpaperPosition.y));
+
+ mFullResImageView.setScaleAndCenter(minWallpaperZoom, centerPosition);
+ }
+
+ private Rect calculateCropRect() {
+ // Calculate Rect of wallpaper in physical pixel terms (i.e., scaled to current zoom).
+ float wallpaperZoom = mFullResImageView.getScale();
+ int scaledWallpaperWidth = (int) (mRawWallpaperSize.x * wallpaperZoom);
+ int scaledWallpaperHeight = (int) (mRawWallpaperSize.y * wallpaperZoom);
+ Rect rect = new Rect();
+ mFullResImageView.visibleFileRect(rect);
+ int scrollX = (int) (rect.left * wallpaperZoom);
+ int scrollY = (int) (rect.top * wallpaperZoom);
+
+ rect.set(0, 0, scaledWallpaperWidth, scaledWallpaperHeight);
+
+ Display defaultDisplay = requireActivity().getWindowManager().getDefaultDisplay();
+ Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(defaultDisplay);
+ // Crop rect should start off as the visible screen and then include extra width and height
+ // if available within wallpaper at the current zoom.
+ Rect cropRect = new Rect(scrollX, scrollY, scrollX + screenSize.x, scrollY + screenSize.y);
+
+ Point defaultCropSurfaceSize = WallpaperCropUtils.getDefaultCropSurfaceSize(
+ getResources(), defaultDisplay);
+ int extraWidth = defaultCropSurfaceSize.x - screenSize.x;
+ int extraHeightTopAndBottom = (int) ((defaultCropSurfaceSize.y - screenSize.y) / 2f);
+
+ // Try to increase size of screenRect to include extra width depending on the layout
+ // direction.
+ if (isRtl()) {
+ cropRect.left = Math.max(cropRect.left - extraWidth, rect.left);
+ } else {
+ cropRect.right = Math.min(cropRect.right + extraWidth, rect.right);
+ }
+
+ // Try to increase the size of the cropRect to to include extra height.
+ int availableExtraHeightTop = cropRect.top - Math.max(
+ rect.top,
+ cropRect.top - extraHeightTopAndBottom);
+ int availableExtraHeightBottom = Math.min(
+ rect.bottom,
+ cropRect.bottom + extraHeightTopAndBottom) - cropRect.bottom;
+
+ int availableExtraHeightTopAndBottom =
+ Math.min(availableExtraHeightTop, availableExtraHeightBottom);
+ cropRect.top -= availableExtraHeightTopAndBottom;
+ cropRect.bottom += availableExtraHeightTopAndBottom;
+
+ return cropRect;
+ }
+
+ @Override
+ protected void setCurrentWallpaper(@Destination int destination) {
+ mWallpaperSetter.setCurrentWallpaper(getActivity(), mWallpaper, mWallpaperAsset,
+ destination, mFullResImageView.getScale(), calculateCropRect(),
+ new SetWallpaperCallback() {
+ @Override
+ public void onSuccess() {
+ finishActivityWithResultOk();
+ }
+
+ @Override
+ public void onError(@Nullable Throwable throwable) {
+ showSetWallpaperErrorDialog(destination);
+ }
+ });
+ }
+}
diff --git a/src/com/android/wallpaper/picker/LivePreviewFragment.java b/src/com/android/wallpaper/picker/LivePreviewFragment.java
new file mode 100644
index 0000000..fee60a8
--- /dev/null
+++ b/src/com/android/wallpaper/picker/LivePreviewFragment.java
@@ -0,0 +1,655 @@
+/*
+ * Copyright (C) 2019 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.picker;
+
+import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.WallpaperColors;
+import android.app.WallpaperManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.service.wallpaper.IWallpaperConnection;
+import android.service.wallpaper.IWallpaperEngine;
+import android.service.wallpaper.IWallpaperService;
+import android.service.wallpaper.WallpaperService;
+import android.service.wallpaper.WallpaperSettingsActivity;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager.LayoutParams;
+import android.view.animation.AnimationUtils;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.LiveData;
+import androidx.slice.Slice;
+import androidx.slice.widget.SliceLiveData;
+import androidx.slice.widget.SliceView;
+import androidx.viewpager.widget.PagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+
+import com.android.wallpaper.R;
+import com.android.wallpaper.compat.BuildCompat;
+import com.android.wallpaper.model.LiveWallpaperInfo;
+import com.android.wallpaper.module.WallpaperPersister.SetWallpaperCallback;
+import com.android.wallpaper.widget.MaterialProgressDrawable;
+
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.tabs.TabLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Fragment which displays the UI for previewing an individual live wallpaper, its attribution
+ * information and settings slices if available.
+ */
+public class LivePreviewFragment extends PreviewFragment {
+
+ private static final String TAG = "LivePreviewFragment";
+
+ private static final String KEY_ACTION_DELETE_LIVE_WALLPAPER = "action_delete_live_wallpaper";
+ private static final String EXTRA_LIVE_WALLPAPER_INFO = "android.live_wallpaper.info";
+
+ /**
+ * Instance of {@link WallpaperConnection} used to bind to the live wallpaper service to show
+ * it in this preview fragment.
+ * @see IWallpaperConnection
+ */
+ private WallpaperConnection mWallpaperConnection;
+
+ private Intent mWallpaperIntent;
+ private Intent mDeleteIntent;
+ private Intent mSettingsIntent;
+
+ private List<Pair<String, View>> mPages;
+ private ImageView mLoadingIndicator;
+ private TextView mAttributionTitle;
+ private TextView mAttributionSubtitle1;
+ private TextView mAttributionSubtitle2;
+ private Button mExploreButton;
+ private Button mSetWallpaperButton;
+ private ViewPager mViewPager;
+ private TabLayout mTabLayout;
+ private SliceView mSettingsSliceView;
+ private LiveData<Slice> mSettingsLiveData;
+ private View mSpacer;
+ private View mLoadingScrim;
+ private MaterialProgressDrawable mProgressDrawable;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ android.app.WallpaperInfo info = mWallpaper.getWallpaperComponent();
+ mWallpaperIntent = new Intent(WallpaperService.SERVICE_INTERFACE)
+ .setClassName(info.getPackageName(), info.getServiceName());
+ setUpExploreIntent(null);
+
+ android.app.WallpaperInfo currentWallpaper =
+ WallpaperManager.getInstance(requireContext()).getWallpaperInfo();
+ String deleteAction = getDeleteAction(info.getServiceInfo(),
+ (currentWallpaper == null) ? null : currentWallpaper.getServiceInfo());
+
+ if (!TextUtils.isEmpty(deleteAction)) {
+ mDeleteIntent = new Intent(deleteAction);
+ mDeleteIntent.setPackage(info.getPackageName());
+ mDeleteIntent.putExtra(EXTRA_LIVE_WALLPAPER_INFO, info);
+ }
+
+ String settingsActivity = info.getSettingsActivity();
+ if (settingsActivity != null) {
+ mSettingsIntent = new Intent();
+ mSettingsIntent.setComponent(new ComponentName(info.getPackageName(),
+ settingsActivity));
+ mSettingsIntent.putExtra(WallpaperSettingsActivity.EXTRA_PREVIEW_MODE, true);
+ PackageManager pm = requireContext().getPackageManager();
+ ActivityInfo activityInfo = mSettingsIntent.resolveActivityInfo(pm, 0);
+ if (activityInfo == null) {
+ Log.i(TAG, "Couldn't find wallpaper settings activity: " + settingsActivity);
+ mSettingsIntent = null;
+ }
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ mPages = new ArrayList<>();
+ View view = super.onCreateView(inflater, container, savedInstanceState);
+ if (view == null) {
+ return null;
+ }
+
+ Activity activity = requireActivity();
+
+ mLoadingScrim = view.findViewById(R.id.loading);
+ mLoadingIndicator = view.findViewById(R.id.loading_indicator);
+ setUpLoadingIndicator();
+
+ mWallpaperConnection = new WallpaperConnection(mWallpaperIntent, activity);
+ container.post(() -> {
+ if (!mWallpaperConnection.connect()) {
+ mWallpaperConnection = null;
+ }
+ });
+
+ return view;
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (mSettingsLiveData != null && mSettingsLiveData.hasObservers()) {
+ mSettingsLiveData.removeObserver(mSettingsSliceView);
+ mSettingsLiveData = null;
+ }
+ if (mWallpaperConnection != null) {
+ mWallpaperConnection.disconnect();
+ }
+ mWallpaperConnection = null;
+ super.onDestroy();
+ }
+
+ @Override
+ protected void setUpBottomSheetView(ViewGroup bottomSheet) {
+
+ initInfoPage();
+ initSettingsPage();
+
+ mViewPager = bottomSheet.findViewById(R.id.viewpager);
+ mTabLayout = bottomSheet.findViewById(R.id.tablayout);
+
+ // Create PagerAdapter
+ final PagerAdapter pagerAdapter = new PagerAdapter() {
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ final View page = mPages.get(position).second;
+ container.addView(page);
+ return page;
+ }
+
+ @Override
+ public void destroyItem(@NonNull ViewGroup container, int position,
+ @NonNull Object object) {
+ if (object instanceof View) {
+ container.removeView((View) object);
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return mPages.size();
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ try {
+ return mPages.get(position).first;
+ } catch (IndexOutOfBoundsException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
+ return (view == object);
+ }
+ };
+
+ // Add OnPageChangeListener to re-measure ViewPager's height
+ mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
+ @Override
+ public void onPageSelected(int position) {
+ mViewPager.requestLayout();
+ }
+ });
+
+ // Set PagerAdapter
+ mViewPager.setAdapter(pagerAdapter);
+
+ // Make TabLayout visible if there are more than one page
+ if (mPages.size() > 1) {
+ mTabLayout.setVisibility(View.VISIBLE);
+ mTabLayout.setupWithViewPager(mViewPager);
+ }
+ mViewPager.setCurrentItem(0);
+ }
+
+ private void setUpLoadingIndicator() {
+ Context context = requireContext();
+ mProgressDrawable = new MaterialProgressDrawable(context.getApplicationContext(),
+ mLoadingIndicator);
+ mProgressDrawable.setAlpha(255);
+ mProgressDrawable.setBackgroundColor(getResources().getColor(R.color.material_white_100,
+ context.getTheme()));
+ mProgressDrawable.setColorSchemeColors(getAttrColor(
+ new ContextThemeWrapper(context, getDeviceDefaultTheme()),
+ android.R.attr.colorAccent));
+ mProgressDrawable.updateSizes(MaterialProgressDrawable.LARGE);
+ mLoadingIndicator.setImageDrawable(mProgressDrawable);
+
+ // We don't want to show the spinner every time we load a wallpaper if it loads quickly;
+ // instead, only start showing the spinner after 100 ms
+ mLoadingIndicator.postDelayed(() -> {
+ if ((mWallpaperConnection == null || !mWallpaperConnection.isEngineReady())
+ && !mTestingModeEnabled) {
+ mLoadingIndicator.setVisibility(View.VISIBLE);
+ mLoadingIndicator.setAlpha(1f);
+ if (mProgressDrawable != null) {
+ mProgressDrawable.start();
+ }
+ }
+ }, 100);
+ }
+
+ private void initInfoPage() {
+ View pageInfo = getLayoutInflater().inflate(R.layout.preview_page_info, null /* root */);
+
+ mAttributionTitle = pageInfo.findViewById(R.id.preview_attribution_pane_title);
+ mAttributionSubtitle1 = pageInfo.findViewById(R.id.preview_attribution_pane_subtitle1);
+ mAttributionSubtitle2 = pageInfo.findViewById(R.id.preview_attribution_pane_subtitle2);
+ mSpacer = pageInfo.findViewById(R.id.spacer);
+
+ mExploreButton = pageInfo.findViewById(R.id.preview_attribution_pane_explore_button);
+ mSetWallpaperButton = pageInfo.findViewById(
+ R.id.preview_attribution_pane_set_wallpaper_button);
+
+ mPages.add(Pair.create(getString(R.string.tab_info), pageInfo));
+ }
+
+ private void initSettingsPage() {
+ final Uri uriSettingsSlice = getSettingsSliceUri(mWallpaper.getWallpaperComponent());
+ if (uriSettingsSlice == null) {
+ return;
+ }
+
+ final View pageSettings = getLayoutInflater().inflate(R.layout.preview_page_settings,
+ null /* root */);
+
+ mSettingsSliceView = pageSettings.findViewById(R.id.settings_slice);
+ mSettingsSliceView.setMode(SliceView.MODE_LARGE);
+ mSettingsSliceView.setScrollable(false);
+
+ // Set LiveData for SliceView
+ mSettingsLiveData = SliceLiveData.fromUri(requireContext() /* context */, uriSettingsSlice);
+ mSettingsLiveData.observeForever(mSettingsSliceView);
+
+ mPages.add(Pair.create(getResources().getString(R.string.tab_customize), pageSettings));
+ }
+
+ private void populateAttributionPane() {
+ final Context context = getContext();
+
+ final BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(mBottomSheet);
+
+ List<String> attributions = mWallpaper.getAttributions(context);
+ if (attributions.size() > 0 && attributions.get(0) != null) {
+ mAttributionTitle.setText(attributions.get(0));
+ }
+
+ if (mWallpaper.getWallpaperComponent().getShowMetadataInPreview()) {
+
+ if (attributions.size() > 1 && attributions.get(1) != null) {
+ mAttributionSubtitle1.setVisibility(View.VISIBLE);
+ mAttributionSubtitle1.setText(attributions.get(1));
+ }
+
+ if (attributions.size() > 2 && attributions.get(2) != null) {
+ mAttributionSubtitle2.setVisibility(View.VISIBLE);
+ mAttributionSubtitle2.setText(attributions.get(2));
+ }
+
+ } else {
+ mExploreIntent = null;
+ }
+
+ setUpSetWallpaperButton(mSetWallpaperButton);
+
+ setUpExploreButton(mExploreButton);
+
+ if (mExploreButton.getVisibility() == View.VISIBLE
+ && mSetWallpaperButton.getVisibility() == View.VISIBLE) {
+ mSpacer.setVisibility(View.VISIBLE);
+ } else {
+ mSpacer.setVisibility(View.GONE);
+ }
+
+ mBottomSheet.setVisibility(View.VISIBLE);
+
+ // Initialize the state of the BottomSheet based on the current state because if the initial
+ // and current state are the same, the state change listener won't fire and set the correct
+ // arrow asset and text alpha.
+ if (mBottomSheetInitialState == STATE_EXPANDED) {
+ setPreviewChecked(false);
+ mAttributionTitle.setAlpha(1f);
+ mAttributionSubtitle1.setAlpha(1f);
+ mAttributionSubtitle2.setAlpha(1f);
+ } else {
+ setPreviewChecked(true);
+ mAttributionTitle.setAlpha(0f);
+ mAttributionSubtitle1.setAlpha(0f);
+ mAttributionSubtitle2.setAlpha(0f);
+ }
+
+ bottomSheetBehavior.setState(mBottomSheetInitialState);
+ }
+
+ @SuppressLint("NewApi") //Already checking with isAtLeastQ
+ private Uri getSettingsSliceUri(android.app.WallpaperInfo info) {
+ if (BuildCompat.isAtLeastQ()) {
+ return info.getSettingsSliceUri();
+ }
+ return null;
+ }
+
+ @Override
+ protected int getLayoutResId() {
+ return R.layout.fragment_live_preview;
+ }
+
+ @Override
+ protected int getBottomSheetResId() {
+ return R.id.bottom_sheet;
+ }
+
+ @Override
+ protected void setCurrentWallpaper(int destination) {
+ mWallpaperSetter.setCurrentWallpaper(getActivity(), mWallpaper, null,
+ destination, 0, null, new SetWallpaperCallback() {
+ @Override
+ public void onSuccess() {
+ finishActivityWithResultOk();
+ }
+
+ @Override
+ public void onError(@Nullable Throwable throwable) {
+ showSetWallpaperErrorDialog(destination);
+ }
+ });
+ }
+
+ @Override
+ protected void setBottomSheetContentAlpha(float alpha) {
+ mExploreButton.setAlpha(alpha);
+ mAttributionTitle.setAlpha(alpha);
+ mAttributionSubtitle1.setAlpha(alpha);
+ mAttributionSubtitle2.setAlpha(alpha);
+ }
+
+ @Override
+ protected void setUpExploreButton(Button exploreButton) {
+ super.setUpExploreButton(exploreButton);
+ if (exploreButton.getVisibility() != View.VISIBLE) {
+ return;
+ }
+ Context context = requireContext();
+ CharSequence exploreLabel = ((LiveWallpaperInfo) mWallpaper).getActionDescription(context);
+ if (!TextUtils.isEmpty(exploreLabel)) {
+ exploreButton.setText(exploreLabel);
+ }
+ }
+
+ @Nullable
+ private String getDeleteAction(ServiceInfo serviceInfo,
+ @Nullable ServiceInfo currentService) {
+ if (!isPackagePreInstalled(serviceInfo.applicationInfo)) {
+ Log.d(TAG, "This wallpaper is not pre-installed: " + serviceInfo.name);
+ return null;
+ }
+
+ // A currently set Live wallpaper should not be deleted.
+ if (currentService != null && TextUtils.equals(serviceInfo.name, currentService.name)) {
+ return null;
+ }
+
+ final Bundle metaData = serviceInfo.metaData;
+ if (metaData != null) {
+ return metaData.getString(KEY_ACTION_DELETE_LIVE_WALLPAPER);
+ }
+ return null;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mWallpaperConnection != null) {
+ mWallpaperConnection.setVisibility(true);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mWallpaperConnection != null) {
+ mWallpaperConnection.setVisibility(false);
+ }
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ menu.findItem(R.id.configure).setVisible(mSettingsIntent != null);
+ menu.findItem(R.id.delete_wallpaper).setVisible(mDeleteIntent != null);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == R.id.configure) {
+ if (getActivity() != null) {
+ startActivity(mSettingsIntent);
+ return true;
+ }
+ } else if (id == R.id.delete_wallpaper) {
+ showDeleteConfirmDialog();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void showDeleteConfirmDialog() {
+ final AlertDialog alertDialog = new AlertDialog.Builder(
+ new ContextThemeWrapper(getContext(), getDeviceDefaultTheme()))
+ .setMessage(R.string.delete_wallpaper_confirmation)
+ .setPositiveButton(R.string.delete_live_wallpaper,
+ (dialog, which) -> deleteLiveWallpaper())
+ .setNegativeButton(android.R.string.cancel, null /* listener */)
+ .create();
+ alertDialog.show();
+ }
+
+ private void deleteLiveWallpaper() {
+ if (mDeleteIntent != null) {
+ requireContext().startService(mDeleteIntent);
+ finishActivityWithResultOk();
+ }
+ }
+
+ private boolean isPackagePreInstalled(ApplicationInfo info) {
+ if (info != null && (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ return true;
+ }
+ return false;
+ }
+
+ private class WallpaperConnection extends IWallpaperConnection.Stub
+ implements ServiceConnection {
+ private final Activity mActivity;
+ private final Intent mIntent;
+ private IWallpaperService mService;
+ private IWallpaperEngine mEngine;
+ private boolean mConnected;
+ private boolean mIsVisible;
+ private boolean mIsEngineVisible;
+ private boolean mEngineReady;
+
+ WallpaperConnection(Intent intent, Activity activity) {
+ mActivity = activity;
+ mIntent = intent;
+ }
+
+ public boolean connect() {
+ synchronized (this) {
+ if (!mActivity.bindService(mIntent, this, Context.BIND_AUTO_CREATE)) {
+ return false;
+ }
+
+ mConnected = true;
+ return true;
+ }
+ }
+
+ public void disconnect() {
+ synchronized (this) {
+ mConnected = false;
+ if (mEngine != null) {
+ try {
+ mEngine.destroy();
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ mEngine = null;
+ }
+ try {
+ mActivity.unbindService(this);
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, "Can't unbind wallpaper service. "
+ + "It might have crashed, just ignoring.", e);
+ }
+ mService = null;
+ }
+ }
+
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (mWallpaperConnection == this) {
+ mService = IWallpaperService.Stub.asInterface(service);
+ try {
+ View root = mActivity.getWindow().getDecorView();
+ int displayId = root.getDisplay().getDisplayId();
+ mService.attach(this, root.getWindowToken(),
+ LayoutParams.TYPE_APPLICATION_MEDIA,
+ true, root.getWidth(), root.getHeight(),
+ new Rect(0, 0, 0, 0), displayId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed attaching wallpaper; clearing", e);
+ }
+ }
+ }
+
+ public void onServiceDisconnected(ComponentName name) {
+ mService = null;
+ mEngine = null;
+ if (mWallpaperConnection == this) {
+ Log.w(TAG, "Wallpaper service gone: " + name);
+ }
+ }
+
+ public void attachEngine(IWallpaperEngine engine, int displayId) {
+ synchronized (this) {
+ if (mConnected) {
+ mEngine = engine;
+ if (mIsVisible) {
+ setEngineVisibility(true);
+ }
+ } else {
+ try {
+ engine.destroy();
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
+ public ParcelFileDescriptor setWallpaper(String name) {
+ return null;
+ }
+
+ @Override
+ public void onWallpaperColorsChanged(WallpaperColors colors, int displayId)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void engineShown(IWallpaperEngine engine) {
+ mLoadingScrim.post(() -> {
+ mLoadingScrim.animate()
+ .alpha(0f)
+ .setDuration(220)
+ .setStartDelay(300)
+ .setInterpolator(AnimationUtils.loadInterpolator(mActivity,
+ android.R.interpolator.fast_out_linear_in))
+ .withEndAction(() -> {
+ if (mLoadingIndicator != null) {
+ mLoadingIndicator.setVisibility(View.GONE);
+ }
+ if (mProgressDrawable != null) {
+ mProgressDrawable.stop();
+ }
+ mLoadingScrim.setVisibility(View.INVISIBLE);
+ populateAttributionPane();
+ });
+ });
+ mEngineReady = true;
+ }
+
+ public boolean isEngineReady() {
+ return mEngineReady;
+ }
+
+ public void setVisibility(boolean visible) {
+ mIsVisible = visible;
+ setEngineVisibility(visible);
+ }
+
+ private void setEngineVisibility(boolean visible) {
+ if (mEngine != null && visible != mIsEngineVisible) {
+ try {
+ mEngine.setVisibility(visible);
+ mIsEngineVisible = visible;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failure setting wallpaper visibility ", e);
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/android/wallpaper/picker/PreviewFragment.java b/src/com/android/wallpaper/picker/PreviewFragment.java
index c698c8c..f1a1625 100755
--- a/src/com/android/wallpaper/picker/PreviewFragment.java
+++ b/src/com/android/wallpaper/picker/PreviewFragment.java
@@ -18,46 +18,33 @@ package com.android.wallpaper.picker;
import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED;
import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Color;
-import android.graphics.Point;
-import android.graphics.PointF;
import android.graphics.PorterDuff.Mode;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
-import android.view.ContextThemeWrapper;
-import android.view.Display;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.CheckBox;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
import android.widget.Toast;
+import androidx.annotation.CallSuper;
+import androidx.annotation.IdRes;
import androidx.annotation.IntDef;
+import androidx.annotation.LayoutRes;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
@@ -66,9 +53,6 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import com.android.wallpaper.R;
-import com.android.wallpaper.asset.Asset;
-import com.android.wallpaper.asset.Asset.BitmapReceiver;
-import com.android.wallpaper.asset.Asset.DimensionsReceiver;
import com.android.wallpaper.compat.BuildCompat;
import com.android.wallpaper.model.LiveWallpaperInfo;
import com.android.wallpaper.model.WallpaperInfo;
@@ -76,19 +60,10 @@ import com.android.wallpaper.module.ExploreIntentChecker;
import com.android.wallpaper.module.Injector;
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.module.UserEventLogger;
-import com.android.wallpaper.module.WallpaperPersister;
import com.android.wallpaper.module.WallpaperPersister.Destination;
-import com.android.wallpaper.module.WallpaperPersister.SetWallpaperCallback;
import com.android.wallpaper.module.WallpaperPreferences;
import com.android.wallpaper.module.WallpaperSetter;
-import com.android.wallpaper.util.ScreenSizeCalculator;
-import com.android.wallpaper.util.WallpaperCropUtils;
-import com.android.wallpaper.widget.MaterialProgressDrawable;
-
-import com.bumptech.glide.Glide;
-import com.bumptech.glide.MemoryCategory;
-import com.davemorrissey.labs.subscaleview.ImageSource;
-import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetBehavior.State;
@@ -96,23 +71,22 @@ import java.util.Date;
import java.util.List;
/**
- * Fragment which displays the UI for previewing an individual wallpaper and its attribution
- * information.
+ * Base Fragment to display the UI for previewing an individual wallpaper
*/
-public class PreviewFragment extends Fragment implements
+public abstract class PreviewFragment extends Fragment implements
SetWallpaperDialogFragment.Listener, SetWallpaperErrorDialogFragment.Listener,
LoadWallpaperErrorDialogFragment.Listener {
/**
* User can view wallpaper and attributions in full screen, but "Set wallpaper" button is hidden.
*/
- public static final int MODE_VIEW_ONLY = 0;
+ static final int MODE_VIEW_ONLY = 0;
/**
* User can view wallpaper and attributions in full screen and click "Set wallpaper" to set the
* wallpaper with pan and crop position to the device.
*/
- public static final int MODE_CROP_AND_SET_WALLPAPER = 1;
+ static final int MODE_CROP_AND_SET_WALLPAPER = 1;
/**
* Possible preview modes for the fragment.
@@ -126,52 +100,56 @@ public class PreviewFragment extends Fragment implements
public static final String ARG_WALLPAPER = "wallpaper";
public static final String ARG_PREVIEW_MODE = "preview_mode";
public static final String ARG_TESTING_MODE_ENABLED = "testing_mode_enabled";
+
+ /**
+ * Creates and returns new instance of {@link ImagePreviewFragment} with the provided wallpaper
+ * set as an argument.
+ */
+ public static PreviewFragment newInstance(
+ WallpaperInfo wallpaperInfo, @PreviewMode int mode, boolean testingModeEnabled) {
+
+ boolean isLive = wallpaperInfo instanceof LiveWallpaperInfo;
+
+ Bundle args = new Bundle();
+ args.putParcelable(ARG_WALLPAPER, wallpaperInfo);
+ args.putInt(ARG_PREVIEW_MODE, mode);
+ args.putBoolean(ARG_TESTING_MODE_ENABLED, testingModeEnabled);
+
+ PreviewFragment fragment = isLive ? new LivePreviewFragment() : new ImagePreviewFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
private static final String TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT =
"load_wallpaper_error_dialog";
private static final String TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT =
"set_wallpaper_error_dialog";
private static final int UNUSED_REQUEST_CODE = 1;
- private static final float DEFAULT_WALLPAPER_MAX_ZOOM = 8f;
private static final String TAG = "PreviewFragment";
- private static final float PAGE_BITMAP_MAX_HEAP_RATIO = 0.25f;
- private static final String KEY_BOTTOM_SHEET_STATE = "key_bottom_sheet_state";
+ static final String KEY_BOTTOM_SHEET_STATE = "key_bottom_sheet_state";
@PreviewMode
- private int mPreviewMode;
+ protected int mPreviewMode;
/**
* When true, enables a test mode of operation -- in which certain UI features are disabled to
* allow for UI tests to run correctly. Works around issue in ProgressDialog currently where the
* dialog constantly keeps the UI thread alive and blocks a test forever.
*/
- private boolean mTestingModeEnabled;
+ protected boolean mTestingModeEnabled;
- protected SubsamplingScaleImageView mFullResImageView;
protected WallpaperInfo mWallpaper;
- private Asset mWallpaperAsset;
- private WallpaperSetter mWallpaperSetter;
- private UserEventLogger mUserEventLogger;
- private LinearLayout mBottomSheet;
- private TextView mAttributionTitle;
- private TextView mAttributionSubtitle1;
- private TextView mAttributionSubtitle2;
- private Button mAttributionExploreButton;
- private int mCurrentScreenOrientation;
- private Point mDefaultCropSurfaceSize;
- private Point mScreenSize;
- private Point mRawWallpaperSize; // Native size of wallpaper image.
- private ImageView mLoadingIndicator;
- private MaterialProgressDrawable mProgressDrawable;
- private ImageView mLowResImageView;
- private Button mSetWallpaperButton;
- private View mSpacer;
- private CheckBox mPreview;
+ protected WallpaperSetter mWallpaperSetter;
+ protected UserEventLogger mUserEventLogger;
+ protected ViewGroup mBottomSheet;
+
+ protected CheckBox mPreview;
@SuppressWarnings("RestrictTo")
@State
- private int mBottomSheetInitialState;
+ protected int mBottomSheetInitialState;
- private Intent mExploreIntent;
+ protected Intent mExploreIntent;
/**
* Staged error dialog fragments that were unable to be shown when the hosting activity didn't
@@ -180,23 +158,7 @@ public class PreviewFragment extends Fragment implements
private SetWallpaperErrorDialogFragment mStagedSetWallpaperErrorDialogFragment;
private LoadWallpaperErrorDialogFragment mStagedLoadWallpaperErrorDialogFragment;
- /**
- * Creates and returns new instance of {@link PreviewFragment} with the provided wallpaper set as
- * an argument.
- */
- public static PreviewFragment newInstance(
- WallpaperInfo wallpaperInfo, @PreviewMode int mode, boolean testingModeEnabled) {
- Bundle args = new Bundle();
- args.putParcelable(ARG_WALLPAPER, wallpaperInfo);
- args.putInt(ARG_PREVIEW_MODE, mode);
- args.putBoolean(ARG_TESTING_MODE_ENABLED, testingModeEnabled);
-
- PreviewFragment fragment = new PreviewFragment();
- fragment.setArguments(args);
- return fragment;
- }
-
- private static int getAttrColor(Context context, int attr) {
+ protected static int getAttrColor(Context context, int attr) {
TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
int colorAccent = ta.getColor(0, 0);
ta.recycle();
@@ -208,12 +170,12 @@ public class PreviewFragment extends Fragment implements
super.onCreate(savedInstanceState);
Activity activity = getActivity();
- Context appContext = activity.getApplicationContext();
+ Context appContext = getContext().getApplicationContext();
Injector injector = InjectorProvider.getInjector();
mUserEventLogger = injector.getUserEventLogger(appContext);
mWallpaper = getArguments().getParcelable(ARG_WALLPAPER);
- mWallpaperAsset = mWallpaper.getAsset(appContext);
+
//noinspection ResourceType
mPreviewMode = getArguments().getInt(ARG_PREVIEW_MODE);
mTestingModeEnabled = getArguments().getBoolean(ARG_TESTING_MODE_ENABLED);
@@ -236,14 +198,18 @@ public class PreviewFragment extends Fragment implements
}
}
+ @LayoutRes
+ protected abstract int getLayoutResId();
+
@Override
+ @CallSuper
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.fragment_preview, container, false);
+ View view = inflater.inflate(getLayoutResId(), container, false);
// Set toolbar as the action bar.
Toolbar toolbar = view.findViewById(R.id.toolbar);
- AppCompatActivity activity = (AppCompatActivity) getActivity();
+ AppCompatActivity activity = (AppCompatActivity) requireActivity();
activity.setSupportActionBar(toolbar);
activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
activity.getSupportActionBar().setDisplayShowTitleEnabled(false);
@@ -270,18 +236,8 @@ public class PreviewFragment extends Fragment implements
R.dimen.preview_toolbar_set_wallpaper_button_end_padding),
/* bottom */ 0);
- mFullResImageView = view.findViewById(R.id.full_res_image);
- mLoadingIndicator = view.findViewById(R.id.loading_indicator);
-
- mBottomSheet = view.findViewById(R.id.bottom_sheet);
- mAttributionTitle = view.findViewById(R.id.preview_attribution_pane_title);
- mAttributionSubtitle1 = view.findViewById(R.id.preview_attribution_pane_subtitle1);
- mAttributionSubtitle2 = view.findViewById(R.id.preview_attribution_pane_subtitle2);
- mAttributionExploreButton = view.findViewById(
- R.id.preview_attribution_pane_explore_button);
- mLowResImageView = view.findViewById(R.id.low_res_image);
- mSetWallpaperButton = view.findViewById(R.id.preview_attribution_pane_set_wallpaper_button);
- mSpacer = view.findViewById(R.id.spacer);
+ mBottomSheet = view.findViewById(getBottomSheetResId());
+ setUpBottomSheetView(mBottomSheet);
// Workaround as we don't have access to bottomDialogCornerRadius, mBottomSheet radii are
// set to dialogCornerRadius by default.
@@ -294,93 +250,18 @@ public class PreviewFragment extends Fragment implements
bottomSheetBackground.setCornerRadii(radii);
mBottomSheet.setBackground(bottomSheetBackground);
- // Trim some memory from Glide to make room for the full-size image in this fragment.
- Glide.get(getActivity()).setMemoryCategory(MemoryCategory.LOW);
-
- mDefaultCropSurfaceSize = WallpaperCropUtils.getDefaultCropSurfaceSize(
- getResources(), getActivity().getWindowManager().getDefaultDisplay());
- mScreenSize = ScreenSizeCalculator.getInstance().getScreenSize(
- getActivity().getWindowManager().getDefaultDisplay());
-
- // Load a low-res placeholder image if there's a thumbnail available from the asset that can be
- // shown to the user more quickly than the full-sized image.
- if (mWallpaperAsset.hasLowResDataSource()) {
- mWallpaperAsset.loadLowResDrawable(getActivity(), mLowResImageView, Color.BLACK,
- new WallpaperPreviewBitmapTransformation(getActivity().getApplicationContext(),
- isRtl()));
- }
-
- mWallpaperAsset.decodeRawDimensions(getActivity(), new DimensionsReceiver() {
- @Override
- public void onDimensionsDecoded(Point dimensions) {
- // Don't continue loading the wallpaper if the Fragment is detached.
- Activity activity = getActivity();
- if (activity == null) {
- return;
- }
-
- // Return early and show a dialog if dimensions are null (signaling a decoding error).
- if (dimensions == null) {
- showLoadWallpaperErrorDialog();
- return;
- }
-
- mRawWallpaperSize = dimensions;
- ExploreIntentChecker intentChecker =
- InjectorProvider.getInjector().getExploreIntentChecker(activity);
- String actionUrl = mWallpaper.getActionUrl(activity);
- if (actionUrl != null && !actionUrl.isEmpty()) {
- Uri exploreUri = Uri.parse(mWallpaper.getActionUrl(activity));
-
- intentChecker.fetchValidActionViewIntent(exploreUri, exploreIntent -> {
- if (getActivity() == null) {
- return;
- }
-
- mExploreIntent = exploreIntent;
- initFullResView();
- });
- } else {
- initFullResView();
- }
- }
- });
-
- // Configure loading indicator with a MaterialProgressDrawable.
- mProgressDrawable = new MaterialProgressDrawable(getActivity().getApplicationContext(),
- mLoadingIndicator);
- mProgressDrawable.setAlpha(255);
- mProgressDrawable.setBackgroundColor(getResources().getColor(R.color.material_white_100,
- getContext().getTheme()));
- mProgressDrawable.setColorSchemeColors(getAttrColor(
- new ContextThemeWrapper(getContext(), getDeviceDefaultTheme()),
- android.R.attr.colorAccent));
- mProgressDrawable.updateSizes(MaterialProgressDrawable.LARGE);
- mLoadingIndicator.setImageDrawable(mProgressDrawable);
-
- // We don't want to show the spinner every time we load an image if it loads quickly; instead,
- // only start showing the spinner if loading the image has taken longer than half of a second.
- mLoadingIndicator.postDelayed(() -> {
- if (mFullResImageView != null && !mFullResImageView.hasImage()
- && !mTestingModeEnabled) {
- mLoadingIndicator.setVisibility(View.VISIBLE);
- mLoadingIndicator.setAlpha(1f);
- if (mProgressDrawable != null) {
- mProgressDrawable.start();
- }
- }
- }, 500);
-
-
- mBottomSheetInitialState = (savedInstanceState == null)
- ? STATE_EXPANDED
- : savedInstanceState.getInt(KEY_BOTTOM_SHEET_STATE,
- STATE_EXPANDED);
+ mBottomSheetInitialState = (savedInstanceState == null) ? STATE_EXPANDED
+ : savedInstanceState.getInt(KEY_BOTTOM_SHEET_STATE, STATE_EXPANDED);
setUpBottomSheetListeners();
return view;
}
+ protected abstract void setUpBottomSheetView(ViewGroup bottomSheet);
+
+ @IdRes
+ protected abstract int getBottomSheetResId();
+
protected int getDeviceDefaultTheme() {
return android.R.style.Theme_DeviceDefault;
}
@@ -398,12 +279,12 @@ public class PreviewFragment extends Fragment implements
// allow committing fragment transactions.
if (mStagedLoadWallpaperErrorDialogFragment != null) {
mStagedLoadWallpaperErrorDialogFragment.show(
- getFragmentManager(), TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT);
+ requireFragmentManager(), TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT);
mStagedLoadWallpaperErrorDialogFragment = null;
}
if (mStagedSetWallpaperErrorDialogFragment != null) {
mStagedSetWallpaperErrorDialogFragment.show(
- getFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
+ requireFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
mStagedSetWallpaperErrorDialogFragment = null;
}
}
@@ -428,20 +309,20 @@ public class PreviewFragment extends Fragment implements
// the IndividualPreviewActivity, the "My photos" selection (by way of
// TopLevelPickerActivity), or from a system "crop and set wallpaper" intent.
// Therefore, handle the Up button as a global Back.
- getActivity().onBackPressed();
+ requireActivity().onBackPressed();
return true;
}
return false;
}
- protected void setupPreviewMenu(Menu menu) {
+ private void setupPreviewMenu(Menu menu) {
mPreview = (CheckBox) menu.findItem(R.id.preview).getActionView();
mPreview.setChecked(mBottomSheetInitialState == STATE_COLLAPSED);
mPreview.setOnClickListener(this::setPreviewBehavior);
}
- private void setPreviewChecked(boolean checked) {
+ protected void setPreviewChecked(boolean checked) {
if (mPreview != null) {
mPreview.setChecked(checked);
int resId = checked ? R.string.expand_attribution_panel
@@ -450,7 +331,7 @@ public class PreviewFragment extends Fragment implements
}
}
- private void setPreviewBehavior(final View v) {
+ private void setPreviewBehavior(View v) {
CheckBox checkbox = (CheckBox) v;
BottomSheetBehavior<?> behavior = BottomSheetBehavior.from(mBottomSheet);
@@ -461,6 +342,61 @@ public class PreviewFragment extends Fragment implements
}
}
+ protected void setUpSetWallpaperButton(Button setWallpaperButton) {
+ if (mPreviewMode == MODE_VIEW_ONLY) {
+ setWallpaperButton.setVisibility(View.GONE);
+ } else {
+ setWallpaperButton.setVisibility(View.VISIBLE);
+ setWallpaperButton.setOnClickListener(this::onSetWallpaperClicked);
+ }
+ }
+
+ protected void setUpExploreButton(Button exploreButton) {
+ exploreButton.setVisibility(View.GONE);
+ if (mExploreIntent == null) {
+ return;
+ }
+ Context context = requireContext();
+ exploreButton.setVisibility(View.VISIBLE);
+ exploreButton.setText(context.getString(
+ mWallpaper.getActionLabelRes(context)));
+
+ exploreButton.setOnClickListener(view -> {
+ mUserEventLogger.logActionClicked(mWallpaper.getCollectionId(context),
+ mWallpaper.getActionLabelRes(context));
+
+ startActivity(mExploreIntent);
+ });
+ }
+
+ protected void setUpExploreIntent(@Nullable Runnable callback) {
+ Context context = getContext();
+ if (context == null) {
+ return;
+ }
+ String actionUrl = mWallpaper.getActionUrl(context);
+ if (actionUrl != null && !actionUrl.isEmpty()) {
+ Uri exploreUri = Uri.parse(mWallpaper.getActionUrl(context));
+ ExploreIntentChecker intentChecker =
+ InjectorProvider.getInjector().getExploreIntentChecker(context);
+
+ intentChecker.fetchValidActionViewIntent(exploreUri, exploreIntent -> {
+ if (getActivity() == null) {
+ return;
+ }
+
+ mExploreIntent = exploreIntent;
+ if (callback != null) {
+ callback.run();
+ }
+ });
+ } else {
+ if (callback != null) {
+ callback.run();
+ }
+ }
+ }
+
@Override
public void onSet(int destination) {
setCurrentWallpaper(destination);
@@ -483,10 +419,6 @@ public class PreviewFragment extends Fragment implements
public void onDestroy() {
super.onDestroy();
mWallpaperSetter.cleanUp();
- if (mProgressDrawable != null) {
- mProgressDrawable.stop();
- }
- mFullResImageView.recycle();
}
@Override
@@ -498,41 +430,8 @@ public class PreviewFragment extends Fragment implements
}
private void onSetWallpaperClicked(View button) {
- if (BuildCompat.isAtLeastN()) {
- mWallpaperSetter.requestDestination(getContext(), getFragmentManager(), this,
- mWallpaper instanceof LiveWallpaperInfo);
- } else {
- setCurrentWallpaper(WallpaperPersister.DEST_HOME_SCREEN);
- }
- }
-
- /**
- * Returns a zoom level that is similar to the actual zoom, but that is exactly 0.5 ** n for some
- * integer n. This is useful for downsampling a bitmap--we want to see the bitmap at full detail,
- * or downsampled to 1 in every 2 pixels, or 1 in 4, and so on, depending on the zoom.
- */
- private static float getDownsampleZoom(float actualZoom) {
- if (actualZoom > 1) {
- // Very zoomed in, but we can't sample more than 1 pixel per pixel.
- return 1.0f;
- }
- float lower = 1.0f / roundUpToPower2((int) Math.ceil(1 / actualZoom));
- float upper = lower * 2;
- return nearestValue(actualZoom, lower, upper);
- }
-
- /**
- * Returns the integer rounded up to the next power of 2.
- */
- private static int roundUpToPower2(int value) {
- return 1 << (32 - Integer.numberOfLeadingZeros(value - 1));
- }
-
- /**
- * Returns the closer of two values a and b to the given value.
- */
- private static float nearestValue(float value, float a, float b) {
- return Math.abs(a - value) < Math.abs(b - value) ? a : b;
+ mWallpaperSetter.requestDestination(getContext(), getFragmentManager(), this,
+ mWallpaper instanceof LiveWallpaperInfo);
}
private void setUpBottomSheetListeners() {
@@ -554,6 +453,8 @@ public class PreviewFragment extends Fragment implements
case STATE_EXPANDED:
setPreviewChecked(false /* checked */);
break;
+ default:
+ Log.v(TAG, "Ignoring BottomSheet state: " + newState);
}
}
@@ -565,264 +466,13 @@ public class PreviewFragment extends Fragment implements
} else {
alpha = 1f - slideOffset;
}
- mAttributionTitle.setAlpha(alpha);
- mAttributionSubtitle1.setAlpha(alpha);
- mAttributionSubtitle2.setAlpha(alpha);
- mAttributionExploreButton.setAlpha(alpha);
+ setBottomSheetContentAlpha(alpha);
}
});
}
- private boolean isWallpaperLoaded() {
- return mFullResImageView.hasImage();
- }
-
- private void populateAttributionPane() {
- final Context context = getContext();
-
- final BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(mBottomSheet);
-
- List<String> attributions = mWallpaper.getAttributions(context);
- if (attributions.size() > 0 && attributions.get(0) != null) {
- mAttributionTitle.setText(attributions.get(0));
- }
-
- if (attributions.size() > 1 && attributions.get(1) != null) {
- mAttributionSubtitle1.setVisibility(View.VISIBLE);
- mAttributionSubtitle1.setText(attributions.get(1));
- }
-
- if (attributions.size() > 2 && attributions.get(2) != null) {
- mAttributionSubtitle2.setVisibility(View.VISIBLE);
- mAttributionSubtitle2.setText(attributions.get(2));
- }
-
- if (mPreviewMode == MODE_CROP_AND_SET_WALLPAPER) {
- mSetWallpaperButton.setVisibility(View.VISIBLE);
- mSetWallpaperButton.setOnClickListener(this::onSetWallpaperClicked);
- } else {
- mSetWallpaperButton.setVisibility(View.GONE);
- }
-
- String actionUrl = mWallpaper.getActionUrl(context);
-
- mAttributionExploreButton.setVisibility(View.GONE);
- if (actionUrl != null && !actionUrl.isEmpty()) {
- if (mExploreIntent != null) {
- mAttributionExploreButton.setVisibility(View.VISIBLE);
- mAttributionExploreButton.setText(context.getString(
- mWallpaper.getActionLabelRes(context)));
-
- mAttributionExploreButton.setOnClickListener(view -> {
- mUserEventLogger.logActionClicked(mWallpaper.getCollectionId(context),
- mWallpaper.getActionLabelRes(context));
-
- startActivity(mExploreIntent);
- });
- }
- }
-
- if (mAttributionExploreButton.getVisibility() == View.VISIBLE
- && mSetWallpaperButton.getVisibility() == View.VISIBLE) {
- mSpacer.setVisibility(View.VISIBLE);
- } else {
- mSpacer.setVisibility(View.GONE);
- }
-
- mBottomSheet.setVisibility(View.VISIBLE);
-
- // Initialize the state of the BottomSheet based on the current state because if the initial
- // and current state are the same, the state change listener won't fire and set the correct
- // arrow asset and text alpha.
- if (bottomSheetBehavior.getState() == STATE_EXPANDED) {
- setPreviewChecked(false);
- mAttributionTitle.setAlpha(1f);
- mAttributionSubtitle1.setAlpha(1f);
- mAttributionSubtitle2.setAlpha(1f);
- } else {
- setPreviewChecked(true);
- mAttributionTitle.setAlpha(0f);
- mAttributionSubtitle1.setAlpha(0f);
- mAttributionSubtitle2.setAlpha(0f);
- }
-
- // Let the state change listener take care of animating a state change to the initial state
- // if there's a state change.
- bottomSheetBehavior.setState(mBottomSheetInitialState);
- }
-
- /**
- * Initializes MosaicView by initializing tiling, setting a fallback page bitmap, and
- * initializing a zoom-scroll observer and click listener.
- */
- private void initFullResView() {
- mFullResImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
-
- // Set a solid black "page bitmap" so MosaicView draws a black background while waiting
- // for the image to load or a transparent one if a thumbnail already loaded.
- Bitmap blackBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- int color = (mLowResImageView.getDrawable() == null) ? Color.BLACK : Color.TRANSPARENT;
- blackBitmap.setPixel(0, 0, color);
- mFullResImageView.setImage(ImageSource.bitmap(blackBitmap));
-
- // Then set a fallback "page bitmap" to cover the whole MosaicView, which is an actual
- // (lower res) version of the image to be displayed.
- Point targetPageBitmapSize = new Point(mRawWallpaperSize);
- mWallpaperAsset.decodeBitmap(targetPageBitmapSize.x, targetPageBitmapSize.y,
- new BitmapReceiver() {
- @Override
- public void onBitmapDecoded(Bitmap pageBitmap) {
- // Check that the activity is still around since the decoding task started.
- if (getActivity() == null) {
- return;
- }
-
- // Some of these may be null depending on if the Fragment is paused, stopped,
- // or destroyed.
- if (mLoadingIndicator != null) {
- mLoadingIndicator.setVisibility(View.GONE);
- }
- // The page bitmap may be null if there was a decoding error, so show an
- // error dialog.
- if (pageBitmap == null) {
- showLoadWallpaperErrorDialog();
- return;
- }
- if (mFullResImageView != null) {
- // Set page bitmap.
- mFullResImageView.setImage(ImageSource.bitmap(pageBitmap));
-
- setDefaultWallpaperZoomAndScroll();
- crossFadeInMosaicView();
- }
- if (mProgressDrawable != null) {
- mProgressDrawable.stop();
- }
- getActivity().invalidateOptionsMenu();
-
- populateAttributionPane();
- }
- });
- }
+ protected void setBottomSheetContentAlpha(float alpha) {
- /**
- * Makes the MosaicView visible with an alpha fade-in animation while fading out the loading
- * indicator.
- */
- private void crossFadeInMosaicView() {
- long shortAnimationDuration = getResources().getInteger(
- android.R.integer.config_shortAnimTime);
-
- mFullResImageView.setAlpha(0f);
- mFullResImageView.animate()
- .alpha(1f)
- .setDuration(shortAnimationDuration)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- // Clear the thumbnail bitmap reference to save memory since it's no longer
- // visible.
- if (mLowResImageView != null) {
- mLowResImageView.setImageBitmap(null);
- }
- }
- });
-
- mLoadingIndicator.animate()
- .alpha(0f)
- .setDuration(shortAnimationDuration)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mLoadingIndicator != null) {
- mLoadingIndicator.setVisibility(View.GONE);
- }
- }
- });
- }
-
- /**
- * Sets the default wallpaper zoom and scroll position based on a "crop surface"
- * (with extra width to account for parallax) superimposed on the screen. Shows as much of the
- * wallpaper as possible on the crop surface and align screen to crop surface such that the
- * default preview matches what would be seen by the user in the left-most home screen.
- *
- * <p>This method is called once in the Fragment lifecycle after the wallpaper asset has loaded
- * and rendered to the layout.
- */
- private void setDefaultWallpaperZoomAndScroll() {
- // Determine minimum zoom to fit maximum visible area of wallpaper on crop surface.
- float defaultWallpaperZoom =
- WallpaperCropUtils.calculateMinZoom(mRawWallpaperSize, mDefaultCropSurfaceSize);
- float minWallpaperZoom =
- WallpaperCropUtils.calculateMinZoom(mRawWallpaperSize, mScreenSize);
-
- Point screenToCropSurfacePosition = WallpaperCropUtils.calculateCenterPosition(
- mDefaultCropSurfaceSize, mScreenSize, true /* alignStart */, isRtl());
- Point zoomedWallpaperSize = new Point(
- Math.round(mRawWallpaperSize.x * defaultWallpaperZoom),
- Math.round(mRawWallpaperSize.y * defaultWallpaperZoom));
- Point cropSurfaceToWallpaperPosition = WallpaperCropUtils.calculateCenterPosition(
- zoomedWallpaperSize, mDefaultCropSurfaceSize, false /* alignStart */, isRtl());
-
- // Set min wallpaper zoom and max zoom on MosaicView widget.
- mFullResImageView.setMaxScale(Math.max(DEFAULT_WALLPAPER_MAX_ZOOM, defaultWallpaperZoom));
- mFullResImageView.setMinScale(minWallpaperZoom);
-
- // Set center to composite positioning between scaled wallpaper and screen.
- PointF centerPosition = new PointF(
- mRawWallpaperSize.x / 2f,
- mRawWallpaperSize.y / 2f);
- centerPosition.offset( - (screenToCropSurfacePosition.x + cropSurfaceToWallpaperPosition.x),
- - (screenToCropSurfacePosition.y + cropSurfaceToWallpaperPosition.y));
-
- mFullResImageView.setScaleAndCenter(minWallpaperZoom, centerPosition);
- }
-
- protected Rect calculateCropRect() {
- // Calculate Rect of wallpaper in physical pixel terms (i.e., scaled to current zoom).
- float wallpaperZoom = mFullResImageView.getScale();
- int scaledWallpaperWidth = (int) (mRawWallpaperSize.x * wallpaperZoom);
- int scaledWallpaperHeight = (int) (mRawWallpaperSize.y * wallpaperZoom);
- Rect rect = new Rect();
- mFullResImageView.visibleFileRect(rect);
- int scrollX = (int) (rect.left * wallpaperZoom);
- int scrollY = (int) (rect.top * wallpaperZoom);
-
- rect.set(0, 0, scaledWallpaperWidth, scaledWallpaperHeight);
- Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(
- getActivity().getWindowManager().getDefaultDisplay());
- // Crop rect should start off as the visible screen and then include extra width and height
- // if available within wallpaper at the current zoom.
- Rect cropRect = new Rect(scrollX, scrollY, scrollX + screenSize.x, scrollY + screenSize.y);
-
- Point defaultCropSurfaceSize = WallpaperCropUtils.getDefaultCropSurfaceSize(
- getResources(), getActivity().getWindowManager().getDefaultDisplay());
- int extraWidth = defaultCropSurfaceSize.x - screenSize.x;
- int extraHeightTopAndBottom = (int) ((defaultCropSurfaceSize.y - screenSize.y) / 2f);
-
- // Try to increase size of screenRect to include extra width depending on the layout
- // direction.
- if (isRtl()) {
- cropRect.left = Math.max(cropRect.left - extraWidth, rect.left);
- } else {
- cropRect.right = Math.min(cropRect.right + extraWidth, rect.right);
- }
-
- // Try to increase the size of the cropRect to to include extra height.
- int availableExtraHeightTop = cropRect.top - Math.max(
- rect.top,
- cropRect.top - extraHeightTopAndBottom);
- int availableExtraHeightBottom = Math.min(
- rect.bottom,
- cropRect.bottom + extraHeightTopAndBottom) - cropRect.bottom;
-
- int availableExtraHeightTopAndBottom =
- Math.min(availableExtraHeightTop, availableExtraHeightBottom);
- cropRect.top -= availableExtraHeightTopAndBottom;
- cropRect.bottom += availableExtraHeightTopAndBottom;
-
- return cropRect;
}
/**
@@ -830,35 +480,22 @@ public class PreviewFragment extends Fragment implements
*
* @param destination The wallpaper destination i.e. home vs. lockscreen vs. both.
*/
- private void setCurrentWallpaper(@Destination final int destination) {
- mWallpaperSetter.setCurrentWallpaper(getActivity(), mWallpaper, mWallpaperAsset,
- destination, mFullResImageView.getScale(), calculateCropRect(),
- new SetWallpaperCallback() {
- @Override
- public void onSuccess() {
- finishActivityWithResultOk();
- }
-
- @Override
- public void onError(@Nullable Throwable throwable) {
- showSetWallpaperErrorDialog(destination);
- }
- });
- }
+ protected abstract void setCurrentWallpaper(@Destination int destination);
- private void finishActivityWithResultOk() {
+ protected void finishActivityWithResultOk() {
+ Activity activity = requireActivity();
try {
- Toast.makeText(
- getActivity(), R.string.wallpaper_set_successfully_message, Toast.LENGTH_SHORT).show();
+ Toast.makeText(activity,
+ R.string.wallpaper_set_successfully_message, Toast.LENGTH_SHORT).show();
} catch (NotFoundException e) {
Log.e(TAG, "Could not show toast " + e);
}
- getActivity().overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
- getActivity().setResult(Activity.RESULT_OK);
- getActivity().finish();
+ activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
+ activity.setResult(Activity.RESULT_OK);
+ activity.finish();
}
- private void showSetWallpaperErrorDialog(@Destination int wallpaperDestination) {
+ protected void showSetWallpaperErrorDialog(@Destination int wallpaperDestination) {
SetWallpaperErrorDialogFragment newFragment = SetWallpaperErrorDialogFragment.newInstance(
R.string.set_wallpaper_error_message, wallpaperDestination);
newFragment.setTargetFragment(this, UNUSED_REQUEST_CODE);
@@ -866,9 +503,9 @@ public class PreviewFragment extends Fragment implements
// Show 'set wallpaper' error dialog now if it's safe to commit fragment transactions,
// otherwise stage it for later when the hosting activity is in a state to commit fragment
// transactions.
- BasePreviewActivity activity = (BasePreviewActivity) getActivity();
+ BasePreviewActivity activity = (BasePreviewActivity) requireActivity();
if (activity.isSafeToCommitFragmentTransaction()) {
- newFragment.show(getFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
+ newFragment.show(requireFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
} else {
mStagedSetWallpaperErrorDialogFragment = newFragment;
}
@@ -878,17 +515,16 @@ public class PreviewFragment extends Fragment implements
* Shows 'load wallpaper' error dialog now or stage it to be shown when the hosting activity is
* in a state that allows committing fragment transactions.
*/
- private void showLoadWallpaperErrorDialog() {
+ protected void showLoadWallpaperErrorDialog() {
LoadWallpaperErrorDialogFragment dialogFragment =
LoadWallpaperErrorDialogFragment.newInstance();
- dialogFragment.setTargetFragment(PreviewFragment.this, UNUSED_REQUEST_CODE);
+ dialogFragment.setTargetFragment(this, UNUSED_REQUEST_CODE);
// Show 'load wallpaper' error dialog now or stage it to be shown when the hosting
// activity is in a state that allows committing fragment transactions.
BasePreviewActivity activity = (BasePreviewActivity) getActivity();
if (activity != null && activity.isSafeToCommitFragmentTransaction()) {
- dialogFragment.show(PreviewFragment.this.getFragmentManager(),
- TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT);
+ dialogFragment.show(requireFragmentManager(), TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT);
} else {
mStagedLoadWallpaperErrorDialogFragment = dialogFragment;
}
@@ -903,59 +539,10 @@ public class PreviewFragment extends Fragment implements
}
/**
- * Gets the appropriate ActivityInfo orientation for the current configuration orientation to
- * enable locking screen rotation at API levels lower than 18.
- */
- @ActivityInfoScreenOrientation
- private int getCompatActivityInfoOrientation() {
- int configOrientation = getResources().getConfiguration().orientation;
- final Display display = getActivity().getWindowManager().getDefaultDisplay();
- int naturalOrientation = Configuration.ORIENTATION_LANDSCAPE;
- switch (display.getRotation()) {
- case Surface.ROTATION_0:
- case Surface.ROTATION_180:
- // We are currently in the same basic orientation as the natural orientation.
- naturalOrientation = configOrientation;
- break;
- case Surface.ROTATION_90:
- case Surface.ROTATION_270:
- // We are currently in the other basic orientation to the natural orientation.
- naturalOrientation = (configOrientation == Configuration.ORIENTATION_LANDSCAPE)
- ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
- break;
- default:
- // continue below
- }
-
- // Since the map starts at portrait, we need to offset if this device's natural orientation
- // is landscape.
- int indexOffset = 0;
- if (naturalOrientation == Configuration.ORIENTATION_LANDSCAPE) {
- indexOffset = 1;
- }
-
- switch ((display.getRotation() + indexOffset) % 4) {
- case 0:
- return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
- case 1:
- return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
- case 2:
- return ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
- case 3:
- return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
- default:
- Log.e(TAG, "Display rotation did not correspond to a valid ActivityInfo orientation"
- + "with display rotation: " + display.getRotation() + " and index offset: "
- + indexOffset + ".");
- return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
- }
- }
-
- /**
* Returns whether layout direction is RTL (or false for LTR). Since native RTL layout support
* was added in API 17, returns false for versions lower than 17.
*/
- private boolean isRtl() {
+ protected boolean isRtl() {
return getResources().getConfiguration().getLayoutDirection()
== View.LAYOUT_DIRECTION_RTL;
}
diff --git a/src/com/android/wallpaper/picker/StartRotationDialogFragment.java b/src/com/android/wallpaper/picker/StartRotationDialogFragment.java
index d5fd017..f0e4dcd 100755
--- a/src/com/android/wallpaper/picker/StartRotationDialogFragment.java
+++ b/src/com/android/wallpaper/picker/StartRotationDialogFragment.java
@@ -29,8 +29,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
-import androidx.appcompat.view.ContextThemeWrapper;
import androidx.fragment.app.DialogFragment;
import com.android.wallpaper.R;
@@ -42,29 +40,14 @@ import com.android.wallpaper.module.InjectorProvider;
*/
public class StartRotationDialogFragment extends DialogFragment {
private static final String KEY_IS_WIFI_ONLY_CHECKED = "key_is_wifi_only_checked";
- private static final String KEY_IS_LIVE_WALLPAPER_PREVIEW_NEEDED = "key_is_live_wallpaper_needed";
private static final boolean DEFAULT_IS_WIFI_ONLY = true;
private boolean mIsWifiOnlyChecked;
- private boolean mIsLiveWallpaperPreviewNeeded;
-
- public static StartRotationDialogFragment newInstance(boolean isLiveWallpaperPreviewNeeded) {
- StartRotationDialogFragment dialogFragment = new StartRotationDialogFragment();
- Bundle args = new Bundle();
- args.putBoolean(KEY_IS_LIVE_WALLPAPER_PREVIEW_NEEDED, isLiveWallpaperPreviewNeeded);
- dialogFragment.setArguments(args);
- return dialogFragment;
- }
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Bundle args = getArguments();
- if (args != null) {
- mIsLiveWallpaperPreviewNeeded = args.getBoolean(KEY_IS_LIVE_WALLPAPER_PREVIEW_NEEDED);
- }
-
if (savedInstanceState == null) {
mIsWifiOnlyChecked = DEFAULT_IS_WIFI_ONLY;
} else {
@@ -117,14 +100,10 @@ public class StartRotationDialogFragment extends DialogFragment {
}
private int getBodyTextResourceId() {
- return mIsLiveWallpaperPreviewNeeded
- ? R.string.start_rotation_dialog_body_live_wallpaper_needed
- : R.string.start_rotation_dialog_body;
+ return R.string.start_rotation_dialog_body;
}
private int getPositiveButtonTextResourceId() {
- return mIsLiveWallpaperPreviewNeeded
- ? R.string.start_rotation_dialog_continue
- : android.R.string.ok;
+ return android.R.string.ok;
}
}
diff --git a/src/com/android/wallpaper/picker/individual/IndividualPickerActivity.java b/src/com/android/wallpaper/picker/individual/IndividualPickerActivity.java
index 367181a..de5ba84 100755
--- a/src/com/android/wallpaper/picker/individual/IndividualPickerActivity.java
+++ b/src/com/android/wallpaper/picker/individual/IndividualPickerActivity.java
@@ -16,8 +16,6 @@
package com.android.wallpaper.picker.individual;
import android.app.Activity;
-import android.app.WallpaperManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources.NotFoundException;
@@ -44,12 +42,9 @@ import com.android.wallpaper.model.PickerIntentFactory;
import com.android.wallpaper.model.WallpaperInfo;
import com.android.wallpaper.module.Injector;
import com.android.wallpaper.module.InjectorProvider;
-import com.android.wallpaper.module.LiveWallpaperStatusChecker;
-import com.android.wallpaper.module.NoBackupImageWallpaper;
import com.android.wallpaper.module.WallpaperPersister;
import com.android.wallpaper.picker.BaseActivity;
import com.android.wallpaper.picker.PreviewActivity.PreviewActivityIntentFactory;
-import com.android.wallpaper.util.ActivityUtils;
import com.android.wallpaper.util.DiskBasedLogger;
/**
@@ -61,13 +56,11 @@ public class IndividualPickerActivity extends BaseActivity {
private static final String EXTRA_CATEGORY_COLLECTION_ID =
"com.android.wallpaper.category_collection_id";
private static final int PREVIEW_WALLPAPER_REQUEST_CODE = 0;
- private static final int NO_BACKUP_IMAGE_WALLPAPER_REQUEST_CODE = 1;
private static final int PREVIEW_LIVEWALLPAPER_REQUEST_CODE = 2;
private static final String KEY_CATEGORY_COLLECTION_ID = "key_category_collection_id";
private InlinePreviewIntentFactory mPreviewIntentFactory;
private WallpaperPersister mWallpaperPersister;
- private LiveWallpaperStatusChecker mLiveWallpaperStatusChecker;
private Category mCategory;
private String mCategoryCollectionId;
@@ -83,7 +76,6 @@ public class IndividualPickerActivity extends BaseActivity {
mPreviewIntentFactory = new PreviewActivityIntentFactory();
Injector injector = InjectorProvider.getInjector();
mWallpaperPersister = injector.getWallpaperPersister(this);
- mLiveWallpaperStatusChecker = injector.getLiveWallpaperStatusChecker(this);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
@@ -160,8 +152,8 @@ public class IndividualPickerActivity extends BaseActivity {
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
- // Handle Up as a Global back since the only entry point to IndividualPickerActivity is from
- // TopLevelPickerActivity.
+ // Handle Up as a Global back since the only entry point to IndividualPickerActivity is
+ // from TopLevelPickerActivity.
onBackPressed();
return true;
}
@@ -184,18 +176,6 @@ public class IndividualPickerActivity extends BaseActivity {
finishWithResultOk(shouldShowMessage);
}
break;
-
- case NO_BACKUP_IMAGE_WALLPAPER_REQUEST_CODE:
- // User clicked "Set wallpaper" in live wallpaper preview UI.
- // NOTE: Don't check for the result code prior to KitKat MR2 because a bug on those versions
- // caused the result code to be discarded from LivePicker so we can't rely on it.
- if ((!BuildCompat.isAtLeastL() || resultCode == Activity.RESULT_OK)
- && mLiveWallpaperStatusChecker.isNoBackupImageWallpaperSet()
- && mCategory.getWallpaperRotationInitializer().startRotation(getApplicationContext())) {
- finishWithResultOk(true);
- }
- break;
-
default:
Log.e(TAG, "Invalid request code: " + requestCode);
}
@@ -211,18 +191,6 @@ public class IndividualPickerActivity extends BaseActivity {
: PREVIEW_WALLPAPER_REQUEST_CODE);
}
- /**
- * Shows the system live wallpaper preview for the {@link NoBackupImageWallpaper} which is used to
- * draw rotating wallpapers on pre-N Android builds.
- */
- public void showNoBackupImageWallpaperPreview() {
- Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
- ComponentName componentName = new ComponentName(this, NoBackupImageWallpaper.class);
- intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, componentName);
- ActivityUtils.startActivityForResultSafely(
- this, intent, NO_BACKUP_IMAGE_WALLPAPER_REQUEST_CODE);
- }
-
private void finishWithResultOk(boolean shouldShowMessage) {
if (shouldShowMessage) {
try {
diff --git a/src/com/android/wallpaper/picker/individual/IndividualPickerFragment.java b/src/com/android/wallpaper/picker/individual/IndividualPickerFragment.java
index db21da3..c0c4ce5 100755
--- a/src/com/android/wallpaper/picker/individual/IndividualPickerFragment.java
+++ b/src/com/android/wallpaper/picker/individual/IndividualPickerFragment.java
@@ -58,13 +58,11 @@ import com.android.wallpaper.model.WallpaperRotationInitializer;
import com.android.wallpaper.model.WallpaperRotationInitializer.Listener;
import com.android.wallpaper.model.WallpaperRotationInitializer.NetworkPreference;
import com.android.wallpaper.model.WallpaperRotationInitializer.RotationInitializationState;
-import com.android.wallpaper.model.WallpaperRotationInitializer.RotationStateListener;
import com.android.wallpaper.module.FormFactorChecker;
import com.android.wallpaper.module.FormFactorChecker.FormFactor;
import com.android.wallpaper.module.Injector;
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.module.PackageStatusNotifier;
-import com.android.wallpaper.module.RotatingWallpaperComponentChecker;
import com.android.wallpaper.module.WallpaperChangedNotifier;
import com.android.wallpaper.module.WallpaperPersister;
import com.android.wallpaper.module.WallpaperPersister.Destination;
@@ -116,7 +114,6 @@ public class IndividualPickerFragment extends Fragment
WallpaperPreferences mWallpaperPreferences;
WallpaperChangedNotifier mWallpaperChangedNotifier;
- RotatingWallpaperComponentChecker mRotatingWallpaperComponentChecker;
RecyclerView mImageGrid;
IndividualAdapter mAdapter;
WallpaperCategory mCategory;
@@ -250,8 +247,6 @@ public class IndividualPickerFragment extends Fragment
mWallpaperChangedNotifier = WallpaperChangedNotifier.getInstance();
mWallpaperChangedNotifier.registerListener(mWallpaperChangedListener);
- mRotatingWallpaperComponentChecker = injector.getRotatingWallpaperComponentChecker();
-
mFormFactor = injector.getFormFactorChecker(appContext).getFormFactor();
mPackageStatusNotifier = injector.getPackageStatusNotifier(appContext);
@@ -445,7 +440,8 @@ public class IndividualPickerFragment extends Fragment
public void onResume() {
super.onResume();
- WallpaperPreferences preferences = InjectorProvider.getInjector().getPreferences(getActivity());
+ WallpaperPreferences preferences = InjectorProvider.getInjector()
+ .getPreferences(getActivity());
preferences.setLastAppActiveTimestamp(new Date().getTime());
// Reset Glide memory settings to a "normal" level of usage since it may have been lowered in
@@ -541,31 +537,23 @@ public class IndividualPickerFragment extends Fragment
* state of the user's device and binds the state of the current category's rotation to the "start
* rotation" tile.
*/
- private void refreshRotationHolder(final RotationHolder rotationHolder) {
+ private void refreshRotationHolder(RotationHolder rotationHolder) {
mWallpaperRotationInitializer.fetchRotationInitializationState(getContext(),
- new RotationStateListener() {
- @Override
- public void onRotationStateReceived(
- @RotationInitializationState final int rotationInitializationState) {
-
- // Update the UI state of the "start rotation" tile displayed on screen. Do this in a
- // Handler so it is scheduled at the end of the message queue. This is necessary to
- // ensure we do not remove or add data from the adapter while the layout is still being
- // computed. RecyclerView documentation therefore recommends performing such changes in
- // a Handler.
- new android.os.Handler().post(new Runnable() {
- @Override
- public void run() {
- // A config change may have destroyed the activity since the refresh started, so
- // check for that to avoid an NPE.
- if (getActivity() == null) {
- return;
- }
+ rotationState -> {
+ // Update the UI state of the "start rotation" tile displayed on screen.
+ // Do this in a Handler so it is scheduled at the end of the message queue.
+ // This is necessary to ensure we do not remove or add data from the adapter
+ // while the layout is still being computed. RecyclerView documentation
+ // therefore recommends performing such changes in a Handler.
+ new Handler().post(() -> {
+ // A config change may have destroyed the activity since the refresh
+ // started, so check for that to avoid an NPE.
+ if (getActivity() == null) {
+ return;
+ }
- rotationHolder.bindRotationInitializationState(rotationInitializationState);
- }
- });
- }
+ rotationHolder.bindRotationInitializationState(rotationState);
+ });
});
}
@@ -614,34 +602,33 @@ public class IndividualPickerFragment extends Fragment
// app before the first wallpaper image in rotation finishes downloading.
Activity activity = getActivity();
- if (activity != null
- && mWallpaperRotationInitializer
- .isNoBackupImageWallpaperPreviewNeeded(appContext)) {
- ((IndividualPickerActivity) activity).showNoBackupImageWallpaperPreview();
- } else {
- if (mWallpaperRotationInitializer.startRotation(appContext)) {
- if (activity != null && mFormFactor == FormFactorChecker.FORM_FACTOR_MOBILE) {
- try {
- Toast.makeText(getActivity(), R.string.wallpaper_set_successfully_message,
- Toast.LENGTH_SHORT).show();
- } catch (NotFoundException e) {
- Log.e(TAG, "Could not show toast " + e);
- }
- activity.setResult(Activity.RESULT_OK);
- activity.finish();
- } else if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
- mAdapter.updateSelectedTile(SPECIAL_FIXED_TILE_ADAPTER_POSITION);
- }
- } else { // Failed to start rotation.
- showStartRotationErrorDialog(networkPreference);
-
- if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
- DesktopRotationHolder rotationViewHolder =
- (DesktopRotationHolder) mImageGrid.findViewHolderForAdapterPosition(
- SPECIAL_FIXED_TILE_ADAPTER_POSITION);
- rotationViewHolder.setSelectionState(SelectableHolder.SELECTION_STATE_DESELECTED);
+ if (mWallpaperRotationInitializer.startRotation(appContext)) {
+ if (activity != null
+ && mFormFactor == FormFactorChecker.FORM_FACTOR_MOBILE) {
+ try {
+ Toast.makeText(getActivity(),
+ R.string.wallpaper_set_successfully_message,
+ Toast.LENGTH_SHORT).show();
+ } catch (NotFoundException e) {
+ Log.e(TAG, "Could not show toast " + e);
}
+
+ activity.setResult(Activity.RESULT_OK);
+ activity.finish();
+ } else if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
+ mAdapter.updateSelectedTile(SPECIAL_FIXED_TILE_ADAPTER_POSITION);
+ }
+ } else { // Failed to start rotation.
+ showStartRotationErrorDialog(networkPreference);
+
+ if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
+ DesktopRotationHolder rotationViewHolder =
+ (DesktopRotationHolder)
+ mImageGrid.findViewHolderForAdapterPosition(
+ SPECIAL_FIXED_TILE_ADAPTER_POSITION);
+ rotationViewHolder.setSelectionState(
+ SelectableHolder.SELECTION_STATE_DESELECTED);
}
}
}
@@ -690,11 +677,7 @@ public class IndividualPickerFragment extends Fragment
* Returns whether rotation is enabled for this category.
*/
boolean isRotationEnabled() {
- boolean isRotationSupported =
- mRotatingWallpaperComponentChecker.getRotatingWallpaperSupport(getContext())
- == RotatingWallpaperComponentChecker.ROTATING_WALLPAPER_SUPPORT_SUPPORTED;
-
- return isRotationSupported && mWallpaperRotationInitializer != null;
+ return mWallpaperRotationInitializer != null;
}
@Override
@@ -732,10 +715,10 @@ public class IndividualPickerFragment extends Fragment
super(itemView);
itemView.setOnClickListener(this);
- mTileLayout = (FrameLayout) itemView.findViewById(R.id.daily_refresh);
- mRotationMessage = (TextView) itemView.findViewById(R.id.rotation_tile_message);
- mRotationTitle = (TextView) itemView.findViewById(R.id.rotation_tile_title);
- mRefreshIcon = (ImageView) itemView.findViewById(R.id.rotation_tile_refresh_icon);
+ mTileLayout = itemView.findViewById(R.id.daily_refresh);
+ mRotationMessage = itemView.findViewById(R.id.rotation_tile_message);
+ mRotationTitle = itemView.findViewById(R.id.rotation_tile_title);
+ mRefreshIcon = itemView.findViewById(R.id.rotation_tile_refresh_icon);
mTileLayout.getLayoutParams().height = mTileSizePx.y;
// If the feature flag for "dynamic start rotation tile" is not enabled, fall back to the
@@ -749,7 +732,8 @@ public class IndividualPickerFragment extends Fragment
mRotationMessage.setTextColor(
getResources().getColor(R.color.rotation_tile_enabled_subtitle_text_color));
mRefreshIcon.setColorFilter(
- getResources().getColor(R.color.rotation_tile_enabled_refresh_icon_color), Mode.SRC_IN);
+ getResources().getColor(R.color.rotation_tile_enabled_refresh_icon_color),
+ Mode.SRC_IN);
return;
}
@@ -765,10 +749,7 @@ public class IndividualPickerFragment extends Fragment
@Override
public void onClick(View v) {
- boolean isLiveWallpaperNeeded = mWallpaperRotationInitializer
- .isNoBackupImageWallpaperPreviewNeeded(getActivity().getApplicationContext());
- DialogFragment startRotationDialogFragment = StartRotationDialogFragment
- .newInstance(isLiveWallpaperNeeded);
+ DialogFragment startRotationDialogFragment = new StartRotationDialogFragment();
startRotationDialogFragment.setTargetFragment(
IndividualPickerFragment.this, UNUSED_REQUEST_CODE);
startRotationDialogFragment.show(getFragmentManager(), TAG_START_ROTATION_DIALOG);