blob: 044a2a6cc4b62db395f4a15707975eebbf052f5b [file] [log] [blame]
Evan Rosky22b6bbd2019-09-26 14:29:57 -07001/*
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 com.android.systemui.wm;
18
19import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
20
21import android.annotation.NonNull;
22import android.content.Context;
23import android.content.res.Configuration;
24import android.graphics.Point;
25import android.graphics.Rect;
26import android.os.Bundle;
27import android.os.ParcelFileDescriptor;
28import android.os.RemoteException;
29import android.util.MergedConfiguration;
30import android.util.Slog;
31import android.util.SparseArray;
32import android.view.Display;
33import android.view.DisplayCutout;
34import android.view.DragEvent;
35import android.view.IWindow;
36import android.view.IWindowManager;
37import android.view.IWindowSession;
38import android.view.IWindowSessionCallback;
39import android.view.InsetsSourceControl;
40import android.view.InsetsState;
41import android.view.SurfaceControl;
Valerie Hau30360552020-01-14 16:12:01 -080042import android.view.SurfaceControlViewHost;
Evan Rosky22b6bbd2019-09-26 14:29:57 -070043import android.view.View;
44import android.view.ViewGroup;
45import android.view.WindowManager;
Evan Rosky22b6bbd2019-09-26 14:29:57 -070046import android.view.WindowlessWindowManager;
47
48import com.android.internal.os.IResultReceiver;
49
50import java.util.HashMap;
51
52import javax.inject.Inject;
53import javax.inject.Singleton;
54
55/**
56 * Represents the "windowing" layer of the System-UI. This layer allows system-ui components to
57 * place and manipulate windows without talking to WindowManager.
58 */
59@Singleton
60public class SystemWindows {
61 private static final String TAG = "SystemWindows";
62
63 private final SparseArray<PerDisplay> mPerDisplay = new SparseArray<>();
Robert Carr59b18882019-12-18 00:38:40 -080064 final HashMap<View, SurfaceControlViewHost> mViewRoots = new HashMap<>();
Evan Rosky22b6bbd2019-09-26 14:29:57 -070065 Context mContext;
66 IWindowSession mSession;
Winson Chung95c9fca2020-01-22 09:48:40 -080067 DisplayController mDisplayController;
Evan Rosky22b6bbd2019-09-26 14:29:57 -070068 IWindowManager mWmService;
69
Winson Chung95c9fca2020-01-22 09:48:40 -080070 private final DisplayController.OnDisplaysChangedListener mDisplayListener =
71 new DisplayController.OnDisplaysChangedListener() {
Evan Rosky22b6bbd2019-09-26 14:29:57 -070072 @Override
73 public void onDisplayAdded(int displayId) { }
74
75 @Override
76 public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
77 PerDisplay pd = mPerDisplay.get(displayId);
78 if (pd == null) {
79 return;
80 }
81 pd.updateConfiguration(newConfig);
82 }
83
84 @Override
85 public void onDisplayRemoved(int displayId) { }
86 };
87
88 @Inject
Winson Chung95c9fca2020-01-22 09:48:40 -080089 public SystemWindows(Context context, DisplayController displayController,
Evan Rosky22b6bbd2019-09-26 14:29:57 -070090 IWindowManager wmService) {
91 mContext = context;
92 mWmService = wmService;
93 mDisplayController = displayController;
94 mDisplayController.addDisplayWindowListener(mDisplayListener);
95 try {
96 mSession = wmService.openSession(
97 new IWindowSessionCallback.Stub() {
98 @Override
99 public void onAnimatorScaleChanged(float scale) {}
100 });
101 } catch (RemoteException e) {
102 Slog.e(TAG, "Unable to create layer", e);
103 }
104 }
105
106 /**
107 * Adds a view to system-ui window management.
108 */
109 public void addView(View view, WindowManager.LayoutParams attrs, int displayId,
110 int windowType) {
111 PerDisplay pd = mPerDisplay.get(displayId);
112 if (pd == null) {
113 pd = new PerDisplay(displayId);
114 mPerDisplay.put(displayId, pd);
115 }
116 pd.addView(view, attrs, windowType);
117 }
118
119 /**
120 * Removes a view from system-ui window management.
121 * @param view
122 */
123 public void removeView(View view) {
Robert Carr59b18882019-12-18 00:38:40 -0800124 SurfaceControlViewHost root = mViewRoots.remove(view);
Evan Rosky22b6bbd2019-09-26 14:29:57 -0700125 root.die();
126 }
127
128 /**
129 * Updates the layout params of a view.
130 */
131 public void updateViewLayout(@NonNull View view, ViewGroup.LayoutParams params) {
Robert Carr59b18882019-12-18 00:38:40 -0800132 SurfaceControlViewHost root = mViewRoots.get(view);
Evan Rosky22b6bbd2019-09-26 14:29:57 -0700133 if (root == null || !(params instanceof WindowManager.LayoutParams)) {
134 return;
135 }
136 view.setLayoutParams(params);
137 root.relayout((WindowManager.LayoutParams) params);
138 }
139
140 /**
141 * Adds a root for system-ui window management with no views. Only useful for IME.
142 */
143 public void addRoot(int displayId, int windowType) {
144 PerDisplay pd = mPerDisplay.get(displayId);
145 if (pd == null) {
146 pd = new PerDisplay(displayId);
147 mPerDisplay.put(displayId, pd);
148 }
149 pd.addRoot(windowType);
150 }
151
152 /**
153 * Get the IWindow token for a specific root.
154 *
155 * @param windowType A window type from {@link android.view.WindowManager}.
156 */
157 IWindow getWindow(int displayId, int windowType) {
158 PerDisplay pd = mPerDisplay.get(displayId);
159 if (pd == null) {
160 return null;
161 }
162 return pd.getWindow(windowType);
163 }
164
165 private class PerDisplay {
166 final int mDisplayId;
167 private final SparseArray<SysUiWindowManager> mWwms = new SparseArray<>();
168
169 PerDisplay(int displayId) {
170 mDisplayId = displayId;
171 }
172
173 public void addView(View view, WindowManager.LayoutParams attrs, int windowType) {
174 SysUiWindowManager wwm = addRoot(windowType);
175 if (wwm == null) {
176 Slog.e(TAG, "Unable to create systemui root");
177 return;
178 }
179 final Display display = mDisplayController.getDisplay(mDisplayId);
Robert Carr59b18882019-12-18 00:38:40 -0800180 SurfaceControlViewHost viewRoot = new SurfaceControlViewHost(mContext, display, wwm);
Evan Rosky22b6bbd2019-09-26 14:29:57 -0700181 attrs.flags |= FLAG_HARDWARE_ACCELERATED;
182 viewRoot.addView(view, attrs);
183 mViewRoots.put(view, viewRoot);
184 }
185
186 SysUiWindowManager addRoot(int windowType) {
187 SysUiWindowManager wwm = mWwms.get(windowType);
188 if (wwm != null) {
189 return wwm;
190 }
191 SurfaceControl rootSurface = null;
192 ContainerWindow win = new ContainerWindow();
193 try {
194 rootSurface = mWmService.addShellRoot(mDisplayId, win, windowType);
195 } catch (RemoteException e) {
196 }
197 if (rootSurface == null) {
198 Slog.e(TAG, "Unable to get root surfacecontrol for systemui");
199 return null;
200 }
201 Context displayContext = mDisplayController.getDisplayContext(mDisplayId);
202 wwm = new SysUiWindowManager(mDisplayId, displayContext, rootSurface, win);
203 mWwms.put(windowType, wwm);
204 return wwm;
205 }
206
207 IWindow getWindow(int windowType) {
208 SysUiWindowManager wwm = mWwms.get(windowType);
209 if (wwm == null) {
210 return null;
211 }
212 return wwm.mContainerWindow;
213 }
214
215 void updateConfiguration(Configuration configuration) {
216 for (int i = 0; i < mWwms.size(); ++i) {
217 mWwms.valueAt(i).updateConfiguration(configuration);
218 }
219 }
220 }
221
222 /**
223 * A subclass of WindowlessWindowManager that provides insets to its viewroots.
224 */
225 public class SysUiWindowManager extends WindowlessWindowManager {
226 final int mDisplayId;
227 ContainerWindow mContainerWindow;
228 public SysUiWindowManager(int displayId, Context ctx, SurfaceControl rootSurface,
229 ContainerWindow container) {
230 super(ctx.getResources().getConfiguration(), rootSurface, null /* hostInputToken */);
231 mContainerWindow = container;
232 mDisplayId = displayId;
233 }
234
235 @Override
236 public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
237 int requestedWidth, int requestedHeight, int viewVisibility, int flags,
238 long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
239 Rect outVisibleInsets, Rect outStableInsets,
240 DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
Valerie Hau30360552020-01-14 16:12:01 -0800241 SurfaceControl outSurfaceControl, InsetsState outInsetsState,
Robert Carr2e20bcd2020-01-22 13:32:38 -0800242 Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
Evan Rosky22b6bbd2019-09-26 14:29:57 -0700243 int res = super.relayout(window, seq, attrs, requestedWidth, requestedHeight,
244 viewVisibility, flags, frameNumber, outFrame, outOverscanInsets,
245 outContentInsets, outVisibleInsets, outStableInsets,
Valerie Hau30360552020-01-14 16:12:01 -0800246 cutout, mergedConfiguration, outSurfaceControl, outInsetsState,
Robert Carr2e20bcd2020-01-22 13:32:38 -0800247 outSurfaceSize, outBLASTSurfaceControl);
Evan Rosky22b6bbd2019-09-26 14:29:57 -0700248 if (res != 0) {
249 return res;
250 }
251 DisplayLayout dl = mDisplayController.getDisplayLayout(mDisplayId);
252 outStableInsets.set(dl.stableInsets());
253 return 0;
254 }
255
256 void updateConfiguration(Configuration configuration) {
257 setConfiguration(configuration);
258 }
259 }
260
261 class ContainerWindow extends IWindow.Stub {
262 ContainerWindow() {}
263
264 @Override
265 public void resized(Rect frame, Rect contentInsets, Rect visibleInsets, Rect stableInsets,
266 boolean reportDraw, MergedConfiguration newMergedConfiguration, Rect backDropFrame,
267 boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
268 DisplayCutout.ParcelableWrapper displayCutout) {}
269
270 @Override
271 public void locationInParentDisplayChanged(Point offset) {}
272
273 @Override
274 public void insetsChanged(InsetsState insetsState) {}
275
276 @Override
277 public void insetsControlChanged(InsetsState insetsState,
278 InsetsSourceControl[] activeControls) {}
279
280 @Override
281 public void showInsets(int types, boolean fromIme) {}
282
283 @Override
284 public void hideInsets(int types, boolean fromIme) {}
285
286 @Override
287 public void moved(int newX, int newY) {}
288
289 @Override
290 public void dispatchAppVisibility(boolean visible) {}
291
292 @Override
293 public void dispatchGetNewSurface() {}
294
295 @Override
296 public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {}
297
298 @Override
299 public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {}
300
301 @Override
302 public void closeSystemDialogs(String reason) {}
303
304 @Override
305 public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
306 boolean sync) {}
307
308 @Override
309 public void dispatchWallpaperCommand(String action, int x, int y,
310 int z, Bundle extras, boolean sync) {}
311
312 /* Drag/drop */
313 @Override
314 public void dispatchDragEvent(DragEvent event) {}
315
316 @Override
317 public void updatePointerIcon(float x, float y) {}
318
319 @Override
320 public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
321 int localValue, int localChanges) {}
322
323 @Override
324 public void dispatchWindowShown() {}
325
326 @Override
327 public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {}
328
329 @Override
330 public void dispatchPointerCaptureChanged(boolean hasCapture) {}
331 }
332}