blob: 144f8e3a7108d55fe3faeef531bfa099d973d781 [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
19import android.content.res.Configuration;
Robert Carr3e722b12019-08-27 13:39:58 -070020import android.graphics.PixelFormat;
Valerie Hau30360552020-01-14 16:12:01 -080021import android.graphics.Point;
Robert Carr9d431e12018-12-17 13:11:48 -080022import android.graphics.Rect;
23import android.os.IBinder;
24import android.os.RemoteException;
Robert Carr9d431e12018-12-17 13:11:48 -080025import android.util.Log;
Jiyong Park624b3932019-07-10 17:53:41 +090026import android.util.MergedConfiguration;
Robert Carr9d431e12018-12-17 13:11:48 -080027import android.view.IWindowSession;
Robert Carr9d431e12018-12-17 13:11:48 -080028
29import java.util.HashMap;
30
31/**
32* A simplistic implementation of IWindowSession. Rather than managing Surfaces
33* as children of the display, it manages Surfaces as children of a given root.
34*
35* By parcelling the root surface, the app can offer another app content for embedding.
36* @hide
37*/
Evan Rosky3f09bb32019-10-09 19:27:52 -070038public class WindowlessWindowManager implements IWindowSession {
Robert Carr9d431e12018-12-17 13:11:48 -080039 private final static String TAG = "WindowlessWindowManager";
40
Robert Carr650e7182019-09-24 14:11:24 -070041 private class State {
42 SurfaceControl mSurfaceControl;
43 WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
Evan Rosky680377e2020-01-10 19:12:10 -080044 int mDisplayId;
45 IBinder mInputChannelToken;
46 State(SurfaceControl sc, WindowManager.LayoutParams p, int displayId,
47 IBinder inputChannelToken) {
Robert Carr650e7182019-09-24 14:11:24 -070048 mSurfaceControl = sc;
49 mParams.copyFrom(p);
Evan Rosky680377e2020-01-10 19:12:10 -080050 mDisplayId = displayId;
51 mInputChannelToken = inputChannelToken;
Robert Carr650e7182019-09-24 14:11:24 -070052 }
53 };
Evan Rosky3f09bb32019-10-09 19:27:52 -070054
Robert Carr9d431e12018-12-17 13:11:48 -080055 /**
56 * Used to store SurfaceControl we've built for clients to
57 * reconfigure them if relayout is called.
58 */
Robert Carr650e7182019-09-24 14:11:24 -070059 final HashMap<IBinder, State> mStateForWindow = new HashMap<IBinder, State>();
Robert Carrdf289462019-09-16 13:20:02 -070060
61 public interface ResizeCompleteCallback {
62 public void finished(SurfaceControl.Transaction completion);
63 }
64
65 final HashMap<IBinder, ResizeCompleteCallback> mResizeCompletionForWindow =
66 new HashMap<IBinder, ResizeCompleteCallback>();
67
Vishnu Nair5cf253192019-11-07 15:33:20 -080068 private final SurfaceSession mSurfaceSession = new SurfaceSession();
69 private final SurfaceControl mRootSurface;
70 private final Configuration mConfiguration;
71 private final IWindowSession mRealWm;
72 private final IBinder mHostInputToken;
Robert Carr9d431e12018-12-17 13:11:48 -080073
74 private int mForceHeight = -1;
75 private int mForceWidth = -1;
76
Evan Rosky3f09bb32019-10-09 19:27:52 -070077 public WindowlessWindowManager(Configuration c, SurfaceControl rootSurface,
78 IBinder hostInputToken) {
Robert Carr9d431e12018-12-17 13:11:48 -080079 mRootSurface = rootSurface;
80 mConfiguration = new Configuration(c);
81 mRealWm = WindowManagerGlobal.getWindowSession();
Vishnu Nair5cf253192019-11-07 15:33:20 -080082 mHostInputToken = hostInputToken;
Robert Carr9d431e12018-12-17 13:11:48 -080083 }
84
Evan Rosky3f09bb32019-10-09 19:27:52 -070085 protected void setConfiguration(Configuration configuration) {
86 mConfiguration.setTo(configuration);
87 }
88
Robert Carrdf289462019-09-16 13:20:02 -070089 /**
90 * Utility API.
91 */
92 void setCompletionCallback(IBinder window, ResizeCompleteCallback callback) {
93 if (mResizeCompletionForWindow.get(window) != null) {
94 Log.w(TAG, "Unsupported overlapping resizes");
95 }
96 mResizeCompletionForWindow.put(window, callback);
97 }
98
99 /**
100 * IWindowSession implementation.
101 */
Vishnu Nair5cf253192019-11-07 15:33:20 -0800102 @Override
Robert Carr9d431e12018-12-17 13:11:48 -0800103 public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
104 int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
Jorim Jaggif081f062019-10-24 16:24:54 +0200105 Rect outStableInsets,
Robert Carr9d431e12018-12-17 13:11:48 -0800106 DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
107 InsetsState outInsetsState) {
108 final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
chaviw183aa5b2019-10-25 11:33:23 -0700109 .setParent(mRootSurface)
110 .setFormat(attrs.format)
111 .setName(attrs.getTitle().toString());
Robert Carr9d431e12018-12-17 13:11:48 -0800112 final SurfaceControl sc = b.build();
Robert Carr9d431e12018-12-17 13:11:48 -0800113
Vishnu Nair5cf253192019-11-07 15:33:20 -0800114 if (((attrs.inputFeatures &
Vishnu Nairddbd2512019-11-12 14:39:43 -0800115 WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0)) {
Robert Carr9d431e12018-12-17 13:11:48 -0800116 try {
Evan Rosky680377e2020-01-10 19:12:10 -0800117 mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, attrs.flags,
118 outInputChannel);
Robert Carr9d431e12018-12-17 13:11:48 -0800119 } catch (RemoteException e) {
Evan Rosky680377e2020-01-10 19:12:10 -0800120 Log.e(TAG, "Failed to grant input to surface: ", e);
Robert Carr9d431e12018-12-17 13:11:48 -0800121 }
122 }
123
Evan Rosky680377e2020-01-10 19:12:10 -0800124 final State state = new State(sc, attrs, displayId,
125 outInputChannel != null ? outInputChannel.getToken() : null);
126 synchronized (this) {
127 mStateForWindow.put(window.asBinder(), state);
128 }
129
Robert Carr9d431e12018-12-17 13:11:48 -0800130 return WindowManagerGlobal.ADD_OKAY | WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
131 }
132
133 @Override
Jiyong Park624b3932019-07-10 17:53:41 +0900134 public int addToDisplayWithoutInputChannel(android.view.IWindow window, int seq,
135 android.view.WindowManager.LayoutParams attrs, int viewVisibility, int layerStackId,
136 android.graphics.Rect outContentInsets, android.graphics.Rect outStableInsets,
137 android.view.InsetsState insetsState) {
138 return 0;
139 }
140
141 @Override
Vishnu Nair5cf253192019-11-07 15:33:20 -0800142 public void remove(android.view.IWindow window) throws RemoteException {
143 mRealWm.remove(window);
Evan Rosky3f09bb32019-10-09 19:27:52 -0700144 State state;
145 synchronized (this) {
146 state = mStateForWindow.remove(window.asBinder());
147 }
148 if (state == null) {
149 throw new IllegalArgumentException(
150 "Invalid window token (never added or removed already)");
151 }
152 try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
153 t.remove(state.mSurfaceControl).apply();
154 }
Vishnu Nair5cf253192019-11-07 15:33:20 -0800155 }
Jiyong Park624b3932019-07-10 17:53:41 +0900156
Robert Carr3e722b12019-08-27 13:39:58 -0700157 private boolean isOpaque(WindowManager.LayoutParams attrs) {
Vishnu Nair5cf253192019-11-07 15:33:20 -0800158 if (attrs.surfaceInsets != null && attrs.surfaceInsets.left != 0 ||
Robert Carr8833ae82019-09-16 13:20:02 -0700159 attrs.surfaceInsets.top != 0 || attrs.surfaceInsets.right != 0 ||
160 attrs.surfaceInsets.bottom != 0) {
Robert Carr3e722b12019-08-27 13:39:58 -0700161 return false;
162 }
163 return !PixelFormat.formatHasAlpha(attrs.format);
164 }
165
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000166 /** @hide */
167 protected SurfaceControl getSurfaceControl(View rootView) {
168 final State s = mStateForWindow.get(rootView.getViewRootImpl().mWindow.asBinder());
169 if (s == null) {
170 return null;
171 }
172 return s.mSurfaceControl;
173 }
174
Jiyong Park624b3932019-07-10 17:53:41 +0900175 @Override
Robert Carr650e7182019-09-24 14:11:24 -0700176 public int relayout(IWindow window, int seq, WindowManager.LayoutParams inAttrs,
Robert Carr9d431e12018-12-17 13:11:48 -0800177 int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
Jorim Jaggif081f062019-10-24 16:24:54 +0200178 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
179 Rect outStableInsets, Rect outBackdropFrame,
Robert Carr9d431e12018-12-17 13:11:48 -0800180 DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
Valerie Hau30360552020-01-14 16:12:01 -0800181 SurfaceControl outSurfaceControl, InsetsState outInsetsState,
Robert Carr2e20bcd2020-01-22 13:32:38 -0800182 Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
Evan Rosky680377e2020-01-10 19:12:10 -0800183 final State state;
Robert Carr9d431e12018-12-17 13:11:48 -0800184 synchronized (this) {
Robert Carr650e7182019-09-24 14:11:24 -0700185 state = mStateForWindow.get(window.asBinder());
Robert Carr9d431e12018-12-17 13:11:48 -0800186 }
Robert Carr650e7182019-09-24 14:11:24 -0700187 if (state == null) {
Robert Carr9d431e12018-12-17 13:11:48 -0800188 throw new IllegalArgumentException(
189 "Invalid window token (never added or removed already)");
190 }
Robert Carr650e7182019-09-24 14:11:24 -0700191 SurfaceControl sc = state.mSurfaceControl;
Robert Carr9d431e12018-12-17 13:11:48 -0800192 SurfaceControl.Transaction t = new SurfaceControl.Transaction();
Robert Carr8833ae82019-09-16 13:20:02 -0700193
Evan Rosky680377e2020-01-10 19:12:10 -0800194 int attrChanges = 0;
Robert Carr650e7182019-09-24 14:11:24 -0700195 if (inAttrs != null) {
Evan Rosky680377e2020-01-10 19:12:10 -0800196 attrChanges = state.mParams.copyFrom(inAttrs);
Robert Carr650e7182019-09-24 14:11:24 -0700197 }
198 WindowManager.LayoutParams attrs = state.mParams;
199
Robert Carr8833ae82019-09-16 13:20:02 -0700200 final Rect surfaceInsets = attrs.surfaceInsets;
201 int width = surfaceInsets != null ?
Robert Carrdf289462019-09-16 13:20:02 -0700202 attrs.width + surfaceInsets.left + surfaceInsets.right : attrs.width;
Robert Carr8833ae82019-09-16 13:20:02 -0700203 int height = surfaceInsets != null ?
Robert Carrdf289462019-09-16 13:20:02 -0700204 attrs.height + surfaceInsets.top + surfaceInsets.bottom : attrs.height;
Robert Carr8833ae82019-09-16 13:20:02 -0700205
Evan Rosky3f09bb32019-10-09 19:27:52 -0700206 t.setBufferSize(sc, width, height)
207 .setOpaque(sc, isOpaque(attrs));
208 if (viewFlags == View.VISIBLE) {
209 t.show(sc);
210 } else {
211 t.hide(sc);
212 }
213 t.apply();
Robert Carr9d431e12018-12-17 13:11:48 -0800214 outSurfaceControl.copyFrom(sc);
Robert Carrdf289462019-09-16 13:20:02 -0700215 outFrame.set(0, 0, attrs.width, attrs.height);
Robert Carr9d431e12018-12-17 13:11:48 -0800216
217 mergedConfiguration.setConfiguration(mConfiguration, mConfiguration);
218
Evan Rosky680377e2020-01-10 19:12:10 -0800219 if ((attrChanges & WindowManager.LayoutParams.FLAGS_CHANGED) != 0
220 && state.mInputChannelToken != null) {
221 try {
222 mRealWm.updateInputChannel(state.mInputChannelToken, state.mDisplayId, sc,
223 attrs.flags);
224 } catch (RemoteException e) {
225 Log.e(TAG, "Failed to update surface input channel: ", e);
226 }
227 }
228
Robert Carr9d431e12018-12-17 13:11:48 -0800229 return 0;
230 }
Jiyong Park624b3932019-07-10 17:53:41 +0900231
232 @Override
233 public void prepareToReplaceWindows(android.os.IBinder appToken, boolean childrenOnly) {
234 }
235
236 @Override
237 public boolean outOfMemory(android.view.IWindow window) {
238 return false;
239 }
240
241 @Override
242 public void setTransparentRegion(android.view.IWindow window, android.graphics.Region region) {
243 }
244
245 @Override
246 public void setInsets(android.view.IWindow window, int touchableInsets,
247 android.graphics.Rect contentInsets, android.graphics.Rect visibleInsets,
248 android.graphics.Region touchableRegion) {
249 }
250
251 @Override
252 public void getDisplayFrame(android.view.IWindow window,
253 android.graphics.Rect outDisplayFrame) {
254 }
255
256 @Override
257 public void finishDrawing(android.view.IWindow window,
258 android.view.SurfaceControl.Transaction postDrawTransaction) {
Robert Carrdf289462019-09-16 13:20:02 -0700259 synchronized (this) {
260 final ResizeCompleteCallback c =
261 mResizeCompletionForWindow.get(window.asBinder());
262 if (c == null) {
263 // No one wanted the callback, but it wasn't necessarily unexpected.
264 postDrawTransaction.apply();
265 return;
266 }
267 c.finished(postDrawTransaction);
268 mResizeCompletionForWindow.remove(window.asBinder());
269 }
Jiyong Park624b3932019-07-10 17:53:41 +0900270 }
271
272 @Override
273 public void setInTouchMode(boolean showFocus) {
274 }
275
276 @Override
277 public boolean getInTouchMode() {
278 return false;
279 }
280
281 @Override
282 public boolean performHapticFeedback(int effectId, boolean always) {
283 return false;
284 }
285
286 @Override
287 public android.os.IBinder performDrag(android.view.IWindow window, int flags,
288 android.view.SurfaceControl surface, int touchSource, float touchX, float touchY,
289 float thumbCenterX, float thumbCenterY, android.content.ClipData data) {
290 return null;
291 }
292
293 @Override
294 public void reportDropResult(android.view.IWindow window, boolean consumed) {
295 }
296
297 @Override
298 public void cancelDragAndDrop(android.os.IBinder dragToken, boolean skipAnimation) {
299 }
300
301 @Override
302 public void dragRecipientEntered(android.view.IWindow window) {
303 }
304
305 @Override
306 public void dragRecipientExited(android.view.IWindow window) {
307 }
308
309 @Override
310 public void setWallpaperPosition(android.os.IBinder windowToken, float x, float y,
311 float xstep, float ystep) {
312 }
313
314 @Override
Lucas Dupin13f4b8a2020-02-19 13:41:52 -0800315 public void setWallpaperZoomOut(android.os.IBinder windowToken, float zoom) {
316 }
317
318 @Override
319 public void setShouldZoomOutWallpaper(android.os.IBinder windowToken, boolean shouldZoom) {
320 }
321
322 @Override
Jiyong Park624b3932019-07-10 17:53:41 +0900323 public void wallpaperOffsetsComplete(android.os.IBinder window) {
324 }
325
326 @Override
327 public void setWallpaperDisplayOffset(android.os.IBinder windowToken, int x, int y) {
328 }
329
330 @Override
331 public android.os.Bundle sendWallpaperCommand(android.os.IBinder window,
332 java.lang.String action, int x, int y, int z, android.os.Bundle extras, boolean sync) {
333 return null;
334 }
335
336 @Override
337 public void wallpaperCommandComplete(android.os.IBinder window, android.os.Bundle result) {
338 }
339
340 @Override
341 public void onRectangleOnScreenRequested(android.os.IBinder token,
342 android.graphics.Rect rectangle) {
343 }
344
345 @Override
346 public android.view.IWindowId getWindowId(android.os.IBinder window) {
347 return null;
348 }
349
350 @Override
351 public void pokeDrawLock(android.os.IBinder window) {
352 }
353
354 @Override
355 public boolean startMovingTask(android.view.IWindow window, float startX, float startY) {
356 return false;
357 }
358
359 @Override
360 public void finishMovingTask(android.view.IWindow window) {
361 }
362
363 @Override
364 public void updatePointerIcon(android.view.IWindow window) {
365 }
366
367 @Override
368 public void reparentDisplayContent(android.view.IWindow window, android.view.SurfaceControl sc,
369 int displayId) {
370 }
371
372 @Override
373 public void updateDisplayContentLocation(android.view.IWindow window, int x, int y,
374 int displayId) {
375 }
376
377 @Override
chaviwaa0d74e2019-12-26 14:13:40 -0800378 public void updateTapExcludeRegion(android.view.IWindow window,
Jiyong Park624b3932019-07-10 17:53:41 +0900379 android.graphics.Region region) {
380 }
381
382 @Override
383 public void insetsModified(android.view.IWindow window, android.view.InsetsState state) {
384 }
385
386 @Override
387 public void reportSystemGestureExclusionChanged(android.view.IWindow window,
388 java.util.List<android.graphics.Rect> exclusionRects) {
389 }
390
391 @Override
Vishnu Nair5cf253192019-11-07 15:33:20 -0800392 public void grantInputChannel(int displayId, SurfaceControl surface, IWindow window,
Evan Rosky680377e2020-01-10 19:12:10 -0800393 IBinder hostInputToken, int flags, InputChannel outInputChannel) {
394 }
395
396 @Override
397 public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
398 int flags) {
Jiyong Park624b3932019-07-10 17:53:41 +0900399 }
400
401 @Override
402 public android.os.IBinder asBinder() {
403 return null;
404 }
Robert Carr9d431e12018-12-17 13:11:48 -0800405}