Fallback to static thumbnail for Live Wallpapers
When WallpaperEngine scalePreview API is not available, use a static
thumbnail for live wallpapers instead of crashing.
Also refactor to extract a single WallpaperSurfaceCallback to make this
simpler.
Bug: 12329489
Change-Id: I6d23c0e4d557ba216e8815bc4c42f775a4dbe841
diff --git a/src/com/android/wallpaper/picker/CategoryFragment.java b/src/com/android/wallpaper/picker/CategoryFragment.java
index db60c5f..9e7201e 100755
--- a/src/com/android/wallpaper/picker/CategoryFragment.java
+++ b/src/com/android/wallpaper/picker/CategoryFragment.java
@@ -15,9 +15,6 @@
*/
package com.android.wallpaper.picker;
-import static android.view.View.MeasureSpec.EXACTLY;
-import static android.view.View.MeasureSpec.makeMeasureSpec;
-
import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED;
import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED;
@@ -32,9 +29,6 @@
import android.provider.Settings;
import android.service.wallpaper.WallpaperService;
import android.view.LayoutInflater;
-import android.view.Surface;
-import android.view.SurfaceControlViewHost;
-import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
@@ -47,7 +41,6 @@
import androidx.appcompat.app.AlertDialog;
import androidx.cardview.widget.CardView;
import androidx.constraintlayout.widget.ConstraintLayout;
-import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
@@ -73,6 +66,7 @@
import com.android.wallpaper.util.SizeCalculator;
import com.android.wallpaper.util.WallpaperConnection;
import com.android.wallpaper.util.WallpaperConnection.WallpaperConnectionListener;
+import com.android.wallpaper.util.WallpaperSurfaceCallback;
import com.android.wallpaper.widget.BottomActionBar;
import com.android.wallpaper.widget.LiveTileOverlay;
import com.android.wallpaper.widget.LockScreenPreviewer;
@@ -96,12 +90,6 @@
implements CategorySelectorFragmentHost, ThumbnailUpdater, WallpaperDestinationCallback,
WallpaperPickerRecyclerViewAccessibilityDelegate.BottomSheetHost {
- private final Rect mPreviewLocalRect = new Rect();
- private final Rect mPreviewGlobalRect = new Rect();
- private final int[] mLivePreviewLocation = new int[2];
- private final WallpaperSurfaceCallback mWallpaperSurfaceCallback =
- new WallpaperSurfaceCallback();
-
/**
* Interface to be implemented by an Activity hosting a {@link CategoryFragment}
*/
@@ -135,6 +123,7 @@
private SurfaceView mWorkspaceSurface;
private WorkspaceSurfaceHolderCallback mWorkspaceSurfaceCallback;
private SurfaceView mWallpaperSurface;
+ private WallpaperSurfaceCallback mWallpaperSurfaceCallback;
private ImageView mLockscreenPreview;
private PreviewPager mPreviewPager;
private List<View> mWallPaperPreviews;
@@ -151,13 +140,13 @@
// The wallpaper information which is currently shown on the lock preview.
private WallpaperInfo mLockPreviewWallpaperInfo;
- // Home workspace surface is behind the app window, and so must the home image wallpaper like
- // the live wallpaper. This view is rendered on mWallpaperSurface for home image wallpaper.
- private ImageView mHomeImageWallpaper;
- private boolean mIsCollapsingByUserSelecting;
private LockScreenPreviewer mLockScreenPreviewer;
private View mRootContainer;
+ private final Rect mPreviewLocalRect = new Rect();
+ private final Rect mPreviewGlobalRect = new Rect();
+ private final int[] mLivePreviewLocation = new int[2];
+
public CategoryFragment() {
mCategorySelectorFragment = new CategorySelectorFragment();
}
@@ -176,6 +165,8 @@
mWorkspaceSurfaceCallback = new WorkspaceSurfaceHolderCallback(
mWorkspaceSurface, getContext());
mWallpaperSurface = homePreviewCard.findViewById(R.id.wallpaper_surface);
+ mWallpaperSurfaceCallback = new WallpaperSurfaceCallback(getContext(), mHomePreview,
+ mWallpaperSurface);
mWallPaperPreviews.add(homePreviewCard);
CardView lockscreenPreviewCard = (CardView) inflater.inflate(
@@ -409,7 +400,6 @@
mIndividualPickerFragment.resizeLayout(mBottomSheetBehavior.getPeekHeight());
mIndividualPickerFragment.scrollToPosition(position);
if (mBottomSheetBehavior.getState() != STATE_COLLAPSED) {
- mIsCollapsingByUserSelecting = true;
mBottomSheetBehavior.setState(STATE_COLLAPSED);
}
});
@@ -647,34 +637,37 @@
if (mWallpaperConnection != null) {
mWallpaperConnection.disconnect();
}
- ImageView previewView = mWallpaperIndex == 0 ? mHomePreview : mLockscreenPreview;
- previewView.getLocationOnScreen(mLivePreviewLocation);
- mPreviewGlobalRect.set(0, 0, previewView.getMeasuredWidth(),
- previewView.getMeasuredHeight());
- mPreviewLocalRect.set(mPreviewGlobalRect);
- mPreviewGlobalRect.offset(mLivePreviewLocation[0], mLivePreviewLocation[1]);
- mWallpaperConnection = new WallpaperConnection(
- getWallpaperIntent(homeWallpaper.getWallpaperComponent()), activity,
- new WallpaperConnectionListener() {
- @Override
- public void onWallpaperColorsChanged(WallpaperColors colors, int displayId) {
- if (mLockPreviewWallpaperInfo instanceof LiveWallpaperInfo) {
- mLockScreenPreviewer.setColor(colors);
+ if (WallpaperConnection.isPreviewAvailable()) {
+ ImageView previewView = mWallpaperIndex == 0 ? mHomePreview : mLockscreenPreview;
+ previewView.getLocationOnScreen(mLivePreviewLocation);
+ mPreviewGlobalRect.set(0, 0, previewView.getMeasuredWidth(),
+ previewView.getMeasuredHeight());
+ mPreviewLocalRect.set(mPreviewGlobalRect);
+ mPreviewGlobalRect.offset(mLivePreviewLocation[0], mLivePreviewLocation[1]);
+ mWallpaperConnection = new WallpaperConnection(
+ getWallpaperIntent(homeWallpaper.getWallpaperComponent()), activity,
+ new WallpaperConnectionListener() {
+ @Override
+ public void onWallpaperColorsChanged(WallpaperColors colors,
+ int displayId) {
+ if (mLockPreviewWallpaperInfo instanceof LiveWallpaperInfo) {
+ mLockScreenPreviewer.setColor(colors);
+ }
}
- }
- }, mPreviewGlobalRect);
+ }, mPreviewGlobalRect);
- LiveTileOverlay.INSTANCE.update(new RectF(mPreviewLocalRect),
- ((CardView) previewView.getParent()).getRadius());
+ LiveTileOverlay.INSTANCE.update(new RectF(mPreviewLocalRect),
+ ((CardView) previewView.getParent()).getRadius());
- mWallpaperConnection.setVisibility(true);
- previewView.post(() -> {
- if (mWallpaperConnection != null && !mWallpaperConnection.connect()) {
- mWallpaperConnection = null;
- LiveTileOverlay.INSTANCE.detach(previewView.getOverlay());
- }
- });
+ mWallpaperConnection.setVisibility(true);
+ previewView.post(() -> {
+ if (mWallpaperConnection != null && !mWallpaperConnection.connect()) {
+ mWallpaperConnection = null;
+ LiveTileOverlay.INSTANCE.detach(previewView.getOverlay());
+ }
+ });
+ }
}
private void updateThumbnail(WallpaperInfo wallpaperInfo, ImageView thumbnailView,
@@ -696,7 +689,8 @@
boolean renderInImageWallpaperSurface =
!(wallpaperInfo instanceof LiveWallpaperInfo) && isHomeWallpaper;
- ImageView imageView = renderInImageWallpaperSurface ? mHomeImageWallpaper : thumbnailView;
+ ImageView imageView = renderInImageWallpaperSurface
+ ? mWallpaperSurfaceCallback.getHomeImageWallpaper() : thumbnailView;
if (imageView != null) {
wallpaperInfo.getThumbAsset(activity.getApplicationContext())
.loadPreviewImage(activity, imageView,
@@ -706,9 +700,9 @@
if (isHomeWallpaper) {
LiveTileOverlay.INSTANCE.detach(thumbnailView.getOverlay());
if (wallpaperInfo instanceof LiveWallpaperInfo) {
- if(mHomeImageWallpaper != null) {
+ if (mWallpaperSurfaceCallback.getHomeImageWallpaper() != null) {
wallpaperInfo.getThumbAsset(activity.getApplicationContext()).loadPreviewImage(
- activity, mHomeImageWallpaper,
+ activity, mWallpaperSurfaceCallback.getHomeImageWallpaper(),
getResources().getColor(R.color.secondary_color));
}
setUpLiveWallpaperPreview(wallpaperInfo);
@@ -720,7 +714,8 @@
}
} else {
// lock screen wallpaper
- if (wallpaperInfo instanceof LiveWallpaperInfo) {
+ if (wallpaperInfo instanceof LiveWallpaperInfo
+ && WallpaperConnection.isPreviewAvailable()) {
LiveTileOverlay.INSTANCE.attach(thumbnailView.getOverlay());
} else {
LiveTileOverlay.INSTANCE.detach(thumbnailView.getOverlay());
@@ -747,45 +742,6 @@
mWorkspaceSurface.getHolder().addCallback(mWorkspaceSurfaceCallback);
}
- private class WallpaperSurfaceCallback implements SurfaceHolder.Callback {
-
- private Surface mLastSurface;
- private SurfaceControlViewHost mHost;
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- if (mLastSurface != holder.getSurface()) {
- mLastSurface = holder.getSurface();
- mHomeImageWallpaper = new ImageView(getContext());
- mHomeImageWallpaper.setBackgroundColor(
- ContextCompat.getColor(getContext(), R.color.primary_color));
- mHomeImageWallpaper.measure(makeMeasureSpec(mHomePreview.getWidth(), EXACTLY),
- makeMeasureSpec(mHomePreview.getHeight(), EXACTLY));
- mHomeImageWallpaper.layout(0, 0, mHomePreview.getWidth(), mHomePreview.getHeight());
-
- cleanUp();
- mHost = new SurfaceControlViewHost(getContext(),
- getContext().getDisplay(), mWallpaperSurface.getHostToken());
- mHost.setView(mHomeImageWallpaper, mHomeImageWallpaper.getWidth(),
- mHomeImageWallpaper.getHeight());
- mWallpaperSurface.setChildSurfacePackage(mHost.getSurfacePackage());
- }
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) { }
-
- public void cleanUp() {
- if (mHost != null) {
- mHost.release();
- mHost = null;
- }
- }
- };
-
private static class PreviewPagerAdapter extends PagerAdapter {
private List<View> mPages;
diff --git a/src/com/android/wallpaper/picker/LivePreviewFragment.java b/src/com/android/wallpaper/picker/LivePreviewFragment.java
index 7af31ac..a28b4a0 100644
--- a/src/com/android/wallpaper/picker/LivePreviewFragment.java
+++ b/src/com/android/wallpaper/picker/LivePreviewFragment.java
@@ -69,10 +69,12 @@
import com.android.wallpaper.util.ScreenSizeCalculator;
import com.android.wallpaper.util.SizeCalculator;
import com.android.wallpaper.util.WallpaperConnection;
+import com.android.wallpaper.util.WallpaperSurfaceCallback;
import com.android.wallpaper.widget.BottomActionBar;
import com.android.wallpaper.widget.BottomActionBar.AccessibilityCallback;
import com.android.wallpaper.widget.LiveTileOverlay;
import com.android.wallpaper.widget.LockScreenPreviewer;
+import com.android.wallpaper.widget.WallpaperColorsLoader;
import com.android.wallpaper.widget.WallpaperInfoView;
import com.google.android.material.tabs.TabLayout;
@@ -115,9 +117,11 @@
private ViewGroup mPreviewContainer;
private TouchForwardingLayout mTouchForwardingLayout;
private SurfaceView mWorkspaceSurface;
+ private SurfaceView mWallpaperSurface;
private ViewGroup mLockPreviewContainer;
private LockScreenPreviewer mLockScreenPreviewer;
private WorkspaceSurfaceHolderCallback mWorkspaceSurfaceCallback;
+ private WallpaperSurfaceCallback mWallpaperSurfaceCallback;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -190,9 +194,13 @@
mLockPreviewContainer = mPreviewContainer.findViewById(R.id.lock_screen_preview_container);
mLockScreenPreviewer = new LockScreenPreviewer(getLifecycle(), activity,
mLockPreviewContainer);
+ mWallpaperSurface = mHomePreviewCard.findViewById(R.id.wallpaper_surface);
mWorkspaceSurface = mHomePreviewCard.findViewById(R.id.workspace_surface);
+
mWorkspaceSurfaceCallback = new WorkspaceSurfaceHolderCallback(
mWorkspaceSurface, getContext());
+ mWallpaperSurfaceCallback = new WallpaperSurfaceCallback(getContext(),
+ mHomePreview, mWallpaperSurface);
TabLayout tabs = inflater.inflate(R.layout.full_preview_tabs,
view.findViewById(R.id.toolbar_tabs_container))
@@ -231,10 +239,15 @@
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
+ updateWallpaperSurface();
setupCurrentWallpaperPreview();
renderWorkspaceSurface();
}
+ private void updateWallpaperSurface() {
+ mWallpaperSurface.getHolder().addCallback(mWallpaperSurfaceCallback);
+ }
+
private void updateScreenPreview(boolean isHomeSelected) {
mWorkspaceSurface.setVisibility(isHomeSelected ? View.VISIBLE : View.INVISIBLE);
mLockPreviewContainer.setVisibility(isHomeSelected ? View.INVISIBLE : View.VISIBLE);
@@ -289,13 +302,17 @@
mWallpaperConnection = null;
}
mWorkspaceSurfaceCallback.cleanUp();
+ mWallpaperSurfaceCallback.cleanUp();
}
private void previewLiveWallpaper(ImageView thumbnailView) {
thumbnailView.post(() -> {
- mWallpaper.getThumbAsset(requireActivity().getApplicationContext()).loadPreviewImage(
- requireActivity(), thumbnailView,
- getResources().getColor(R.color.secondary_color));
+ if (mWallpaperSurfaceCallback.getHomeImageWallpaper() != null) {
+ mWallpaper.getThumbAsset(requireActivity().getApplicationContext())
+ .loadPreviewImage(requireActivity(),
+ mWallpaperSurfaceCallback.getHomeImageWallpaper(),
+ getResources().getColor(R.color.secondary_color));
+ }
LiveTileOverlay.INSTANCE.detach(thumbnailView.getOverlay());
setUpLiveWallpaperPreview(mWallpaper, thumbnailView,
@@ -317,18 +334,25 @@
thumbnail.setBounds(previewView.getLeft(), previewView.getTop(), previewView.getRight(),
previewView.getBottom());
}
- repositionPreview(previewView);
- mWallpaperConnection = new WallpaperConnection(
- getWallpaperIntent(homeWallpaper.getWallpaperComponent()),
- activity,
- /* listener= */ this,
- mPreviewGlobalRect);
+ if (WallpaperConnection.isPreviewAvailable()) {
+ repositionPreview(previewView);
+ mWallpaperConnection = new WallpaperConnection(
+ getWallpaperIntent(homeWallpaper.getWallpaperComponent()),
+ activity,
+ /* listener= */ this,
+ mPreviewGlobalRect);
- LiveTileOverlay.INSTANCE.update(new RectF(mPreviewLocalRect),
- ((CardView) previewView.getParent()).getRadius());
+ LiveTileOverlay.INSTANCE.update(new RectF(mPreviewLocalRect),
+ ((CardView) previewView.getParent()).getRadius());
- mWallpaperConnection.setVisibility(true);
+ mWallpaperConnection.setVisibility(true);
+ } else {
+ WallpaperColorsLoader.getWallpaperColors(
+ activity,
+ homeWallpaper.getThumbAsset(activity),
+ mLockScreenPreviewer::setColor);
+ }
mLoadingScrim.post(() -> mLoadingScrim.animate()
.alpha(0f)
.setStartDelay(50)
diff --git a/src/com/android/wallpaper/util/WallpaperConnection.java b/src/com/android/wallpaper/util/WallpaperConnection.java
index 1b5bdae..27b02ee 100644
--- a/src/com/android/wallpaper/util/WallpaperConnection.java
+++ b/src/com/android/wallpaper/util/WallpaperConnection.java
@@ -42,6 +42,13 @@
*/
public class WallpaperConnection extends IWallpaperConnection.Stub implements ServiceConnection {
+ /**
+ * Returns whether live preview is available in framework.
+ */
+ public static boolean isPreviewAvailable() {
+ return WallpaperEngineCompat.supportsScalePreview();
+ }
+
private static final String TAG = "WallpaperConnection";
private final Activity mActivity;
private final Intent mIntent;
diff --git a/src/com/android/wallpaper/util/WallpaperSurfaceCallback.java b/src/com/android/wallpaper/util/WallpaperSurfaceCallback.java
new file mode 100644
index 0000000..64f13bd
--- /dev/null
+++ b/src/com/android/wallpaper/util/WallpaperSurfaceCallback.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2020 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.util;
+
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.makeMeasureSpec;
+
+import android.content.Context;
+import android.view.Surface;
+import android.view.SurfaceControlViewHost;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.widget.ImageView;
+
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+
+import com.android.wallpaper.R;
+
+/**
+ * Default implementation of {@link SurfaceHolder.Callback} to render a static wallpaper when the
+ * surface has been created.
+ */
+public class WallpaperSurfaceCallback implements SurfaceHolder.Callback {
+
+ /**
+ * Listener used to be notified when this surface is created
+ */
+ public interface SurfaceListener {
+ /**
+ * Called when {@link WallpaperSurfaceCallback#surfaceCreated(SurfaceHolder)} is called.
+ */
+ void onSurfaceCreated();
+ }
+
+ private Surface mLastSurface;
+ private SurfaceControlViewHost mHost;
+ // Home workspace surface is behind the app window, and so must the home image wallpaper like
+ // the live wallpaper. This view is rendered on here for home image wallpaper.
+ private ImageView mHomeImageWallpaper;
+ private final Context mContext;
+ private final ImageView mHomePreview;
+ private final SurfaceView mWallpaperSurface;
+ @Nullable
+ private final SurfaceListener mListener;
+
+ public WallpaperSurfaceCallback(Context context, ImageView homePreview,
+ SurfaceView wallpaperSurface, @Nullable SurfaceListener listener) {
+ mContext = context;
+ mHomePreview = homePreview;
+ mWallpaperSurface = wallpaperSurface;
+ mListener = listener;
+ }
+
+ public WallpaperSurfaceCallback(Context context, ImageView homePreview,
+ SurfaceView wallpaperSurface) {
+ this(context, homePreview, wallpaperSurface, null);
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ if (mLastSurface != holder.getSurface()) {
+ mLastSurface = holder.getSurface();
+ mHomeImageWallpaper = new ImageView(mContext);
+ mHomeImageWallpaper.setBackgroundColor(
+ ContextCompat.getColor(mContext, R.color.primary_color));
+ mHomeImageWallpaper.measure(makeMeasureSpec(mHomePreview.getWidth(), EXACTLY),
+ makeMeasureSpec(mHomePreview.getHeight(), EXACTLY));
+ mHomeImageWallpaper.layout(0, 0, mHomePreview.getWidth(),
+ mHomePreview.getHeight());
+
+ cleanUp();
+ mHost = new SurfaceControlViewHost(mContext,
+ mContext.getDisplay(), mWallpaperSurface.getHostToken());
+ mHost.setView(mHomeImageWallpaper, mHomeImageWallpaper.getWidth(),
+ mHomeImageWallpaper.getHeight());
+ mWallpaperSurface.setChildSurfacePackage(mHost.getSurfacePackage());
+ }
+ if (mListener != null) {
+ mListener.onSurfaceCreated();
+ }
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) { }
+
+ /**
+ * Call to release resources.
+ */
+ public void cleanUp() {
+ if (mHost != null) {
+ mHost.release();
+ mHost = null;
+ }
+ }
+
+ @Nullable
+ public ImageView getHomeImageWallpaper() {
+ return mHomeImageWallpaper;
+ }
+}