blob: 86a4fe170387f6ec7081a4f2bdc4d7d754579bf5 [file] [log] [blame]
Robert Carr9d431e12018-12-17 13:11:48 -08001/*
2 * Copyright (C) 2019 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 */
16
17package android.view;
18
Vishnu Nair5cf253192019-11-07 15:33:20 -080019import android.annotation.NonNull;
20import android.annotation.Nullable;
Robert Carr8833ae82019-09-16 13:20:02 -070021import android.annotation.TestApi;
Vishnu Nair5cf253192019-11-07 15:33:20 -080022import android.content.Context;
Robert Carr87f5d2c2020-01-19 17:27:00 -080023import android.graphics.PixelFormat;
Vishnu Nair5cf253192019-11-07 15:33:20 -080024import android.os.IBinder;
Robert Carr87f5d2c2020-01-19 17:27:00 -080025import android.os.Parcel;
26import android.os.Parcelable;
Jackal Guoac234d62020-02-03 15:05:43 +080027import android.view.accessibility.IAccessibilityEmbeddedConnection;
Robert Carr8833ae82019-09-16 13:20:02 -070028
Robert Carr271d9c72020-03-12 12:39:24 -070029import java.util.Objects;
30
Robert Carr9d431e12018-12-17 13:11:48 -080031/**
Robert Carr87f5d2c2020-01-19 17:27:00 -080032 * Utility class for adding a View hierarchy to a {@link SurfaceControl}. The View hierarchy
33 * will render in to a root SurfaceControl, and receive input based on the SurfaceControl's
34 * placement on-screen. The primary usage of this class is to embed a View hierarchy from
35 * one process in to another. After the SurfaceControlViewHost has been set up in the embedded
36 * content provider, we can send the {@link SurfaceControlViewHost.SurfacePackage}
37 * to the host process. The host process can then attach the hierarchy to a SurfaceView within
38 * its own by calling
39 * {@link SurfaceView#setChildSurfacePackage}.
Robert Carr9d431e12018-12-17 13:11:48 -080040 */
Robert Carr59b18882019-12-18 00:38:40 -080041public class SurfaceControlViewHost {
Evan Roskycff7ebb2020-04-22 16:54:49 -070042 private final ViewRootImpl mViewRoot;
Vishnu Nair5cf253192019-11-07 15:33:20 -080043 private WindowlessWindowManager mWm;
Evan Rosky3f09bb32019-10-09 19:27:52 -070044
Robert Carr59b18882019-12-18 00:38:40 -080045 private SurfaceControl mSurfaceControl;
Jackal Guoac234d62020-02-03 15:05:43 +080046 private IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection;
Robert Carr59b18882019-12-18 00:38:40 -080047
48 /**
Robert Carr87f5d2c2020-01-19 17:27:00 -080049 * Package encapsulating a Surface hierarchy which contains interactive view
50 * elements. It's expected to get this object from
51 * {@link SurfaceControlViewHost#getSurfacePackage} afterwards it can be embedded within
52 * a SurfaceView by calling {@link SurfaceView#setChildSurfacePackage}.
Robert Carr20c23962020-04-10 15:23:42 -070053 *
54 * Note that each {@link SurfacePackage} must be released by calling
55 * {@link SurfacePackage#release}. However, if you use the recommended flow,
56 * the framework will automatically handle the lifetime for you.
57 *
58 * 1. When sending the package to the remote process, return it from an AIDL method
59 * or manually use FLAG_WRITE_RETURN_VALUE in writeToParcel. This will automatically
60 * release the package in the local process.
61 * 2. In the remote process, consume the package using SurfaceView. This way the
62 * SurfaceView will take over the lifetime and call {@link SurfacePackage#release}
63 * for the user.
64 *
65 * One final note: The {@link SurfacePackage} lifetime is totally de-coupled
66 * from the lifetime of the underlying {@link SurfaceControlViewHost}. Regardless
67 * of the lifetime of the package the user should still call
68 * {@link SurfaceControlViewHost#release} when finished.
Robert Carr59b18882019-12-18 00:38:40 -080069 */
Robert Carr87f5d2c2020-01-19 17:27:00 -080070 public static final class SurfacePackage implements Parcelable {
Robert Carrd9c9c0c2020-03-17 11:31:55 -070071 private SurfaceControl mSurfaceControl;
Jackal Guoac234d62020-02-03 15:05:43 +080072 private final IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection;
Robert Carr59b18882019-12-18 00:38:40 -080073
Jackal Guoac234d62020-02-03 15:05:43 +080074 SurfacePackage(SurfaceControl sc, IAccessibilityEmbeddedConnection connection) {
Robert Carr59b18882019-12-18 00:38:40 -080075 mSurfaceControl = sc;
Jackal Guoac234d62020-02-03 15:05:43 +080076 mAccessibilityEmbeddedConnection = connection;
Robert Carr59b18882019-12-18 00:38:40 -080077 }
78
Robert Carr87f5d2c2020-01-19 17:27:00 -080079 private SurfacePackage(Parcel in) {
80 mSurfaceControl = new SurfaceControl();
81 mSurfaceControl.readFromParcel(in);
Jackal Guoac234d62020-02-03 15:05:43 +080082 mAccessibilityEmbeddedConnection = IAccessibilityEmbeddedConnection.Stub.asInterface(
83 in.readStrongBinder());
Robert Carr87f5d2c2020-01-19 17:27:00 -080084 }
85
86 /**
87 * Use {@link SurfaceView#setChildSurfacePackage} or manually fix
88 * accessibility (see SurfaceView implementation).
89 * @hide
90 */
Robert Carr59b18882019-12-18 00:38:40 -080091 public @NonNull SurfaceControl getSurfaceControl() {
92 return mSurfaceControl;
93 }
Robert Carr87f5d2c2020-01-19 17:27:00 -080094
Jackal Guoac234d62020-02-03 15:05:43 +080095 /**
96 * Gets an accessibility embedded connection interface for this SurfaceControlViewHost.
97 *
98 * @return {@link IAccessibilityEmbeddedConnection} interface.
99 * @hide
100 */
101 public IAccessibilityEmbeddedConnection getAccessibilityEmbeddedConnection() {
102 return mAccessibilityEmbeddedConnection;
103 }
104
Robert Carr87f5d2c2020-01-19 17:27:00 -0800105 @Override
106 public int describeContents() {
107 return 0;
108 }
109
110 @Override
111 public void writeToParcel(@NonNull Parcel out, int flags) {
112 mSurfaceControl.writeToParcel(out, flags);
Jackal Guoac234d62020-02-03 15:05:43 +0800113 out.writeStrongBinder(mAccessibilityEmbeddedConnection.asBinder());
Robert Carr87f5d2c2020-01-19 17:27:00 -0800114 }
115
Robert Carrd9c9c0c2020-03-17 11:31:55 -0700116 /**
Robert Carr5af7d622020-03-17 12:04:20 -0700117 * Release the {@link SurfaceControl} associated with this package.
118 * It's not necessary to call this if you pass the package to
119 * {@link SurfaceView#setChildSurfacePackage} as {@link SurfaceView} will
120 * take ownership in that case.
Robert Carrd9c9c0c2020-03-17 11:31:55 -0700121 */
122 public void release() {
123 if (mSurfaceControl != null) {
124 mSurfaceControl.release();
125 }
126 mSurfaceControl = null;
127 }
128
Robert Carr87f5d2c2020-01-19 17:27:00 -0800129 public static final @NonNull Creator<SurfacePackage> CREATOR
130 = new Creator<SurfacePackage>() {
131 public SurfacePackage createFromParcel(Parcel in) {
132 return new SurfacePackage(in);
133 }
134 public SurfacePackage[] newArray(int size) {
135 return new SurfacePackage[size];
136 }
137 };
Robert Carr59b18882019-12-18 00:38:40 -0800138 }
139
Evan Rosky3f09bb32019-10-09 19:27:52 -0700140 /** @hide */
Robert Carr59b18882019-12-18 00:38:40 -0800141 public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d,
Evan Rosky3f09bb32019-10-09 19:27:52 -0700142 @NonNull WindowlessWindowManager wwm) {
Tony Huang89d580c2020-03-26 14:10:26 +0800143 this(c, d, wwm, false /* useSfChoreographer */);
144 }
145
146 /** @hide */
147 public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d,
148 @NonNull WindowlessWindowManager wwm, boolean useSfChoreographer) {
Evan Rosky3f09bb32019-10-09 19:27:52 -0700149 mWm = wwm;
Tony Huang89d580c2020-03-26 14:10:26 +0800150 mViewRoot = new ViewRootImpl(c, d, mWm, useSfChoreographer);
Robert Carr6d16c8c2020-02-21 12:04:31 -0800151 mViewRoot.forceDisableBLAST();
Jackal Guoac234d62020-02-03 15:05:43 +0800152 mAccessibilityEmbeddedConnection = mViewRoot.getAccessibilityEmbeddedConnection();
Evan Rosky3f09bb32019-10-09 19:27:52 -0700153 }
154
Robert Carr87f5d2c2020-01-19 17:27:00 -0800155 /**
156 * Construct a new SurfaceControlViewHost. The root Surface will be
157 * allocated internally and is accessible via getSurfacePackage().
158 *
159 * The {@param hostToken} parameter, primarily used for ANR reporting,
160 * must be obtained from whomever will be hosting the embedded hierarchy.
161 * It's accessible from {@link SurfaceView#getHostToken}.
162 *
163 * @param context The Context object for your activity or application.
164 * @param display The Display the hierarchy will be placed on.
165 * @param hostToken The host token, as discussed above.
166 */
167 public SurfaceControlViewHost(@NonNull Context context, @NonNull Display display,
168 @Nullable IBinder hostToken) {
Robert Carr59b18882019-12-18 00:38:40 -0800169 mSurfaceControl = new SurfaceControl.Builder()
170 .setContainerLayer()
171 .setName("SurfaceControlViewHost")
172 .build();
Robert Carr87f5d2c2020-01-19 17:27:00 -0800173 mWm = new WindowlessWindowManager(context.getResources().getConfiguration(),
174 mSurfaceControl, hostToken);
175 mViewRoot = new ViewRootImpl(context, display, mWm);
Robert Carr6d16c8c2020-02-21 12:04:31 -0800176 mViewRoot.forceDisableBLAST();
Jackal Guoac234d62020-02-03 15:05:43 +0800177 mAccessibilityEmbeddedConnection = mViewRoot.getAccessibilityEmbeddedConnection();
Robert Carr9d431e12018-12-17 13:11:48 -0800178 }
179
Robert Carr87f5d2c2020-01-19 17:27:00 -0800180 /**
Robert Carr7a31b8b2020-06-19 13:14:00 -0700181 * @hide
182 */
183 @Override
184 protected void finalize() throws Throwable {
185 // We aren't on the UI thread here so we need to pass false to
186 // doDie
187 mViewRoot.die(false /* immediate */);
188 }
189
190
191 /**
Robert Carr87f5d2c2020-01-19 17:27:00 -0800192 * Return a SurfacePackage for the root SurfaceControl of the embedded hierarchy.
193 * Rather than be directly reparented using {@link SurfaceControl.Transaction} this
194 * SurfacePackage should be passed to {@link SurfaceView#setChildSurfacePackage}
195 * which will not only reparent the Surface, but ensure the accessibility hierarchies
196 * are linked.
197 */
Robert Carr59b18882019-12-18 00:38:40 -0800198 public @Nullable SurfacePackage getSurfacePackage() {
Jackal Guoac234d62020-02-03 15:05:43 +0800199 if (mSurfaceControl != null && mAccessibilityEmbeddedConnection != null) {
200 return new SurfacePackage(mSurfaceControl, mAccessibilityEmbeddedConnection);
Robert Carr59b18882019-12-18 00:38:40 -0800201 } else {
202 return null;
203 }
204 }
205
Robert Carr87f5d2c2020-01-19 17:27:00 -0800206 /**
207 * @hide
208 */
Evan Rosky680377e2020-01-10 19:12:10 -0800209 @TestApi
Robert Carr271d9c72020-03-12 12:39:24 -0700210 public void setView(@NonNull View view, @NonNull WindowManager.LayoutParams attrs) {
211 Objects.requireNonNull(view);
Robert Carr9d431e12018-12-17 13:11:48 -0800212 mViewRoot.setView(view, attrs, null);
213 }
Robert Carrdf289462019-09-16 13:20:02 -0700214
Robert Carr87f5d2c2020-01-19 17:27:00 -0800215 /**
216 * Set the root view of the SurfaceControlViewHost. This view will render in to
217 * the SurfaceControl, and receive input based on the SurfaceControls positioning on
218 * screen. It will be laid as if it were in a window of the passed in width and height.
219 *
220 * @param view The View to add
221 * @param width The width to layout the View within, in pixels.
222 * @param height The height to layout the View within, in pixels.
223 */
Robert Carr271d9c72020-03-12 12:39:24 -0700224 public void setView(@NonNull View view, int width, int height) {
Robert Carr87f5d2c2020-01-19 17:27:00 -0800225 final WindowManager.LayoutParams lp =
226 new WindowManager.LayoutParams(width, height,
227 WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
Robert Carr4d5e6302020-03-23 12:47:06 -0700228 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
Robert Carr271d9c72020-03-12 12:39:24 -0700229 setView(view, lp);
230 }
231
232 /**
233 * @return The view passed to setView, or null if none has been passed.
234 */
235 public @Nullable View getView() {
236 return mViewRoot.getView();
Robert Carr87f5d2c2020-01-19 17:27:00 -0800237 }
238
239 /**
Evan Roskycff7ebb2020-04-22 16:54:49 -0700240 * @return the ViewRootImpl wrapped by this host.
241 * @hide
242 */
243 public IWindow getWindowToken() {
244 return mViewRoot.mWindow;
245 }
246
247 /**
Evan Rosky12837282020-04-27 19:12:25 -0700248 * @return the WindowlessWindowManager instance that this host is attached to.
249 * @hide
250 */
251 public @NonNull WindowlessWindowManager getWindowlessWM() {
252 return mWm;
253 }
254
255 /**
Robert Carr87f5d2c2020-01-19 17:27:00 -0800256 * @hide
257 */
Evan Rosky680377e2020-01-10 19:12:10 -0800258 @TestApi
Robert Carrdf289462019-09-16 13:20:02 -0700259 public void relayout(WindowManager.LayoutParams attrs) {
260 mViewRoot.setLayoutParams(attrs, false);
261 mViewRoot.setReportNextDraw();
262 mWm.setCompletionCallback(mViewRoot.mWindow.asBinder(), (SurfaceControl.Transaction t) -> {
263 t.apply();
264 });
265 }
Vishnu Nair5cf253192019-11-07 15:33:20 -0800266
Robert Carr87f5d2c2020-01-19 17:27:00 -0800267 /**
268 * Modify the size of the root view.
269 *
270 * @param width Width in pixels
271 * @param height Height in pixels
272 */
273 public void relayout(int width, int height) {
274 final WindowManager.LayoutParams lp =
275 new WindowManager.LayoutParams(width, height,
276 WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
Robert Carr7fdf5d12020-02-27 12:11:16 -0800277 relayout(lp);
Robert Carr87f5d2c2020-01-19 17:27:00 -0800278 }
279
280 /**
281 * Trigger the tear down of the embedded view hierarchy and release the SurfaceControl.
282 * This will result in onDispatchedFromWindow being dispatched to the embedded view hierarchy
283 * and render the object unusable.
284 */
285 public void release() {
Robert Carr86440502020-05-04 11:23:29 -0700286 // ViewRoot will release mSurfaceControl for us.
Robert Carr5409e242020-06-19 13:08:22 -0700287 mViewRoot.die(true /* immediate */);
Vishnu Nair5cf253192019-11-07 15:33:20 -0800288 }
Robert Carr9d431e12018-12-17 13:11:48 -0800289}