blob: 26619235a826e1c18be1c8c9a3f6e1e872292361 [file] [log] [blame]
Tracy Zhou3eb234c2020-05-05 15:17:33 -07001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.wallpaper.picker;
17
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070018import android.app.WallpaperColors;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070019import android.content.Context;
20import android.os.Bundle;
21import android.os.Message;
22import android.os.RemoteException;
Santiago Etchebehere616808f2021-05-19 16:10:07 -070023import android.util.Log;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070024import android.view.Surface;
25import android.view.SurfaceHolder;
26import android.view.SurfaceView;
27
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070028import androidx.annotation.Nullable;
29
Tracy Zhou3eb234c2020-05-05 15:17:33 -070030import com.android.wallpaper.R;
31import com.android.wallpaper.util.PreviewUtils;
32import com.android.wallpaper.util.SurfaceViewUtils;
33
Santiago Etchebehere8b495672021-05-29 11:37:46 -070034import java.util.concurrent.atomic.AtomicBoolean;
35
Tracy Zhou3eb234c2020-05-05 15:17:33 -070036/** A surface holder callback that renders user's workspace on the passed in surface view. */
37public class WorkspaceSurfaceHolderCallback implements SurfaceHolder.Callback {
38
Santiago Etchebehere8b495672021-05-29 11:37:46 -070039 /**
40 * Listener to be called when workspace surface is updated with a new Surface Package.
41 */
42 public interface WorkspaceRenderListener {
43 /**
44 * Called on the main thread after the workspace surface is updated from the provider
45 */
46 void onWorkspaceRendered();
47 }
48
Santiago Etchebehere616808f2021-05-19 16:10:07 -070049 private static final String TAG = "WsSurfaceHolderCallback";
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070050 private static final String KEY_WALLPAPER_COLORS = "wallpaper_colors";
Tracy Zhou3eb234c2020-05-05 15:17:33 -070051 private final SurfaceView mWorkspaceSurface;
52 private final PreviewUtils mPreviewUtils;
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070053 private final boolean mShouldUseWallpaperColors;
Santiago Etchebehere8b495672021-05-29 11:37:46 -070054 private final AtomicBoolean mRequestPending = new AtomicBoolean(false);
Tracy Zhou3eb234c2020-05-05 15:17:33 -070055
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070056 private WallpaperColors mWallpaperColors;
57 private boolean mIsWallpaperColorsReady;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070058 private Surface mLastSurface;
59 private Message mCallback;
Santiago Etchebehere8b495672021-05-29 11:37:46 -070060 private WorkspaceRenderListener mListener;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070061
Tracy Zhoua63c9862020-06-22 01:05:14 -070062 private boolean mNeedsToCleanUp;
63
chihhangchuangc0e80c12020-06-05 16:48:49 +080064 public WorkspaceSurfaceHolderCallback(SurfaceView workspaceSurface, Context context) {
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070065 this(workspaceSurface, context, false);
66 }
67
68 /**
69 * Creates a new instance of {@link WorkspaceSurfaceHolderCallback} specifying if wallpaper
70 * colors should be used to preview the workspace.
71 *
72 * @param shouldUseWallpaperColors if true, the workspace preview won't be requested until both
73 * the surface is created and wallpaper colors are set via
74 * {@link #setWallpaperColors(WallpaperColors)}
75 */
76 public WorkspaceSurfaceHolderCallback(SurfaceView workspaceSurface, Context context,
77 boolean shouldUseWallpaperColors) {
Tracy Zhou3eb234c2020-05-05 15:17:33 -070078 mWorkspaceSurface = workspaceSurface;
79 mPreviewUtils = new PreviewUtils(context,
80 context.getString(R.string.grid_control_metadata_name));
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070081 mShouldUseWallpaperColors = shouldUseWallpaperColors;
Tracy Zhou3eb234c2020-05-05 15:17:33 -070082 }
83
84 @Override
85 public void surfaceCreated(SurfaceHolder holder) {
86 if (mPreviewUtils.supportsPreview() && mLastSurface != holder.getSurface()) {
87 mLastSurface = holder.getSurface();
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070088 maybeRenderPreview();
89 }
90 }
Tracy Zhoua63c9862020-06-22 01:05:14 -070091
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070092 /**
93 * Set the current wallpaper's colors. This method must be called if this instance was created
Santiago Etchebehere62287292021-04-30 15:53:22 -070094 * with shouldUseWallpaperColors = true (even with {@code null} colors), and conversely, calling
95 * this method when {@code shouldUseWallpaperColors = false} will be a no-op.
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070096 *
97 * @param colors WallpaperColors extracted from the current wallpaper preview, or {@code null}
98 * if none are available.
99 * @see #WorkspaceSurfaceHolderCallback(SurfaceView, Context, boolean)
100 */
101 public void setWallpaperColors(@Nullable WallpaperColors colors) {
Santiago Etchebehere62287292021-04-30 15:53:22 -0700102 if (!mShouldUseWallpaperColors) {
103 return;
104 }
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -0700105 mWallpaperColors = colors;
106 mIsWallpaperColorsReady = true;
107 maybeRenderPreview();
108 }
109
Santiago Etchebehere8b495672021-05-29 11:37:46 -0700110 public void setListener(WorkspaceRenderListener listener) {
111 mListener = listener;
112 }
113
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -0700114 private void maybeRenderPreview() {
115 if ((mShouldUseWallpaperColors && !mIsWallpaperColorsReady) || mLastSurface == null) {
116 return;
117 }
Santiago Etchebehere8b495672021-05-29 11:37:46 -0700118
119 mRequestPending.set(true);
Santiago Etchebeheref99ff202021-06-01 15:19:22 -0700120 requestPreview(mWorkspaceSurface, (result) -> {
Santiago Etchebehere8b495672021-05-29 11:37:46 -0700121 mRequestPending.set(false);
122 if (result != null && mLastSurface != null) {
Santiago Etchebehere3e452912021-06-07 18:10:30 -0700123 mWorkspaceSurface.setChildSurfacePackage(
124 SurfaceViewUtils.getSurfacePackage(result));
Santiago Etchebehere8b495672021-05-29 11:37:46 -0700125
Ching-Sung Li724a03c2021-05-27 16:05:05 +0800126 mCallback = SurfaceViewUtils.getCallback(result);
127
128 if (mNeedsToCleanUp) {
129 cleanUp();
Santiago Etchebehere8b495672021-05-29 11:37:46 -0700130 } else if (mListener != null) {
131 mListener.onWorkspaceRendered();
Ching-Sung Li724a03c2021-05-27 16:05:05 +0800132 }
133 }
134 });
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700135 }
136
137 @Override
138 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
139
140 @Override
Santiago Etchebeheref99ff202021-06-01 15:19:22 -0700141 public void surfaceDestroyed(SurfaceHolder holder) {
Santiago Etchebeheref99ff202021-06-01 15:19:22 -0700142 }
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700143
144 public void cleanUp() {
145 if (mCallback != null) {
146 try {
147 mCallback.replyTo.send(mCallback);
Santiago Etchebehere8b495672021-05-29 11:37:46 -0700148 mNeedsToCleanUp = false;
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700149 } catch (RemoteException e) {
Santiago Etchebehere616808f2021-05-19 16:10:07 -0700150 Log.w(TAG, "Couldn't call cleanup on workspace preview", e);
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700151 } finally {
152 mCallback = null;
153 }
Tracy Zhoua63c9862020-06-22 01:05:14 -0700154 } else {
Santiago Etchebehere8b495672021-05-29 11:37:46 -0700155 if (mRequestPending.get()) {
156 mNeedsToCleanUp = true;
157 }
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700158 }
159 }
chihhangchuangc0e80c12020-06-05 16:48:49 +0800160
161 public void resetLastSurface() {
162 mLastSurface = null;
163 }
164
Santiago Etchebeheref99ff202021-06-01 15:19:22 -0700165 protected void requestPreview(SurfaceView workspaceSurface,
166 PreviewUtils.WorkspacePreviewCallback callback) {
James O'Leary0c26b0e2021-06-21 09:45:24 -0400167 if (workspaceSurface.getDisplay() == null) {
168 Log.w(TAG,
169 "No display ID, avoiding asking for workspace preview, lest WallpaperPicker "
170 + "crash");
171 return;
172 }
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -0700173 Bundle request = SurfaceViewUtils.createSurfaceViewRequest(workspaceSurface);
174 if (mWallpaperColors != null) {
175 request.putParcelable(KEY_WALLPAPER_COLORS, mWallpaperColors);
176 }
Santiago Etchebeheref99ff202021-06-01 15:19:22 -0700177 mPreviewUtils.renderPreview(request, callback);
chihhangchuangc0e80c12020-06-05 16:48:49 +0800178 }
Tracy Zhou3eb234c2020-05-05 15:17:33 -0700179}