Add live wallpaper support for Grid preview
Add supprot for grid full preview first, next step is to add for grid picker.
Video: https://drive.google.com/file/d/1AH6AUno2IYxHzEt1nItNmASf0S6OEbgM/view?usp=sharing
Test: Manually
Bug: 155938545
Change-Id: If2cc9a7e7e79f346100fea4b821862c515bbc644
diff --git a/res/layout/fragment_grid_full_preview.xml b/res/layout/fragment_grid_full_preview.xml
index 80733ab..1c01743 100644
--- a/res/layout/fragment_grid_full_preview.xml
+++ b/res/layout/fragment_grid_full_preview.xml
@@ -40,13 +40,19 @@
<ImageView
android:id="@+id/grid_full_preview_image"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent"
+ android:background="@color/primary_color"/>
<SurfaceView
- android:id="@+id/grid_full_preview_surface"
+ android:id="@+id/grid_full_preview_option_surface"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
+ <SurfaceView
+ android:id="@+id/grid_full_preview_wallpaper_surface"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
</androidx.cardview.widget.CardView>
</FrameLayout>
</LinearLayout>
diff --git a/src/com/android/customization/picker/grid/GridFragment.java b/src/com/android/customization/picker/grid/GridFragment.java
index b3495c6..c9af437 100644
--- a/src/com/android/customization/picker/grid/GridFragment.java
+++ b/src/com/android/customization/picker/grid/GridFragment.java
@@ -19,6 +19,7 @@
import static com.android.customization.picker.ViewOnlyFullPreviewActivity.SECTION_GRID;
import static com.android.customization.picker.grid.GridFullPreviewFragment.EXTRA_GRID_OPTION;
+import static com.android.customization.picker.grid.GridFullPreviewFragment.EXTRA_GRID_USES_SURFACE_VIEW;
import static com.android.customization.picker.grid.GridFullPreviewFragment.EXTRA_WALLPAPER_INFO;
import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY;
@@ -297,6 +298,7 @@
Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_WALLPAPER_INFO, mHomeWallpaper);
bundle.putParcelable(EXTRA_GRID_OPTION, mSelectedOption);
+ bundle.putBoolean(EXTRA_GRID_USES_SURFACE_VIEW, mGridManager.usesSurfaceView());
Intent intent = ViewOnlyFullPreviewActivity.newIntent(getContext(), SECTION_GRID, bundle);
startActivityForResult(intent, FULL_PREVIEW_REQUEST_CODE);
}
@@ -367,7 +369,8 @@
super.setCard(card);
mPreview = card.findViewById(R.id.grid_preview_image);
mPreviewSurface = card.findViewById(R.id.grid_preview_surface);
- card.setOnClickListener(view -> showFullPreview());
+ // PreviewSurface is the top of its window(card view), due to #setZOrderOnTop(true).
+ mPreviewSurface.setOnClickListener(view -> showFullPreview());
}
public void bindPreviewContent() {
diff --git a/src/com/android/customization/picker/grid/GridFullPreviewFragment.java b/src/com/android/customization/picker/grid/GridFullPreviewFragment.java
index 9e469a3..4803ca2 100644
--- a/src/com/android/customization/picker/grid/GridFullPreviewFragment.java
+++ b/src/com/android/customization/picker/grid/GridFullPreviewFragment.java
@@ -16,19 +16,24 @@
package com.android.customization.picker.grid;
import static android.app.Activity.RESULT_OK;
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.makeMeasureSpec;
import static com.android.customization.picker.grid.GridFragment.PREVIEW_FADE_DURATION_MS;
import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY;
import android.app.Activity;
import android.content.Intent;
-import android.graphics.drawable.BitmapDrawable;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Bundle;
import android.os.Message;
import android.os.RemoteException;
+import android.service.wallpaper.WallpaperService;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.Surface;
+import android.view.SurfaceControlViewHost;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
@@ -38,6 +43,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.cardview.widget.CardView;
+import androidx.core.content.ContextCompat;
import com.android.customization.model.grid.GridOption;
import com.android.customization.model.grid.GridOptionsManager;
@@ -47,12 +53,15 @@
import com.android.wallpaper.R;
import com.android.wallpaper.asset.Asset;
import com.android.wallpaper.asset.ContentUriAsset;
+import com.android.wallpaper.model.LiveWallpaperInfo;
import com.android.wallpaper.model.WallpaperInfo;
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.picker.AppbarFragment;
import com.android.wallpaper.util.SurfaceViewUtils;
import com.android.wallpaper.util.TileSizeCalculator;
+import com.android.wallpaper.util.WallpaperConnection;
import com.android.wallpaper.widget.BottomActionBar;
+import com.android.wallpaper.widget.LiveTileOverlay;
import com.bumptech.glide.request.RequestOptions;
@@ -61,15 +70,26 @@
static final String EXTRA_WALLPAPER_INFO = "wallpaper_info";
static final String EXTRA_GRID_OPTION = "grid_option";
+ static final String EXTRA_GRID_USES_SURFACE_VIEW = "uses_surface_view";
+
+ private final Rect mPreviewLocalRect = new Rect();
+ private final Rect mPreviewGlobalRect = new Rect();
+ private final int[] mLivePreviewLocation = new int[2];
private GridOptionsManager mGridManager;
private WallpaperInfo mWallpaper;
private GridOption mGridOption;
+ private boolean mUsesSurfaceView;
private CardView mCardView;
- private ImageView mPreview;
- private SurfaceView mPreviewSurface;
- private BitmapDrawable mCardBackground;
+ private ImageView mHomePreview;
+ private SurfaceView mGridOptionSurface;
+ private SurfaceView mWallpaperSurface;
+ private WallpaperConnection mWallpaperConnection;
+
+ // 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;
/**
* Returns a new {@link GridFullPreviewFragment} with the provided title and bundle arguments
@@ -89,6 +109,7 @@
super.onCreate(savedInstanceState);
mWallpaper = getArguments().getParcelable(EXTRA_WALLPAPER_INFO);
mGridOption = getArguments().getParcelable(EXTRA_GRID_OPTION);
+ mUsesSurfaceView = getArguments().getBoolean(EXTRA_GRID_USES_SURFACE_VIEW);
CustomizationInjector injector = (CustomizationInjector) InjectorProvider.getInjector();
ThemesUserEventLogger eventLogger = (ThemesUserEventLogger) injector.getUserEventLogger(
@@ -108,8 +129,10 @@
setUpToolbar(view);
mCardView = view.findViewById(R.id.grid_full_preview_card);
- mPreview = view.findViewById(R.id.grid_full_preview_image);
- mPreviewSurface = view.findViewById(R.id.grid_full_preview_surface);
+ mHomePreview = view.findViewById(R.id.grid_full_preview_image);
+ mGridOptionSurface = view.findViewById(R.id.grid_full_preview_option_surface);
+ mWallpaperSurface = view.findViewById(R.id.grid_full_preview_wallpaper_surface);
+ mGridOptionSurface.setVisibility(View.GONE);
final DisplayMetrics dm = getResources().getDisplayMetrics();
float screenAspectRatio = (float) dm.heightPixels / dm.widthPixels;
@@ -125,16 +148,19 @@
mCardView.setRadius(TileSizeCalculator.getPreviewCornerRadius(
getActivity(), mCardView.getMeasuredWidth()));
view.removeOnLayoutChangeListener(this);
- loadWallpaperBackground();
}
});
-
- // Needs to fetch for the result of #usesSurfaceView.
- mGridManager.fetchOptions(grids -> bindPreviewContent(), false);
return view;
}
@Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ updateWallpaperSurface();
+ updateWorkspaceSurface();
+ }
+
+ @Override
protected void onBottomActionBarReady(BottomActionBar bottomActionBar) {
bottomActionBar.bindBackButtonToSystemBackKey(getActivity());
bottomActionBar.showActionsOnly(APPLY);
@@ -142,6 +168,32 @@
bottomActionBar.show();
}
+ @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 onDestroyView() {
+ super.onDestroyView();
+ LiveTileOverlay.INSTANCE.detach(mHomePreview.getOverlay());
+ if (mWallpaperConnection != null) {
+ mWallpaperConnection.disconnect();
+ mWallpaperConnection = null;
+ }
+ }
+
private void finishActivityWithResultOk() {
Activity activity = requireActivity();
activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
@@ -151,33 +203,23 @@
activity.finish();
}
- private void loadWallpaperBackground() {
- if (mWallpaper != null && mCardView.getMeasuredWidth() > 0
- && mCardView.getMeasuredHeight() > 0) {
- mWallpaper.getThumbAsset(getContext()).decodeBitmap(mCardView.getMeasuredWidth(),
- mCardView.getMeasuredHeight(),
- bitmap -> {
- mCardBackground = new BitmapDrawable(getResources(), bitmap);
- bindWallpaperIfAvailable();
- });
- }
+ private void updateWallpaperSurface() {
+ mWallpaperSurface.setZOrderMediaOverlay(false);
+ mWallpaperSurface.getHolder().addCallback(mWallpaperSurfaceCallback);
}
- private void bindPreviewContent() {
- bindWallpaperIfAvailable();
- final boolean usesSurfaceViewForPreview = mGridManager.usesSurfaceView();
- mPreview.setVisibility(usesSurfaceViewForPreview ? View.GONE : View.VISIBLE);
- mPreviewSurface.setVisibility(usesSurfaceViewForPreview ? View.VISIBLE : View.GONE);
- if (usesSurfaceViewForPreview) {
- mPreviewSurface.setZOrderOnTop(true);
- mPreviewSurface.getHolder().addCallback(mSurfaceCallback);
+ private void updateWorkspaceSurface() {
+ if (mUsesSurfaceView) {
+ mGridOptionSurface.setZOrderOnTop(true);
+ mGridOptionSurface.getHolder().addCallback(mGridOptionSurfaceCallback);
+ mGridOptionSurface.setVisibility(View.VISIBLE);
} else {
final Asset previewAsset = new ContentUriAsset(
getContext(),
mGridOption.previewImageUri,
RequestOptions.fitCenterTransform());
previewAsset.loadDrawableWithTransition(getContext(),
- mPreview /* imageView */,
+ mHomePreview /* imageView */,
PREVIEW_FADE_DURATION_MS /* duration */,
null /* drawableLoadedListener */,
getResources().getColor(android.R.color.transparent,
@@ -185,14 +227,70 @@
}
}
- private void bindWallpaperIfAvailable() {
- if (mCardBackground != null) {
- mPreview.setBackground(mCardBackground);
- mPreviewSurface.setBackground(mCardBackground);
+ private void setUpWallpaperPreview() {
+ if (mWallpaper != null && mHomeImageWallpaper != null) {
+ boolean renderInImageWallpaperSurface = !(mWallpaper instanceof LiveWallpaperInfo);
+ mWallpaper.getThumbAsset(getContext())
+ .loadPreviewImage(getActivity(),
+ renderInImageWallpaperSurface ? mHomeImageWallpaper : mHomePreview,
+ getResources().getColor(R.color.secondary_color));
+ LiveTileOverlay.INSTANCE.detach(mHomePreview.getOverlay());
+ if (mWallpaper instanceof LiveWallpaperInfo) {
+ mWallpaper.getThumbAsset(getContext().getApplicationContext())
+ .loadPreviewImage(
+ getActivity(),
+ mHomeImageWallpaper,
+ getContext().getColor(R.color.secondary_color));
+ setUpLiveWallpaperPreview(mWallpaper);
+ } else {
+ if (mWallpaperConnection != null) {
+ mWallpaperConnection.disconnect();
+ mWallpaperConnection = null;
+ }
+ }
}
}
- private final SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {
+ private void setUpLiveWallpaperPreview(WallpaperInfo homeWallpaper) {
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
+ if (mWallpaperConnection != null) {
+ mWallpaperConnection.disconnect();
+ }
+
+ mHomePreview.getLocationOnScreen(mLivePreviewLocation);
+ mPreviewGlobalRect.set(0, 0, mHomePreview.getMeasuredWidth(),
+ mHomePreview.getMeasuredHeight());
+ mPreviewLocalRect.set(mPreviewGlobalRect);
+ mPreviewGlobalRect.offset(mLivePreviewLocation[0], mLivePreviewLocation[1]);
+
+ mWallpaperConnection = new WallpaperConnection(
+ getWallpaperIntent(homeWallpaper.getWallpaperComponent()), activity,
+ new WallpaperConnection.WallpaperConnectionListener() {
+ @Override
+ public void onEngineShown() {}
+ }, mPreviewGlobalRect);
+
+ LiveTileOverlay.INSTANCE.update(new RectF(mPreviewLocalRect), mCardView.getRadius());
+
+ mWallpaperConnection.setVisibility(true);
+ mHomePreview.post(() -> {
+ if (!mWallpaperConnection.connect()) {
+ mWallpaperConnection = null;
+ LiveTileOverlay.INSTANCE.detach(mHomePreview.getOverlay());
+ }
+ });
+ }
+
+ private Intent getWallpaperIntent(android.app.WallpaperInfo info) {
+ return new Intent(WallpaperService.SERVICE_INTERFACE)
+ .setClassName(info.getPackageName(), info.getServiceName());
+ }
+
+ private final SurfaceHolder.Callback mGridOptionSurfaceCallback = new SurfaceHolder.Callback() {
private Surface mLastSurface;
private Message mCallback;
@@ -202,10 +300,10 @@
if (mLastSurface != holder.getSurface()) {
mLastSurface = holder.getSurface();
Bundle result = mGridManager.renderPreview(
- SurfaceViewUtils.createSurfaceViewRequest(mPreviewSurface),
+ SurfaceViewUtils.createSurfaceViewRequest(mGridOptionSurface),
mGridOption.name);
if (result != null) {
- mPreviewSurface.setChildSurfacePackage(
+ mGridOptionSurface.setChildSurfacePackage(
SurfaceViewUtils.getSurfacePackage(result));
mCallback = SurfaceViewUtils.getCallback(result);
}
@@ -213,8 +311,7 @@
}
@Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {}
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
@@ -229,4 +326,35 @@
}
}
};
+
+ private final SurfaceHolder.Callback mWallpaperSurfaceCallback = new SurfaceHolder.Callback() {
+
+ private Surface mLastSurface;
+
+ @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());
+
+ SurfaceControlViewHost host = new SurfaceControlViewHost(getContext(),
+ getContext().getDisplay(), mWallpaperSurface.getHostToken());
+ host.setView(mHomeImageWallpaper, mHomeImageWallpaper.getWidth(),
+ mHomeImageWallpaper.getHeight());
+ mWallpaperSurface.setChildSurfacePackage(host.getSurfacePackage());
+ }
+ setUpWallpaperPreview();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {}
+ };
}