blob: 7086dc09c8a30bf0fade08b66b2d0d90ee24444d [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 /**
181 * Return a SurfacePackage for the root SurfaceControl of the embedded hierarchy.
182 * Rather than be directly reparented using {@link SurfaceControl.Transaction} this
183 * SurfacePackage should be passed to {@link SurfaceView#setChildSurfacePackage}
184 * which will not only reparent the Surface, but ensure the accessibility hierarchies
185 * are linked.
186 */
Robert Carr59b18882019-12-18 00:38:40 -0800187 public @Nullable SurfacePackage getSurfacePackage() {
Jackal Guoac234d62020-02-03 15:05:43 +0800188 if (mSurfaceControl != null && mAccessibilityEmbeddedConnection != null) {
189 return new SurfacePackage(mSurfaceControl, mAccessibilityEmbeddedConnection);
Robert Carr59b18882019-12-18 00:38:40 -0800190 } else {
191 return null;
192 }
193 }
194
Robert Carr87f5d2c2020-01-19 17:27:00 -0800195 /**
196 * @hide
197 */
Evan Rosky680377e2020-01-10 19:12:10 -0800198 @TestApi
Robert Carr271d9c72020-03-12 12:39:24 -0700199 public void setView(@NonNull View view, @NonNull WindowManager.LayoutParams attrs) {
200 Objects.requireNonNull(view);
Robert Carr9d431e12018-12-17 13:11:48 -0800201 mViewRoot.setView(view, attrs, null);
202 }
Robert Carrdf289462019-09-16 13:20:02 -0700203
Robert Carr87f5d2c2020-01-19 17:27:00 -0800204 /**
205 * Set the root view of the SurfaceControlViewHost. This view will render in to
206 * the SurfaceControl, and receive input based on the SurfaceControls positioning on
207 * screen. It will be laid as if it were in a window of the passed in width and height.
208 *
209 * @param view The View to add
210 * @param width The width to layout the View within, in pixels.
211 * @param height The height to layout the View within, in pixels.
212 */
Robert Carr271d9c72020-03-12 12:39:24 -0700213 public void setView(@NonNull View view, int width, int height) {
Robert Carr87f5d2c2020-01-19 17:27:00 -0800214 final WindowManager.LayoutParams lp =
215 new WindowManager.LayoutParams(width, height,
216 WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
Robert Carr4d5e6302020-03-23 12:47:06 -0700217 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
Robert Carr271d9c72020-03-12 12:39:24 -0700218 setView(view, lp);
219 }
220
221 /**
222 * @return The view passed to setView, or null if none has been passed.
223 */
224 public @Nullable View getView() {
225 return mViewRoot.getView();
Robert Carr87f5d2c2020-01-19 17:27:00 -0800226 }
227
228 /**
Evan Roskycff7ebb2020-04-22 16:54:49 -0700229 * @return the ViewRootImpl wrapped by this host.
230 * @hide
231 */
232 public IWindow getWindowToken() {
233 return mViewRoot.mWindow;
234 }
235
236 /**
Evan Rosky12837282020-04-27 19:12:25 -0700237 * @return the WindowlessWindowManager instance that this host is attached to.
238 * @hide
239 */
240 public @NonNull WindowlessWindowManager getWindowlessWM() {
241 return mWm;
242 }
243
244 /**
Robert Carr87f5d2c2020-01-19 17:27:00 -0800245 * @hide
246 */
Evan Rosky680377e2020-01-10 19:12:10 -0800247 @TestApi
Robert Carrdf289462019-09-16 13:20:02 -0700248 public void relayout(WindowManager.LayoutParams attrs) {
249 mViewRoot.setLayoutParams(attrs, false);
250 mViewRoot.setReportNextDraw();
251 mWm.setCompletionCallback(mViewRoot.mWindow.asBinder(), (SurfaceControl.Transaction t) -> {
252 t.apply();
253 });
254 }
Vishnu Nair5cf253192019-11-07 15:33:20 -0800255
Robert Carr87f5d2c2020-01-19 17:27:00 -0800256 /**
257 * Modify the size of the root view.
258 *
259 * @param width Width in pixels
260 * @param height Height in pixels
261 */
262 public void relayout(int width, int height) {
263 final WindowManager.LayoutParams lp =
264 new WindowManager.LayoutParams(width, height,
265 WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
Robert Carr7fdf5d12020-02-27 12:11:16 -0800266 relayout(lp);
Robert Carr87f5d2c2020-01-19 17:27:00 -0800267 }
268
269 /**
270 * Trigger the tear down of the embedded view hierarchy and release the SurfaceControl.
271 * This will result in onDispatchedFromWindow being dispatched to the embedded view hierarchy
272 * and render the object unusable.
273 */
274 public void release() {
Robert Carr86440502020-05-04 11:23:29 -0700275 // ViewRoot will release mSurfaceControl for us.
Robert Carrbb7964d2020-03-18 14:24:38 -0700276 mViewRoot.die(false /* immediate */);
Vishnu Nair5cf253192019-11-07 15:33:20 -0800277 }
Evan Rosky3f09bb32019-10-09 19:27:52 -0700278
279 /**
280 * Tell this viewroot to clean itself up.
281 * @hide
282 */
283 public void die() {
284 mViewRoot.die(false /* immediate */);
285 }
Robert Carr9d431e12018-12-17 13:11:48 -0800286}