blob: cd954c41f46936661875beeed85b13f003d385cb [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
Evan Rosky12837282020-04-27 19:12:25 -070019import android.annotation.Nullable;
Robert Carr9d431e12018-12-17 13:11:48 -080020import android.content.res.Configuration;
Robert Carr3e722b12019-08-27 13:39:58 -070021import android.graphics.PixelFormat;
Valerie Hau30360552020-01-14 16:12:01 -080022import android.graphics.Point;
Robert Carr9d431e12018-12-17 13:11:48 -080023import android.graphics.Rect;
Evan Rosky12837282020-04-27 19:12:25 -070024import android.graphics.Region;
Robert Carr9d431e12018-12-17 13:11:48 -080025import android.os.IBinder;
26import android.os.RemoteException;
Robert Carr9d431e12018-12-17 13:11:48 -080027import android.util.Log;
Jiyong Park624b3932019-07-10 17:53:41 +090028import android.util.MergedConfiguration;
Robert Carr9d431e12018-12-17 13:11:48 -080029
30import java.util.HashMap;
Evan Rosky12837282020-04-27 19:12:25 -070031import java.util.Objects;
Robert Carr9d431e12018-12-17 13:11:48 -080032
33/**
34* A simplistic implementation of IWindowSession. Rather than managing Surfaces
35* as children of the display, it manages Surfaces as children of a given root.
36*
37* By parcelling the root surface, the app can offer another app content for embedding.
38* @hide
39*/
Evan Rosky3f09bb32019-10-09 19:27:52 -070040public class WindowlessWindowManager implements IWindowSession {
Robert Carr9d431e12018-12-17 13:11:48 -080041 private final static String TAG = "WindowlessWindowManager";
42
Robert Carr650e7182019-09-24 14:11:24 -070043 private class State {
Tony Huang0f8981d2020-04-20 17:38:37 +080044 //TODO : b/150190730 we should create it when view show and release it when view invisible.
Robert Carr650e7182019-09-24 14:11:24 -070045 SurfaceControl mSurfaceControl;
46 WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
Evan Rosky680377e2020-01-10 19:12:10 -080047 int mDisplayId;
48 IBinder mInputChannelToken;
Evan Rosky12837282020-04-27 19:12:25 -070049 Region mInputRegion;
Evan Rosky680377e2020-01-10 19:12:10 -080050 State(SurfaceControl sc, WindowManager.LayoutParams p, int displayId,
51 IBinder inputChannelToken) {
Robert Carr650e7182019-09-24 14:11:24 -070052 mSurfaceControl = sc;
53 mParams.copyFrom(p);
Evan Rosky680377e2020-01-10 19:12:10 -080054 mDisplayId = displayId;
55 mInputChannelToken = inputChannelToken;
Robert Carr650e7182019-09-24 14:11:24 -070056 }
57 };
Evan Rosky3f09bb32019-10-09 19:27:52 -070058
Robert Carr9d431e12018-12-17 13:11:48 -080059 /**
60 * Used to store SurfaceControl we've built for clients to
61 * reconfigure them if relayout is called.
62 */
Robert Carr650e7182019-09-24 14:11:24 -070063 final HashMap<IBinder, State> mStateForWindow = new HashMap<IBinder, State>();
Robert Carrdf289462019-09-16 13:20:02 -070064
65 public interface ResizeCompleteCallback {
66 public void finished(SurfaceControl.Transaction completion);
67 }
68
69 final HashMap<IBinder, ResizeCompleteCallback> mResizeCompletionForWindow =
70 new HashMap<IBinder, ResizeCompleteCallback>();
71
Vishnu Nair5cf253192019-11-07 15:33:20 -080072 private final SurfaceSession mSurfaceSession = new SurfaceSession();
73 private final SurfaceControl mRootSurface;
74 private final Configuration mConfiguration;
75 private final IWindowSession mRealWm;
76 private final IBinder mHostInputToken;
Robert Carr9d431e12018-12-17 13:11:48 -080077
78 private int mForceHeight = -1;
79 private int mForceWidth = -1;
80
Evan Rosky3f09bb32019-10-09 19:27:52 -070081 public WindowlessWindowManager(Configuration c, SurfaceControl rootSurface,
82 IBinder hostInputToken) {
Robert Carr9d431e12018-12-17 13:11:48 -080083 mRootSurface = rootSurface;
84 mConfiguration = new Configuration(c);
85 mRealWm = WindowManagerGlobal.getWindowSession();
Vishnu Nair5cf253192019-11-07 15:33:20 -080086 mHostInputToken = hostInputToken;
Robert Carr9d431e12018-12-17 13:11:48 -080087 }
88
Evan Rosky3f09bb32019-10-09 19:27:52 -070089 protected void setConfiguration(Configuration configuration) {
90 mConfiguration.setTo(configuration);
91 }
92
Robert Carrdf289462019-09-16 13:20:02 -070093 /**
94 * Utility API.
95 */
96 void setCompletionCallback(IBinder window, ResizeCompleteCallback callback) {
97 if (mResizeCompletionForWindow.get(window) != null) {
98 Log.w(TAG, "Unsupported overlapping resizes");
99 }
100 mResizeCompletionForWindow.put(window, callback);
101 }
102
Evan Rosky12837282020-04-27 19:12:25 -0700103 protected void setTouchRegion(IBinder window, @Nullable Region region) {
104 State state;
105 synchronized (this) {
106 // Do everything while locked so that we synchronize with relayout. This should be a
107 // very infrequent operation.
108 state = mStateForWindow.get(window);
109 if (state == null) {
110 return;
111 }
112 if (Objects.equals(region, state.mInputRegion)) {
113 return;
114 }
115 state.mInputRegion = region != null ? new Region(region) : null;
116 if (state.mInputChannelToken != null) {
117 try {
118 mRealWm.updateInputChannel(state.mInputChannelToken, state.mDisplayId,
119 state.mSurfaceControl, state.mParams.flags, state.mInputRegion);
120 } catch (RemoteException e) {
121 Log.e(TAG, "Failed to update surface input channel: ", e);
122 }
123 }
124 }
125 }
126
Robert Carrdf289462019-09-16 13:20:02 -0700127 /**
128 * IWindowSession implementation.
129 */
Vishnu Nair5cf253192019-11-07 15:33:20 -0800130 @Override
Robert Carr9d431e12018-12-17 13:11:48 -0800131 public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
132 int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
Jorim Jaggif081f062019-10-24 16:24:54 +0200133 Rect outStableInsets,
Robert Carr9d431e12018-12-17 13:11:48 -0800134 DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
Tiger Huang0426a332020-03-29 01:17:08 +0800135 InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
Robert Carr9d431e12018-12-17 13:11:48 -0800136 final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
chaviw183aa5b2019-10-25 11:33:23 -0700137 .setParent(mRootSurface)
138 .setFormat(attrs.format)
139 .setName(attrs.getTitle().toString());
Robert Carr9d431e12018-12-17 13:11:48 -0800140 final SurfaceControl sc = b.build();
Robert Carr9d431e12018-12-17 13:11:48 -0800141
Vishnu Nair5cf253192019-11-07 15:33:20 -0800142 if (((attrs.inputFeatures &
Vishnu Nairddbd2512019-11-12 14:39:43 -0800143 WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0)) {
Robert Carr9d431e12018-12-17 13:11:48 -0800144 try {
Evan Rosky680377e2020-01-10 19:12:10 -0800145 mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, attrs.flags,
146 outInputChannel);
Robert Carr9d431e12018-12-17 13:11:48 -0800147 } catch (RemoteException e) {
Evan Rosky680377e2020-01-10 19:12:10 -0800148 Log.e(TAG, "Failed to grant input to surface: ", e);
Robert Carr9d431e12018-12-17 13:11:48 -0800149 }
150 }
151
Evan Rosky680377e2020-01-10 19:12:10 -0800152 final State state = new State(sc, attrs, displayId,
153 outInputChannel != null ? outInputChannel.getToken() : null);
154 synchronized (this) {
155 mStateForWindow.put(window.asBinder(), state);
156 }
157
Robert Carr9d431e12018-12-17 13:11:48 -0800158 return WindowManagerGlobal.ADD_OKAY | WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
159 }
160
wilsonshihd0fc2ca2020-03-18 22:41:55 +0800161 /**
162 * IWindowSession implementation. Currently this class doesn't need to support for multi-user.
163 */
164 @Override
165 public int addToDisplayAsUser(IWindow window, int seq, WindowManager.LayoutParams attrs,
166 int viewVisibility, int displayId, int userId, Rect outFrame,
167 Rect outContentInsets, Rect outStableInsets,
168 DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
169 InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
170 return addToDisplay(window, seq, attrs, viewVisibility, displayId,
171 outFrame, outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
172 outInsetsState, outActiveControls);
173 }
174
Robert Carr9d431e12018-12-17 13:11:48 -0800175 @Override
Jiyong Park624b3932019-07-10 17:53:41 +0900176 public int addToDisplayWithoutInputChannel(android.view.IWindow window, int seq,
177 android.view.WindowManager.LayoutParams attrs, int viewVisibility, int layerStackId,
178 android.graphics.Rect outContentInsets, android.graphics.Rect outStableInsets,
179 android.view.InsetsState insetsState) {
180 return 0;
181 }
182
183 @Override
Vishnu Nair5cf253192019-11-07 15:33:20 -0800184 public void remove(android.view.IWindow window) throws RemoteException {
185 mRealWm.remove(window);
Evan Rosky3f09bb32019-10-09 19:27:52 -0700186 State state;
187 synchronized (this) {
188 state = mStateForWindow.remove(window.asBinder());
189 }
190 if (state == null) {
191 throw new IllegalArgumentException(
192 "Invalid window token (never added or removed already)");
193 }
arthurhung03d65a72020-04-28 09:19:24 +0800194
Evan Rosky3f09bb32019-10-09 19:27:52 -0700195 try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
196 t.remove(state.mSurfaceControl).apply();
197 }
Vishnu Nair5cf253192019-11-07 15:33:20 -0800198 }
Jiyong Park624b3932019-07-10 17:53:41 +0900199
Robert Carr3e722b12019-08-27 13:39:58 -0700200 private boolean isOpaque(WindowManager.LayoutParams attrs) {
Vishnu Nair5cf253192019-11-07 15:33:20 -0800201 if (attrs.surfaceInsets != null && attrs.surfaceInsets.left != 0 ||
Robert Carr8833ae82019-09-16 13:20:02 -0700202 attrs.surfaceInsets.top != 0 || attrs.surfaceInsets.right != 0 ||
203 attrs.surfaceInsets.bottom != 0) {
Robert Carr3e722b12019-08-27 13:39:58 -0700204 return false;
205 }
206 return !PixelFormat.formatHasAlpha(attrs.format);
207 }
208
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000209 /** @hide */
210 protected SurfaceControl getSurfaceControl(View rootView) {
211 final State s = mStateForWindow.get(rootView.getViewRootImpl().mWindow.asBinder());
212 if (s == null) {
213 return null;
214 }
215 return s.mSurfaceControl;
216 }
217
Jiyong Park624b3932019-07-10 17:53:41 +0900218 @Override
Robert Carr650e7182019-09-24 14:11:24 -0700219 public int relayout(IWindow window, int seq, WindowManager.LayoutParams inAttrs,
Robert Carr9d431e12018-12-17 13:11:48 -0800220 int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
Jorim Jaggif081f062019-10-24 16:24:54 +0200221 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
222 Rect outStableInsets, Rect outBackdropFrame,
Robert Carr9d431e12018-12-17 13:11:48 -0800223 DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
Valerie Hau30360552020-01-14 16:12:01 -0800224 SurfaceControl outSurfaceControl, InsetsState outInsetsState,
Tiger Huang0426a332020-03-29 01:17:08 +0800225 InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
226 SurfaceControl outBLASTSurfaceControl) {
Evan Rosky680377e2020-01-10 19:12:10 -0800227 final State state;
Robert Carr9d431e12018-12-17 13:11:48 -0800228 synchronized (this) {
Robert Carr650e7182019-09-24 14:11:24 -0700229 state = mStateForWindow.get(window.asBinder());
Robert Carr9d431e12018-12-17 13:11:48 -0800230 }
Robert Carr650e7182019-09-24 14:11:24 -0700231 if (state == null) {
Robert Carr9d431e12018-12-17 13:11:48 -0800232 throw new IllegalArgumentException(
233 "Invalid window token (never added or removed already)");
234 }
Robert Carr650e7182019-09-24 14:11:24 -0700235 SurfaceControl sc = state.mSurfaceControl;
Robert Carr9d431e12018-12-17 13:11:48 -0800236 SurfaceControl.Transaction t = new SurfaceControl.Transaction();
Robert Carr8833ae82019-09-16 13:20:02 -0700237
Evan Rosky680377e2020-01-10 19:12:10 -0800238 int attrChanges = 0;
Robert Carr650e7182019-09-24 14:11:24 -0700239 if (inAttrs != null) {
Evan Rosky680377e2020-01-10 19:12:10 -0800240 attrChanges = state.mParams.copyFrom(inAttrs);
Robert Carr650e7182019-09-24 14:11:24 -0700241 }
242 WindowManager.LayoutParams attrs = state.mParams;
243
Evan Rosky3f09bb32019-10-09 19:27:52 -0700244 if (viewFlags == View.VISIBLE) {
Tony Huang0f8981d2020-04-20 17:38:37 +0800245 final Rect surfaceInsets = attrs.surfaceInsets;
246 int width = surfaceInsets != null
247 ? attrs.width + surfaceInsets.left + surfaceInsets.right : attrs.width;
248 int height = surfaceInsets != null
249 ? attrs.height + surfaceInsets.top + surfaceInsets.bottom : attrs.height;
250
251 t.setBufferSize(sc, width, height).setOpaque(sc, isOpaque(attrs)).show(sc).apply();
252 outSurfaceControl.copyFrom(sc);
Evan Rosky3f09bb32019-10-09 19:27:52 -0700253 } else {
Tony Huang0f8981d2020-04-20 17:38:37 +0800254 t.hide(sc).apply();
255 outSurfaceControl.release();
Evan Rosky3f09bb32019-10-09 19:27:52 -0700256 }
Robert Carrdf289462019-09-16 13:20:02 -0700257 outFrame.set(0, 0, attrs.width, attrs.height);
Robert Carr9d431e12018-12-17 13:11:48 -0800258
259 mergedConfiguration.setConfiguration(mConfiguration, mConfiguration);
260
Evan Rosky680377e2020-01-10 19:12:10 -0800261 if ((attrChanges & WindowManager.LayoutParams.FLAGS_CHANGED) != 0
262 && state.mInputChannelToken != null) {
263 try {
264 mRealWm.updateInputChannel(state.mInputChannelToken, state.mDisplayId, sc,
Evan Rosky12837282020-04-27 19:12:25 -0700265 attrs.flags, state.mInputRegion);
Evan Rosky680377e2020-01-10 19:12:10 -0800266 } catch (RemoteException e) {
267 Log.e(TAG, "Failed to update surface input channel: ", e);
268 }
269 }
270
Robert Carr9d431e12018-12-17 13:11:48 -0800271 return 0;
272 }
Jiyong Park624b3932019-07-10 17:53:41 +0900273
274 @Override
275 public void prepareToReplaceWindows(android.os.IBinder appToken, boolean childrenOnly) {
276 }
277
278 @Override
279 public boolean outOfMemory(android.view.IWindow window) {
280 return false;
281 }
282
283 @Override
284 public void setTransparentRegion(android.view.IWindow window, android.graphics.Region region) {
285 }
286
287 @Override
288 public void setInsets(android.view.IWindow window, int touchableInsets,
289 android.graphics.Rect contentInsets, android.graphics.Rect visibleInsets,
290 android.graphics.Region touchableRegion) {
291 }
292
293 @Override
294 public void getDisplayFrame(android.view.IWindow window,
295 android.graphics.Rect outDisplayFrame) {
296 }
297
298 @Override
299 public void finishDrawing(android.view.IWindow window,
300 android.view.SurfaceControl.Transaction postDrawTransaction) {
Robert Carrdf289462019-09-16 13:20:02 -0700301 synchronized (this) {
302 final ResizeCompleteCallback c =
303 mResizeCompletionForWindow.get(window.asBinder());
304 if (c == null) {
305 // No one wanted the callback, but it wasn't necessarily unexpected.
306 postDrawTransaction.apply();
307 return;
308 }
309 c.finished(postDrawTransaction);
310 mResizeCompletionForWindow.remove(window.asBinder());
311 }
Jiyong Park624b3932019-07-10 17:53:41 +0900312 }
313
314 @Override
315 public void setInTouchMode(boolean showFocus) {
316 }
317
318 @Override
319 public boolean getInTouchMode() {
320 return false;
321 }
322
323 @Override
324 public boolean performHapticFeedback(int effectId, boolean always) {
325 return false;
326 }
327
328 @Override
329 public android.os.IBinder performDrag(android.view.IWindow window, int flags,
330 android.view.SurfaceControl surface, int touchSource, float touchX, float touchY,
331 float thumbCenterX, float thumbCenterY, android.content.ClipData data) {
332 return null;
333 }
334
335 @Override
336 public void reportDropResult(android.view.IWindow window, boolean consumed) {
337 }
338
339 @Override
340 public void cancelDragAndDrop(android.os.IBinder dragToken, boolean skipAnimation) {
341 }
342
343 @Override
344 public void dragRecipientEntered(android.view.IWindow window) {
345 }
346
347 @Override
348 public void dragRecipientExited(android.view.IWindow window) {
349 }
350
351 @Override
352 public void setWallpaperPosition(android.os.IBinder windowToken, float x, float y,
353 float xstep, float ystep) {
354 }
355
356 @Override
Lucas Dupin13f4b8a2020-02-19 13:41:52 -0800357 public void setWallpaperZoomOut(android.os.IBinder windowToken, float zoom) {
358 }
359
360 @Override
361 public void setShouldZoomOutWallpaper(android.os.IBinder windowToken, boolean shouldZoom) {
362 }
363
364 @Override
Jiyong Park624b3932019-07-10 17:53:41 +0900365 public void wallpaperOffsetsComplete(android.os.IBinder window) {
366 }
367
368 @Override
369 public void setWallpaperDisplayOffset(android.os.IBinder windowToken, int x, int y) {
370 }
371
372 @Override
373 public android.os.Bundle sendWallpaperCommand(android.os.IBinder window,
374 java.lang.String action, int x, int y, int z, android.os.Bundle extras, boolean sync) {
375 return null;
376 }
377
378 @Override
379 public void wallpaperCommandComplete(android.os.IBinder window, android.os.Bundle result) {
380 }
381
382 @Override
383 public void onRectangleOnScreenRequested(android.os.IBinder token,
384 android.graphics.Rect rectangle) {
385 }
386
387 @Override
388 public android.view.IWindowId getWindowId(android.os.IBinder window) {
389 return null;
390 }
391
392 @Override
393 public void pokeDrawLock(android.os.IBinder window) {
394 }
395
396 @Override
397 public boolean startMovingTask(android.view.IWindow window, float startX, float startY) {
398 return false;
399 }
400
401 @Override
402 public void finishMovingTask(android.view.IWindow window) {
403 }
404
405 @Override
406 public void updatePointerIcon(android.view.IWindow window) {
407 }
408
409 @Override
410 public void reparentDisplayContent(android.view.IWindow window, android.view.SurfaceControl sc,
411 int displayId) {
412 }
413
414 @Override
415 public void updateDisplayContentLocation(android.view.IWindow window, int x, int y,
416 int displayId) {
417 }
418
419 @Override
chaviwaa0d74e2019-12-26 14:13:40 -0800420 public void updateTapExcludeRegion(android.view.IWindow window,
Jiyong Park624b3932019-07-10 17:53:41 +0900421 android.graphics.Region region) {
422 }
423
424 @Override
425 public void insetsModified(android.view.IWindow window, android.view.InsetsState state) {
426 }
427
428 @Override
429 public void reportSystemGestureExclusionChanged(android.view.IWindow window,
430 java.util.List<android.graphics.Rect> exclusionRects) {
431 }
432
433 @Override
Vishnu Nair5cf253192019-11-07 15:33:20 -0800434 public void grantInputChannel(int displayId, SurfaceControl surface, IWindow window,
Evan Rosky680377e2020-01-10 19:12:10 -0800435 IBinder hostInputToken, int flags, InputChannel outInputChannel) {
436 }
437
438 @Override
439 public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
Evan Rosky12837282020-04-27 19:12:25 -0700440 int flags, Region region) {
Jiyong Park624b3932019-07-10 17:53:41 +0900441 }
442
443 @Override
444 public android.os.IBinder asBinder() {
445 return null;
446 }
Robert Carr9d431e12018-12-17 13:11:48 -0800447}