blob: 41a3847975219baa6e92c355eaad5df4e7ea89e2 [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 {
Vishnu Nair5cf253192019-11-07 15:33:20 -080042 private ViewRootImpl mViewRoot;
43 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 Carr59b18882019-12-18 00:38:40 -080053 */
Robert Carr87f5d2c2020-01-19 17:27:00 -080054 public static final class SurfacePackage implements Parcelable {
55 private final SurfaceControl mSurfaceControl;
Jackal Guoac234d62020-02-03 15:05:43 +080056 private final IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection;
Robert Carr59b18882019-12-18 00:38:40 -080057
Jackal Guoac234d62020-02-03 15:05:43 +080058 SurfacePackage(SurfaceControl sc, IAccessibilityEmbeddedConnection connection) {
Robert Carr59b18882019-12-18 00:38:40 -080059 mSurfaceControl = sc;
Jackal Guoac234d62020-02-03 15:05:43 +080060 mAccessibilityEmbeddedConnection = connection;
Robert Carr59b18882019-12-18 00:38:40 -080061 }
62
Robert Carr87f5d2c2020-01-19 17:27:00 -080063 private SurfacePackage(Parcel in) {
64 mSurfaceControl = new SurfaceControl();
65 mSurfaceControl.readFromParcel(in);
Jackal Guoac234d62020-02-03 15:05:43 +080066 mAccessibilityEmbeddedConnection = IAccessibilityEmbeddedConnection.Stub.asInterface(
67 in.readStrongBinder());
Robert Carr87f5d2c2020-01-19 17:27:00 -080068 }
69
70 /**
71 * Use {@link SurfaceView#setChildSurfacePackage} or manually fix
72 * accessibility (see SurfaceView implementation).
73 * @hide
74 */
Robert Carr59b18882019-12-18 00:38:40 -080075 public @NonNull SurfaceControl getSurfaceControl() {
76 return mSurfaceControl;
77 }
Robert Carr87f5d2c2020-01-19 17:27:00 -080078
Jackal Guoac234d62020-02-03 15:05:43 +080079 /**
80 * Gets an accessibility embedded connection interface for this SurfaceControlViewHost.
81 *
82 * @return {@link IAccessibilityEmbeddedConnection} interface.
83 * @hide
84 */
85 public IAccessibilityEmbeddedConnection getAccessibilityEmbeddedConnection() {
86 return mAccessibilityEmbeddedConnection;
87 }
88
Robert Carr87f5d2c2020-01-19 17:27:00 -080089 @Override
90 public int describeContents() {
91 return 0;
92 }
93
94 @Override
95 public void writeToParcel(@NonNull Parcel out, int flags) {
96 mSurfaceControl.writeToParcel(out, flags);
Jackal Guoac234d62020-02-03 15:05:43 +080097 out.writeStrongBinder(mAccessibilityEmbeddedConnection.asBinder());
Robert Carr87f5d2c2020-01-19 17:27:00 -080098 }
99
100 public static final @NonNull Creator<SurfacePackage> CREATOR
101 = new Creator<SurfacePackage>() {
102 public SurfacePackage createFromParcel(Parcel in) {
103 return new SurfacePackage(in);
104 }
105 public SurfacePackage[] newArray(int size) {
106 return new SurfacePackage[size];
107 }
108 };
Robert Carr59b18882019-12-18 00:38:40 -0800109 }
110
Evan Rosky3f09bb32019-10-09 19:27:52 -0700111 /** @hide */
Robert Carr59b18882019-12-18 00:38:40 -0800112 public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d,
Evan Rosky3f09bb32019-10-09 19:27:52 -0700113 @NonNull WindowlessWindowManager wwm) {
114 mWm = wwm;
115 mViewRoot = new ViewRootImpl(c, d, mWm);
Robert Carr6d16c8c2020-02-21 12:04:31 -0800116 mViewRoot.forceDisableBLAST();
Jackal Guoac234d62020-02-03 15:05:43 +0800117 mAccessibilityEmbeddedConnection = mViewRoot.getAccessibilityEmbeddedConnection();
Evan Rosky3f09bb32019-10-09 19:27:52 -0700118 }
119
Robert Carr87f5d2c2020-01-19 17:27:00 -0800120 /**
121 * Construct a new SurfaceControlViewHost. The root Surface will be
122 * allocated internally and is accessible via getSurfacePackage().
123 *
124 * The {@param hostToken} parameter, primarily used for ANR reporting,
125 * must be obtained from whomever will be hosting the embedded hierarchy.
126 * It's accessible from {@link SurfaceView#getHostToken}.
127 *
128 * @param context The Context object for your activity or application.
129 * @param display The Display the hierarchy will be placed on.
130 * @param hostToken The host token, as discussed above.
131 */
132 public SurfaceControlViewHost(@NonNull Context context, @NonNull Display display,
133 @Nullable IBinder hostToken) {
Robert Carr59b18882019-12-18 00:38:40 -0800134 mSurfaceControl = new SurfaceControl.Builder()
135 .setContainerLayer()
136 .setName("SurfaceControlViewHost")
137 .build();
Robert Carr87f5d2c2020-01-19 17:27:00 -0800138 mWm = new WindowlessWindowManager(context.getResources().getConfiguration(),
139 mSurfaceControl, hostToken);
140 mViewRoot = new ViewRootImpl(context, display, mWm);
Robert Carr6d16c8c2020-02-21 12:04:31 -0800141 mViewRoot.forceDisableBLAST();
Jackal Guoac234d62020-02-03 15:05:43 +0800142 mAccessibilityEmbeddedConnection = mViewRoot.getAccessibilityEmbeddedConnection();
Robert Carr9d431e12018-12-17 13:11:48 -0800143 }
144
Robert Carr87f5d2c2020-01-19 17:27:00 -0800145 /**
146 * Return a SurfacePackage for the root SurfaceControl of the embedded hierarchy.
147 * Rather than be directly reparented using {@link SurfaceControl.Transaction} this
148 * SurfacePackage should be passed to {@link SurfaceView#setChildSurfacePackage}
149 * which will not only reparent the Surface, but ensure the accessibility hierarchies
150 * are linked.
151 */
Robert Carr59b18882019-12-18 00:38:40 -0800152 public @Nullable SurfacePackage getSurfacePackage() {
Jackal Guoac234d62020-02-03 15:05:43 +0800153 if (mSurfaceControl != null && mAccessibilityEmbeddedConnection != null) {
154 return new SurfacePackage(mSurfaceControl, mAccessibilityEmbeddedConnection);
Robert Carr59b18882019-12-18 00:38:40 -0800155 } else {
156 return null;
157 }
158 }
159
Robert Carr87f5d2c2020-01-19 17:27:00 -0800160 /**
161 * @hide
162 */
Evan Rosky680377e2020-01-10 19:12:10 -0800163 @TestApi
Robert Carr271d9c72020-03-12 12:39:24 -0700164 public void setView(@NonNull View view, @NonNull WindowManager.LayoutParams attrs) {
165 Objects.requireNonNull(view);
Robert Carr9d431e12018-12-17 13:11:48 -0800166 mViewRoot.setView(view, attrs, null);
167 }
Robert Carrdf289462019-09-16 13:20:02 -0700168
Robert Carr87f5d2c2020-01-19 17:27:00 -0800169 /**
170 * Set the root view of the SurfaceControlViewHost. This view will render in to
171 * the SurfaceControl, and receive input based on the SurfaceControls positioning on
172 * screen. It will be laid as if it were in a window of the passed in width and height.
173 *
174 * @param view The View to add
175 * @param width The width to layout the View within, in pixels.
176 * @param height The height to layout the View within, in pixels.
177 */
Robert Carr271d9c72020-03-12 12:39:24 -0700178 public void setView(@NonNull View view, int width, int height) {
Robert Carr87f5d2c2020-01-19 17:27:00 -0800179 final WindowManager.LayoutParams lp =
180 new WindowManager.LayoutParams(width, height,
181 WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
Robert Carr271d9c72020-03-12 12:39:24 -0700182 setView(view, lp);
183 }
184
185 /**
186 * @return The view passed to setView, or null if none has been passed.
187 */
188 public @Nullable View getView() {
189 return mViewRoot.getView();
Robert Carr87f5d2c2020-01-19 17:27:00 -0800190 }
191
192 /**
193 * @hide
194 */
Evan Rosky680377e2020-01-10 19:12:10 -0800195 @TestApi
Robert Carrdf289462019-09-16 13:20:02 -0700196 public void relayout(WindowManager.LayoutParams attrs) {
197 mViewRoot.setLayoutParams(attrs, false);
198 mViewRoot.setReportNextDraw();
199 mWm.setCompletionCallback(mViewRoot.mWindow.asBinder(), (SurfaceControl.Transaction t) -> {
200 t.apply();
201 });
202 }
Vishnu Nair5cf253192019-11-07 15:33:20 -0800203
Robert Carr87f5d2c2020-01-19 17:27:00 -0800204 /**
205 * Modify the size of the root view.
206 *
207 * @param width Width in pixels
208 * @param height Height in pixels
209 */
210 public void relayout(int width, int height) {
211 final WindowManager.LayoutParams lp =
212 new WindowManager.LayoutParams(width, height,
213 WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
Robert Carr7fdf5d12020-02-27 12:11:16 -0800214 relayout(lp);
Robert Carr87f5d2c2020-01-19 17:27:00 -0800215 }
216
217 /**
218 * Trigger the tear down of the embedded view hierarchy and release the SurfaceControl.
219 * This will result in onDispatchedFromWindow being dispatched to the embedded view hierarchy
220 * and render the object unusable.
221 */
222 public void release() {
Vishnu Nair5cf253192019-11-07 15:33:20 -0800223 mViewRoot.dispatchDetachedFromWindow();
Robert Carr87f5d2c2020-01-19 17:27:00 -0800224 mSurfaceControl.release();
Vishnu Nair5cf253192019-11-07 15:33:20 -0800225 }
Evan Rosky3f09bb32019-10-09 19:27:52 -0700226
227 /**
228 * Tell this viewroot to clean itself up.
229 * @hide
230 */
231 public void die() {
232 mViewRoot.die(false /* immediate */);
233 }
Robert Carr9d431e12018-12-17 13:11:48 -0800234}