blob: 69943e3904ed3cce7a3107027d88b3fa2f51510c [file] [log] [blame]
Jeff Brownbd6e1502012-08-28 03:27:37 -07001/*
2 * Copyright (C) 2012 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.server.display;
18
Charles Chenb28fb722020-05-21 17:19:32 +080019import static com.android.server.display.DisplayDeviceInfo.FLAG_TRUSTED;
20
Chris Li1ac23bb2020-04-20 22:39:53 -070021import android.annotation.Nullable;
Jeff Brownbd6e1502012-08-28 03:27:37 -070022import android.content.Context;
23import android.database.ContentObserver;
Craig Mautnerd5523dc2012-10-02 13:49:22 -070024import android.graphics.SurfaceTexture;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070025import android.os.Handler;
Jeff Brownbd6e1502012-08-28 03:27:37 -070026import android.os.IBinder;
27import android.provider.Settings;
Chris Li1ac23bb2020-04-20 22:39:53 -070028import android.text.TextUtils;
Jeff Brownbd6e1502012-08-28 03:27:37 -070029import android.util.DisplayMetrics;
30import android.util.Slog;
Jeff Brown92130f62012-10-24 21:28:33 -070031import android.view.Display;
Jeff Brownbd6e1502012-08-28 03:27:37 -070032import android.view.Gravity;
Jeff Brownbd6e1502012-08-28 03:27:37 -070033import android.view.Surface;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080034import android.view.SurfaceControl;
Jeff Brownbd6e1502012-08-28 03:27:37 -070035
Michael Wrighta3dab232019-02-22 16:54:21 +000036import com.android.internal.util.DumpUtils;
37import com.android.internal.util.IndentingPrintWriter;
38
Jeff Brownbd6e1502012-08-28 03:27:37 -070039import java.io.PrintWriter;
40import java.util.ArrayList;
P.Y. Laligand10188812015-05-06 14:50:52 -070041import java.util.Arrays;
42import java.util.List;
Jeff Brownbd6e1502012-08-28 03:27:37 -070043import java.util.regex.Matcher;
44import java.util.regex.Pattern;
45
46/**
47 * A display adapter that uses overlay windows to simulate secondary displays
48 * for development purposes. Use Development Settings to enable one or more
49 * overlay displays.
50 * <p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070051 * This object has two different handlers (which may be the same) which must not
52 * get confused. The main handler is used to posting messages to the display manager
53 * service as usual. The UI handler is only used by the {@link OverlayDisplayWindow}.
54 * </p><p>
55 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
P.Y. Laligand10188812015-05-06 14:50:52 -070056 * </p><p>
57 * This adapter is configured via the
58 * {@link android.provider.Settings.Global#OVERLAY_DISPLAY_DEVICES} setting. This setting should be
59 * formatted as follows:
60 * <pre>
Chris Li1ac23bb2020-04-20 22:39:53 -070061 * [display1];[display2];...
62 * </pre>
63 * with each display specified as:
64 * <pre>
P.Y. Laligand10188812015-05-06 14:50:52 -070065 * [mode1]|[mode2]|...,[flag1],[flag2],...
66 * </pre>
67 * with each mode specified as:
68 * <pre>
69 * [width]x[height]/[densityDpi]
70 * </pre>
71 * Supported flags:
72 * <ul>
73 * <li><pre>secure</pre>: creates a secure display</li>
Chris Li1ac23bb2020-04-20 22:39:53 -070074 * <li><pre>own_content_only</pre>: only shows this display's own content</li>
75 * <li><pre>should_show_system_decorations</pre>: supports system decorations</li>
P.Y. Laligand10188812015-05-06 14:50:52 -070076 * </ul>
Chris Li1ac23bb2020-04-20 22:39:53 -070077 * </p><p>
78 * Example:
79 * <ul>
80 * <li><code>1280x720/213</code>: make one overlay that is 1280x720 at 213dpi.</li>
81 * <li><code>1920x1080/320,secure;1280x720/213</code>: make two overlays, the first at 1080p and
82 * secure; the second at 720p.</li>
83 * <li><code>1920x1080/320|3840x2160/640</code>: make one overlay that is 1920x1080 at
84 * 213dpi by default, but can also be upscaled to 3840x2160 at 640dpi by the system if the
85 * display device allows.</li>
86 * <li>If the value is empty, then no overlay display devices are created.</li>
87 * </ul></p>
Jeff Brownbd6e1502012-08-28 03:27:37 -070088 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -070089final class OverlayDisplayAdapter extends DisplayAdapter {
90 static final String TAG = "OverlayDisplayAdapter";
91 static final boolean DEBUG = false;
Jeff Brownbd6e1502012-08-28 03:27:37 -070092
Chris Li1ac23bb2020-04-20 22:39:53 -070093 /**
94 * When this flag is set, the overlay display is considered secure.
95 * @see DisplayDeviceInfo#FLAG_SECURE
96 */
97 private static final String OVERLAY_DISPLAY_FLAG_SECURE = "secure";
98
99 /**
100 * When this flag is set, only show this display's own content; do not mirror the content of
101 * another display.
102 * @see DisplayDeviceInfo#FLAG_OWN_CONTENT_ONLY
103 */
104 private static final String OVERLAY_DISPLAY_FLAG_OWN_CONTENT_ONLY = "own_content_only";
105
106 /**
107 * When this flag is set, the overlay display should support system decorations.
108 * @see DisplayDeviceInfo#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
109 */
110 private static final String OVERLAY_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS =
111 "should_show_system_decorations";
112
Jeff Brownbd6e1502012-08-28 03:27:37 -0700113 private static final int MIN_WIDTH = 100;
114 private static final int MIN_HEIGHT = 100;
115 private static final int MAX_WIDTH = 4096;
116 private static final int MAX_HEIGHT = 4096;
117
Chris Li1ac23bb2020-04-20 22:39:53 -0700118 private static final String DISPLAY_SPLITTER = ";";
119 private static final String MODE_SPLITTER = "\\|";
120 private static final String FLAG_SPLITTER = ",";
121
122 private static final Pattern DISPLAY_PATTERN = Pattern.compile("([^,]+)(,[,_a-z]+)*");
123 private static final Pattern MODE_PATTERN = Pattern.compile("(\\d+)x(\\d+)/(\\d+)");
Jeff Brownbd6e1502012-08-28 03:27:37 -0700124
Wale Ogunwale361ca212014-11-20 11:42:38 -0800125 // Unique id prefix for overlay displays.
126 private static final String UNIQUE_ID_PREFIX = "overlay:";
127
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700128 private final Handler mUiHandler;
129 private final ArrayList<OverlayDisplayHandle> mOverlays =
130 new ArrayList<OverlayDisplayHandle>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700131 private String mCurrentOverlaySetting = "";
132
Jeff Brown66692502012-10-18 16:13:44 -0700133 // Called with SyncRoot lock held.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700134 public OverlayDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
135 Context context, Handler handler, Listener listener, Handler uiHandler) {
136 super(syncRoot, context, handler, listener, TAG);
137 mUiHandler = uiHandler;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700138 }
139
140 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700141 public void dumpLocked(PrintWriter pw) {
142 super.dumpLocked(pw);
Jeff Browncbad9762012-09-04 21:57:59 -0700143
Jeff Brownbd6e1502012-08-28 03:27:37 -0700144 pw.println("mCurrentOverlaySetting=" + mCurrentOverlaySetting);
145 pw.println("mOverlays: size=" + mOverlays.size());
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700146 for (OverlayDisplayHandle overlay : mOverlays) {
147 overlay.dumpLocked(pw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700148 }
149 }
150
151 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700152 public void registerLocked() {
153 super.registerLocked();
Jeff Browncbad9762012-09-04 21:57:59 -0700154
155 getHandler().post(new Runnable() {
156 @Override
157 public void run() {
158 getContext().getContentResolver().registerContentObserver(
Jeff Brownd4935962012-09-25 13:27:20 -0700159 Settings.Global.getUriFor(Settings.Global.OVERLAY_DISPLAY_DEVICES),
160 true, new ContentObserver(getHandler()) {
161 @Override
162 public void onChange(boolean selfChange) {
163 updateOverlayDisplayDevices();
164 }
165 });
Jeff Browncbad9762012-09-04 21:57:59 -0700166
Jeff Brownd4935962012-09-25 13:27:20 -0700167 updateOverlayDisplayDevices();
Jeff Browncbad9762012-09-04 21:57:59 -0700168 }
169 });
Jeff Brownbd6e1502012-08-28 03:27:37 -0700170 }
171
Jeff Brownd4935962012-09-25 13:27:20 -0700172 private void updateOverlayDisplayDevices() {
173 synchronized (getSyncRoot()) {
174 updateOverlayDisplayDevicesLocked();
175 }
176 }
177
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700178 private void updateOverlayDisplayDevicesLocked() {
Jeff Brownd4935962012-09-25 13:27:20 -0700179 String value = Settings.Global.getString(getContext().getContentResolver(),
180 Settings.Global.OVERLAY_DISPLAY_DEVICES);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700181 if (value == null) {
182 value = "";
183 }
184
185 if (value.equals(mCurrentOverlaySetting)) {
186 return;
187 }
188 mCurrentOverlaySetting = value;
189
190 if (!mOverlays.isEmpty()) {
191 Slog.i(TAG, "Dismissing all overlay display devices.");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700192 for (OverlayDisplayHandle overlay : mOverlays) {
193 overlay.dismissLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700194 }
195 mOverlays.clear();
196 }
197
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700198 int count = 0;
Chris Li1ac23bb2020-04-20 22:39:53 -0700199 for (String part : value.split(DISPLAY_SPLITTER)) {
P.Y. Laligand10188812015-05-06 14:50:52 -0700200 Matcher displayMatcher = DISPLAY_PATTERN.matcher(part);
201 if (displayMatcher.matches()) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700202 if (count >= 4) {
203 Slog.w(TAG, "Too many overlay display devices specified: " + value);
204 break;
205 }
P.Y. Laligand10188812015-05-06 14:50:52 -0700206 String modeString = displayMatcher.group(1);
207 String flagString = displayMatcher.group(2);
208 ArrayList<OverlayMode> modes = new ArrayList<>();
Chris Li1ac23bb2020-04-20 22:39:53 -0700209 for (String mode : modeString.split(MODE_SPLITTER)) {
P.Y. Laligand10188812015-05-06 14:50:52 -0700210 Matcher modeMatcher = MODE_PATTERN.matcher(mode);
211 if (modeMatcher.matches()) {
212 try {
213 int width = Integer.parseInt(modeMatcher.group(1), 10);
214 int height = Integer.parseInt(modeMatcher.group(2), 10);
215 int densityDpi = Integer.parseInt(modeMatcher.group(3), 10);
216 if (width >= MIN_WIDTH && width <= MAX_WIDTH
217 && height >= MIN_HEIGHT && height <= MAX_HEIGHT
218 && densityDpi >= DisplayMetrics.DENSITY_LOW
Jeff Brownfe4ad332015-06-09 18:26:31 -0700219 && densityDpi <= DisplayMetrics.DENSITY_XXXHIGH) {
P.Y. Laligand10188812015-05-06 14:50:52 -0700220 modes.add(new OverlayMode(width, height, densityDpi));
221 continue;
Jeff Brownfe4ad332015-06-09 18:26:31 -0700222 } else {
223 Slog.w(TAG, "Ignoring out-of-range overlay display mode: " + mode);
P.Y. Laligand10188812015-05-06 14:50:52 -0700224 }
225 } catch (NumberFormatException ex) {
226 }
227 } else if (mode.isEmpty()) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700228 continue;
229 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700230 }
P.Y. Laligand10188812015-05-06 14:50:52 -0700231 if (!modes.isEmpty()) {
232 int number = ++count;
233 String name = getContext().getResources().getString(
234 com.android.internal.R.string.display_manager_overlay_display_name,
235 number);
236 int gravity = chooseOverlayGravity(number);
Chris Li1ac23bb2020-04-20 22:39:53 -0700237 OverlayFlags flags = OverlayFlags.parseFlags(flagString);
P.Y. Laligand10188812015-05-06 14:50:52 -0700238
239 Slog.i(TAG, "Showing overlay display device #" + number
Chris Li1ac23bb2020-04-20 22:39:53 -0700240 + ": name=" + name + ", modes=" + Arrays.toString(modes.toArray())
241 + ", flags=" + flags);
P.Y. Laligand10188812015-05-06 14:50:52 -0700242
Chris Li1ac23bb2020-04-20 22:39:53 -0700243 mOverlays.add(new OverlayDisplayHandle(name, modes, gravity, flags, number));
P.Y. Laligand10188812015-05-06 14:50:52 -0700244 continue;
245 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700246 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700247 Slog.w(TAG, "Malformed overlay display devices setting: " + value);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700248 }
249 }
250
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700251 private static int chooseOverlayGravity(int overlayNumber) {
252 switch (overlayNumber) {
253 case 1:
254 return Gravity.TOP | Gravity.LEFT;
255 case 2:
256 return Gravity.BOTTOM | Gravity.RIGHT;
257 case 3:
258 return Gravity.TOP | Gravity.RIGHT;
259 case 4:
260 default:
261 return Gravity.BOTTOM | Gravity.LEFT;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700262 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700263 }
264
P.Y. Laligand10188812015-05-06 14:50:52 -0700265 private abstract class OverlayDisplayDevice extends DisplayDevice {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700266 private final String mName;
267 private final float mRefreshRate;
Andy McFaddene8b1aeb2014-06-13 14:05:40 -0700268 private final long mDisplayPresentationDeadlineNanos;
Chris Li1ac23bb2020-04-20 22:39:53 -0700269 private final OverlayFlags mFlags;
P.Y. Laligand10188812015-05-06 14:50:52 -0700270 private final List<OverlayMode> mRawModes;
271 private final Display.Mode[] mModes;
272 private final int mDefaultMode;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700273
Jeff Brown037c33e2014-04-09 00:31:55 -0700274 private int mState;
Craig Mautnerd5523dc2012-10-02 13:49:22 -0700275 private SurfaceTexture mSurfaceTexture;
Jeff Brown037c33e2014-04-09 00:31:55 -0700276 private Surface mSurface;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700277 private DisplayDeviceInfo mInfo;
P.Y. Laligand10188812015-05-06 14:50:52 -0700278 private int mActiveMode;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700279
Chris Li1ac23bb2020-04-20 22:39:53 -0700280 OverlayDisplayDevice(IBinder displayToken, String name,
P.Y. Laligand10188812015-05-06 14:50:52 -0700281 List<OverlayMode> modes, int activeMode, int defaultMode,
282 float refreshRate, long presentationDeadlineNanos,
Chris Li1ac23bb2020-04-20 22:39:53 -0700283 OverlayFlags flags, int state, SurfaceTexture surfaceTexture, int number) {
Wale Ogunwale361ca212014-11-20 11:42:38 -0800284 super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700285 mName = name;
286 mRefreshRate = refreshRate;
Andy McFaddene8b1aeb2014-06-13 14:05:40 -0700287 mDisplayPresentationDeadlineNanos = presentationDeadlineNanos;
Chris Li1ac23bb2020-04-20 22:39:53 -0700288 mFlags = flags;
Jeff Brown037c33e2014-04-09 00:31:55 -0700289 mState = state;
Craig Mautnerd5523dc2012-10-02 13:49:22 -0700290 mSurfaceTexture = surfaceTexture;
P.Y. Laligand10188812015-05-06 14:50:52 -0700291 mRawModes = modes;
292 mModes = new Display.Mode[modes.size()];
293 for (int i = 0; i < modes.size(); i++) {
294 OverlayMode mode = modes.get(i);
295 mModes[i] = createMode(mode.mWidth, mode.mHeight, refreshRate);
296 }
297 mActiveMode = activeMode;
298 mDefaultMode = defaultMode;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700299 }
300
Jesse Hall6a6bc212013-08-08 12:15:03 -0700301 public void destroyLocked() {
302 mSurfaceTexture = null;
303 if (mSurface != null) {
304 mSurface.release();
305 mSurface = null;
Craig Mautnerd5523dc2012-10-02 13:49:22 -0700306 }
Jesse Hall6a6bc212013-08-08 12:15:03 -0700307 SurfaceControl.destroyDisplay(getDisplayTokenLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700308 }
309
310 @Override
Michael Wright1c9977b2016-07-12 13:30:10 -0700311 public boolean hasStableUniqueId() {
312 return false;
313 }
314
315 @Override
Robert Carrae606b42018-02-15 15:36:23 -0800316 public void performTraversalLocked(SurfaceControl.Transaction t) {
Craig Mautnerd5523dc2012-10-02 13:49:22 -0700317 if (mSurfaceTexture != null) {
318 if (mSurface == null) {
319 mSurface = new Surface(mSurfaceTexture);
320 }
Robert Carrae606b42018-02-15 15:36:23 -0800321 setSurfaceLocked(t, mSurface);
Craig Mautnerd5523dc2012-10-02 13:49:22 -0700322 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700323 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700324
Jeff Brown037c33e2014-04-09 00:31:55 -0700325 public void setStateLocked(int state) {
326 mState = state;
327 mInfo = null;
328 }
329
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700330 @Override
331 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
332 if (mInfo == null) {
P.Y. Laligand10188812015-05-06 14:50:52 -0700333 Display.Mode mode = mModes[mActiveMode];
334 OverlayMode rawMode = mRawModes.get(mActiveMode);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700335 mInfo = new DisplayDeviceInfo();
336 mInfo.name = mName;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800337 mInfo.uniqueId = getUniqueId();
P.Y. Laligand10188812015-05-06 14:50:52 -0700338 mInfo.width = mode.getPhysicalWidth();
339 mInfo.height = mode.getPhysicalHeight();
340 mInfo.modeId = mode.getModeId();
341 mInfo.defaultModeId = mModes[0].getModeId();
342 mInfo.supportedModes = mModes;
343 mInfo.densityDpi = rawMode.mDensityDpi;
344 mInfo.xDpi = rawMode.mDensityDpi;
345 mInfo.yDpi = rawMode.mDensityDpi;
Andy McFaddene8b1aeb2014-06-13 14:05:40 -0700346 mInfo.presentationDeadlineNanos = mDisplayPresentationDeadlineNanos +
347 1000000000L / (int) mRefreshRate; // display's deadline + 1 frame
Jeff Brown7d00aff2013-08-02 19:03:49 -0700348 mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION;
Chris Li1ac23bb2020-04-20 22:39:53 -0700349 if (mFlags.mSecure) {
Jeff Brown040f44d2013-08-02 18:14:46 -0700350 mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE;
351 }
Chris Li1ac23bb2020-04-20 22:39:53 -0700352 if (mFlags.mOwnContentOnly) {
353 mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
354 }
355 if (mFlags.mShouldShowSystemDecorations) {
356 mInfo.flags |= DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
357 }
Jeff Brown92130f62012-10-24 21:28:33 -0700358 mInfo.type = Display.TYPE_OVERLAY;
Arthur Hungba025562019-02-15 18:15:10 +0800359 mInfo.touch = DisplayDeviceInfo.TOUCH_VIRTUAL;
Jeff Brown037c33e2014-04-09 00:31:55 -0700360 mInfo.state = mState;
Charles Chenb28fb722020-05-21 17:19:32 +0800361 // The display is trusted since it is created by system.
362 mInfo.flags |= FLAG_TRUSTED;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700363 }
364 return mInfo;
365 }
P.Y. Laligand10188812015-05-06 14:50:52 -0700366
367 @Override
Ana Kruleca74a8642019-11-14 00:51:00 +0100368 public void setDesiredDisplayModeSpecsLocked(
369 DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {
Steven Thomasec161942020-01-03 12:46:28 -0800370 final int id = displayModeSpecs.baseModeId;
P.Y. Laligand10188812015-05-06 14:50:52 -0700371 int index = -1;
372 if (id == 0) {
373 // Use the default.
374 index = 0;
375 } else {
376 for (int i = 0; i < mModes.length; i++) {
377 if (mModes[i].getModeId() == id) {
378 index = i;
379 break;
380 }
381 }
382 }
383 if (index == -1) {
384 Slog.w(TAG, "Unable to locate mode " + id + ", reverting to default.");
385 index = mDefaultMode;
386 }
387 if (mActiveMode == index) {
388 return;
389 }
390 mActiveMode = index;
391 mInfo = null;
392 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
393 onModeChangedLocked(index);
394 }
395
396 /**
397 * Called when the device switched to a new mode.
398 *
399 * @param index index of the mode in the list of modes
400 */
401 public abstract void onModeChangedLocked(int index);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700402 }
403
404 /**
405 * Functions as a handle for overlay display devices which are created and
406 * destroyed asynchronously.
407 *
408 * Guarded by the {@link DisplayManagerService.SyncRoot} lock.
409 */
410 private final class OverlayDisplayHandle implements OverlayDisplayWindow.Listener {
P.Y. Laligand10188812015-05-06 14:50:52 -0700411 private static final int DEFAULT_MODE_INDEX = 0;
412
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700413 private final String mName;
P.Y. Laligand10188812015-05-06 14:50:52 -0700414 private final List<OverlayMode> mModes;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700415 private final int mGravity;
Chris Li1ac23bb2020-04-20 22:39:53 -0700416 private final OverlayFlags mFlags;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800417 private final int mNumber;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700418
419 private OverlayDisplayWindow mWindow;
420 private OverlayDisplayDevice mDevice;
P.Y. Laligand10188812015-05-06 14:50:52 -0700421 private int mActiveMode;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700422
Chris Li1ac23bb2020-04-20 22:39:53 -0700423 OverlayDisplayHandle(
424 String name,
425 List<OverlayMode> modes,
426 int gravity,
427 OverlayFlags flags,
428 int number) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700429 mName = name;
P.Y. Laligand10188812015-05-06 14:50:52 -0700430 mModes = modes;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700431 mGravity = gravity;
Chris Li1ac23bb2020-04-20 22:39:53 -0700432 mFlags = flags;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800433 mNumber = number;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700434
P.Y. Laligand10188812015-05-06 14:50:52 -0700435 mActiveMode = 0;
436
437 showLocked();
438 }
439
440 private void showLocked() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700441 mUiHandler.post(mShowRunnable);
442 }
443
444 public void dismissLocked() {
445 mUiHandler.removeCallbacks(mShowRunnable);
446 mUiHandler.post(mDismissRunnable);
447 }
448
P.Y. Laligand10188812015-05-06 14:50:52 -0700449 private void onActiveModeChangedLocked(int index) {
450 mUiHandler.removeCallbacks(mResizeRunnable);
451 mActiveMode = index;
452 if (mWindow != null) {
453 mUiHandler.post(mResizeRunnable);
454 }
455 }
456
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700457 // Called on the UI thread.
458 @Override
Andy McFaddene8b1aeb2014-06-13 14:05:40 -0700459 public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate,
460 long presentationDeadlineNanos, int state) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700461 synchronized (getSyncRoot()) {
Chris Li1ac23bb2020-04-20 22:39:53 -0700462 IBinder displayToken = SurfaceControl.createDisplay(mName, mFlags.mSecure);
P.Y. Laligand10188812015-05-06 14:50:52 -0700463 mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode,
464 DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos,
Chris Li1ac23bb2020-04-20 22:39:53 -0700465 mFlags, state, surfaceTexture, mNumber) {
P.Y. Laligand10188812015-05-06 14:50:52 -0700466 @Override
467 public void onModeChangedLocked(int index) {
468 onActiveModeChangedLocked(index);
469 }
470 };
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700471
472 sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);
473 }
474 }
475
476 // Called on the UI thread.
477 @Override
478 public void onWindowDestroyed() {
479 synchronized (getSyncRoot()) {
480 if (mDevice != null) {
Jesse Hall6a6bc212013-08-08 12:15:03 -0700481 mDevice.destroyLocked();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700482 sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED);
483 }
484 }
485 }
486
Jeff Brown037c33e2014-04-09 00:31:55 -0700487 // Called on the UI thread.
488 @Override
489 public void onStateChanged(int state) {
490 synchronized (getSyncRoot()) {
491 if (mDevice != null) {
492 mDevice.setStateLocked(state);
493 sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_CHANGED);
494 }
495 }
496 }
497
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700498 public void dumpLocked(PrintWriter pw) {
Jeff Browncbad9762012-09-04 21:57:59 -0700499 pw.println(" " + mName + ":");
P.Y. Laligand10188812015-05-06 14:50:52 -0700500 pw.println(" mModes=" + Arrays.toString(mModes.toArray()));
501 pw.println(" mActiveMode=" + mActiveMode);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700502 pw.println(" mGravity=" + mGravity);
Chris Li1ac23bb2020-04-20 22:39:53 -0700503 pw.println(" mFlags=" + mFlags);
Wale Ogunwale361ca212014-11-20 11:42:38 -0800504 pw.println(" mNumber=" + mNumber);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700505
506 // Try to dump the window state.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700507 if (mWindow != null) {
Jeff Browncbad9762012-09-04 21:57:59 -0700508 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
509 ipw.increaseIndent();
Dianne Hackbornae6688b2015-02-11 17:02:41 -0800510 DumpUtils.dumpAsync(mUiHandler, mWindow, ipw, "", 200);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700511 }
512 }
513
514 // Runs on the UI thread.
515 private final Runnable mShowRunnable = new Runnable() {
516 @Override
517 public void run() {
P.Y. Laligand10188812015-05-06 14:50:52 -0700518 OverlayMode mode = mModes.get(mActiveMode);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700519 OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(),
Chris Li1ac23bb2020-04-20 22:39:53 -0700520 mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity,
521 mFlags.mSecure, OverlayDisplayHandle.this);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700522 window.show();
523
524 synchronized (getSyncRoot()) {
525 mWindow = window;
526 }
527 }
528 };
529
530 // Runs on the UI thread.
531 private final Runnable mDismissRunnable = new Runnable() {
532 @Override
533 public void run() {
534 OverlayDisplayWindow window;
535 synchronized (getSyncRoot()) {
536 window = mWindow;
537 mWindow = null;
538 }
539
540 if (window != null) {
541 window.dismiss();
542 }
543 }
544 };
P.Y. Laligand10188812015-05-06 14:50:52 -0700545
546 // Runs on the UI thread.
547 private final Runnable mResizeRunnable = new Runnable() {
548 @Override
549 public void run() {
550 OverlayMode mode;
551 OverlayDisplayWindow window;
552 synchronized (getSyncRoot()) {
553 if (mWindow == null) {
554 return;
555 }
556 mode = mModes.get(mActiveMode);
557 window = mWindow;
558 }
559 window.resize(mode.mWidth, mode.mHeight, mode.mDensityDpi);
560 }
561 };
562 }
563
564 /**
565 * A display mode for an overlay display.
566 */
567 private static final class OverlayMode {
568 final int mWidth;
569 final int mHeight;
570 final int mDensityDpi;
571
572 OverlayMode(int width, int height, int densityDpi) {
573 mWidth = width;
574 mHeight = height;
575 mDensityDpi = densityDpi;
576 }
577
578 @Override
579 public String toString() {
580 return new StringBuilder("{")
581 .append("width=").append(mWidth)
582 .append(", height=").append(mHeight)
583 .append(", densityDpi=").append(mDensityDpi)
584 .append("}")
585 .toString();
586 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700587 }
Chris Li1ac23bb2020-04-20 22:39:53 -0700588
589 /** Represents the flags of the overlay display. */
590 private static final class OverlayFlags {
591 /** See {@link #OVERLAY_DISPLAY_FLAG_SECURE}. */
592 final boolean mSecure;
593
594 /** See {@link #OVERLAY_DISPLAY_FLAG_OWN_CONTENT_ONLY}. */
595 final boolean mOwnContentOnly;
596
597 /** See {@link #OVERLAY_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS}. */
598 final boolean mShouldShowSystemDecorations;
599
600 OverlayFlags(
601 boolean secure,
602 boolean ownContentOnly,
603 boolean shouldShowSystemDecorations) {
604 mSecure = secure;
605 mOwnContentOnly = ownContentOnly;
606 mShouldShowSystemDecorations = shouldShowSystemDecorations;
607 }
608
609 static OverlayFlags parseFlags(@Nullable String flagString) {
610 if (TextUtils.isEmpty(flagString)) {
611 return new OverlayFlags(
612 false /* secure */,
613 false /* ownContentOnly */,
614 false /* shouldShowSystemDecorations */);
615 }
616
617 boolean secure = false;
618 boolean ownContentOnly = false;
619 boolean shouldShowSystemDecorations = false;
620 for (String flag: flagString.split(FLAG_SPLITTER)) {
621 if (OVERLAY_DISPLAY_FLAG_SECURE.equals(flag)) {
622 secure = true;
623 }
624 if (OVERLAY_DISPLAY_FLAG_OWN_CONTENT_ONLY.equals(flag)) {
625 ownContentOnly = true;
626 }
627 if (OVERLAY_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS.equals(flag)) {
628 shouldShowSystemDecorations = true;
629 }
630 }
631 return new OverlayFlags(secure, ownContentOnly, shouldShowSystemDecorations);
632 }
633
634 @Override
635 public String toString() {
636 return new StringBuilder("{")
637 .append("secure=").append(mSecure)
638 .append(", ownContentOnly=").append(mOwnContentOnly)
639 .append(", shouldShowSystemDecorations=").append(mShouldShowSystemDecorations)
640 .append("}")
641 .toString();
642 }
643 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700644}