| /* |
| * 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.customization.picker; |
| |
| import static android.view.View.MeasureSpec.EXACTLY; |
| import static android.view.View.MeasureSpec.makeMeasureSpec; |
| |
| import android.app.Activity; |
| import android.content.Intent; |
| import android.graphics.Rect; |
| import android.graphics.RectF; |
| import android.service.wallpaper.WallpaperService; |
| import android.view.Surface; |
| import android.view.SurfaceControlViewHost; |
| import android.view.SurfaceHolder; |
| import android.view.SurfaceView; |
| import android.view.ViewGroup; |
| import android.widget.ImageView; |
| |
| import androidx.annotation.MainThread; |
| import androidx.cardview.widget.CardView; |
| import androidx.core.content.ContextCompat; |
| import androidx.lifecycle.Lifecycle; |
| import androidx.lifecycle.LifecycleObserver; |
| import androidx.lifecycle.OnLifecycleEvent; |
| |
| import com.android.wallpaper.R; |
| import com.android.wallpaper.model.LiveWallpaperInfo; |
| import com.android.wallpaper.model.WallpaperInfo; |
| import com.android.wallpaper.util.ScreenSizeCalculator; |
| import com.android.wallpaper.util.SizeCalculator; |
| import com.android.wallpaper.util.WallpaperConnection; |
| import com.android.wallpaper.widget.LiveTileOverlay; |
| |
| /** A class to load the wallpaper to the view. */ |
| public class WallpaperPreviewer implements LifecycleObserver { |
| |
| private final Rect mPreviewLocalRect = new Rect(); |
| private final Rect mPreviewGlobalRect = new Rect(); |
| private final int[] mLivePreviewLocation = new int[2]; |
| |
| private final Activity mActivity; |
| private final ImageView mHomePreview; |
| private final SurfaceView mWallpaperSurface; |
| |
| private WallpaperInfo mWallpaper; |
| 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; |
| |
| public WallpaperPreviewer(Lifecycle lifecycle, Activity activity, ImageView homePreview, |
| SurfaceView wallpaperSurface) { |
| lifecycle.addObserver(this); |
| |
| mActivity = activity; |
| mHomePreview = homePreview; |
| mWallpaperSurface = wallpaperSurface; |
| mWallpaperSurface.setZOrderMediaOverlay(false); |
| mWallpaperSurface.getHolder().addCallback(mSurfaceCallback); |
| } |
| |
| @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) |
| @MainThread |
| public void onResume() { |
| if (mWallpaperConnection != null) { |
| mWallpaperConnection.setVisibility(true); |
| } |
| } |
| |
| @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) |
| @MainThread |
| public void onPause() { |
| if (mWallpaperConnection != null) { |
| mWallpaperConnection.setVisibility(false); |
| } |
| } |
| |
| @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) |
| @MainThread |
| public void onDestroy() { |
| LiveTileOverlay.INSTANCE.detach(mHomePreview.getOverlay()); |
| if (mWallpaperConnection != null) { |
| mWallpaperConnection.disconnect(); |
| mWallpaperConnection = null; |
| } |
| |
| mWallpaperSurface.getHolder().removeCallback(mSurfaceCallback); |
| Surface surface = mWallpaperSurface.getHolder().getSurface(); |
| if (surface != null) { |
| surface.release(); |
| } |
| } |
| |
| /** Updates the preview card view radius to match the device radius. */ |
| public void updatePreviewCardRadius() { |
| final float screenAspectRatio = |
| ScreenSizeCalculator.getInstance().getScreenAspectRatio(mActivity); |
| CardView cardView = (CardView) mHomePreview.getParent(); |
| final int cardWidth = (int) (cardView.getMeasuredHeight() / screenAspectRatio); |
| ViewGroup.LayoutParams layoutParams = cardView.getLayoutParams(); |
| layoutParams.width = cardWidth; |
| cardView.setLayoutParams(layoutParams); |
| cardView.setRadius(SizeCalculator.getPreviewCornerRadius(mActivity, cardWidth)); |
| } |
| |
| /** Loads the wallpaper. */ |
| public void setWallpaper(WallpaperInfo wallpaperInfo) { |
| mWallpaper = wallpaperInfo; |
| setUpWallpaperPreview(); |
| } |
| |
| private void setUpWallpaperPreview() { |
| if (mWallpaper != null && mHomeImageWallpaper != null) { |
| boolean renderInImageWallpaperSurface = !(mWallpaper instanceof LiveWallpaperInfo); |
| mWallpaper.getThumbAsset(mActivity.getApplicationContext()) |
| .loadPreviewImage(mActivity, |
| renderInImageWallpaperSurface ? mHomeImageWallpaper : mHomePreview, |
| mActivity.getResources().getColor(R.color.secondary_color)); |
| LiveTileOverlay.INSTANCE.detach(mHomePreview.getOverlay()); |
| if (mWallpaper instanceof LiveWallpaperInfo) { |
| mWallpaper.getThumbAsset(mActivity.getApplicationContext()) |
| .loadPreviewImage( |
| mActivity, |
| mHomeImageWallpaper, |
| mActivity.getColor(R.color.secondary_color)); |
| setUpLiveWallpaperPreview(mWallpaper); |
| } else { |
| if (mWallpaperConnection != null) { |
| mWallpaperConnection.disconnect(); |
| mWallpaperConnection = null; |
| } |
| } |
| } |
| } |
| |
| private void setUpLiveWallpaperPreview(WallpaperInfo homeWallpaper) { |
| if (mActivity == null || mActivity.isFinishing()) { |
| 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()), mActivity, |
| /* listener= */ null, mPreviewGlobalRect); |
| |
| LiveTileOverlay.INSTANCE.update(new RectF(mPreviewLocalRect), |
| ((CardView) mHomePreview.getParent()).getRadius()); |
| |
| mWallpaperConnection.setVisibility(true); |
| mHomePreview.post(() -> { |
| if (mWallpaperConnection != null && !mWallpaperConnection.connect()) { |
| mWallpaperConnection = null; |
| LiveTileOverlay.INSTANCE.detach(mHomePreview.getOverlay()); |
| } |
| }); |
| } |
| |
| private final SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() { |
| |
| private Surface mLastSurface; |
| |
| @Override |
| public void surfaceCreated(SurfaceHolder holder) { |
| if (mLastSurface != holder.getSurface()) { |
| mLastSurface = holder.getSurface(); |
| mHomeImageWallpaper = new ImageView(mActivity); |
| mHomeImageWallpaper.setBackgroundColor( |
| ContextCompat.getColor(mActivity, 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(mActivity, |
| mActivity.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) {} |
| }; |
| |
| private static Intent getWallpaperIntent(android.app.WallpaperInfo info) { |
| return new Intent(WallpaperService.SERVICE_INTERFACE) |
| .setClassName(info.getPackageName(), info.getServiceName()); |
| } |
| } |