Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package com.android.server.display; |
| 18 | |
Charles Chen | b28fb72 | 2020-05-21 17:19:32 +0800 | [diff] [blame] | 19 | import static com.android.server.display.DisplayDeviceInfo.FLAG_TRUSTED; |
| 20 | |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 21 | import android.annotation.Nullable; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 22 | import android.content.Context; |
| 23 | import android.database.ContentObserver; |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 24 | import android.graphics.SurfaceTexture; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 25 | import android.os.Handler; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 26 | import android.os.IBinder; |
| 27 | import android.provider.Settings; |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 28 | import android.text.TextUtils; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 29 | import android.util.DisplayMetrics; |
| 30 | import android.util.Slog; |
Jeff Brown | 92130f6 | 2012-10-24 21:28:33 -0700 | [diff] [blame] | 31 | import android.view.Display; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 32 | import android.view.Gravity; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 33 | import android.view.Surface; |
Mathias Agopian | 3866f0d | 2013-02-11 22:08:48 -0800 | [diff] [blame] | 34 | import android.view.SurfaceControl; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 35 | |
Michael Wright | a3dab23 | 2019-02-22 16:54:21 +0000 | [diff] [blame] | 36 | import com.android.internal.util.DumpUtils; |
| 37 | import com.android.internal.util.IndentingPrintWriter; |
| 38 | |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 39 | import java.io.PrintWriter; |
| 40 | import java.util.ArrayList; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 41 | import java.util.Arrays; |
| 42 | import java.util.List; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 43 | import java.util.regex.Matcher; |
| 44 | import 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 Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 51 | * 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. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 56 | * </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 Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 61 | * [display1];[display2];... |
| 62 | * </pre> |
| 63 | * with each display specified as: |
| 64 | * <pre> |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 65 | * [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 Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 74 | * <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. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 76 | * </ul> |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 77 | * </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 Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 88 | */ |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 89 | final class OverlayDisplayAdapter extends DisplayAdapter { |
| 90 | static final String TAG = "OverlayDisplayAdapter"; |
| 91 | static final boolean DEBUG = false; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 92 | |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 93 | /** |
| 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 Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 113 | 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 Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 118 | 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 Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 124 | |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 125 | // Unique id prefix for overlay displays. |
| 126 | private static final String UNIQUE_ID_PREFIX = "overlay:"; |
| 127 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 128 | private final Handler mUiHandler; |
| 129 | private final ArrayList<OverlayDisplayHandle> mOverlays = |
| 130 | new ArrayList<OverlayDisplayHandle>(); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 131 | private String mCurrentOverlaySetting = ""; |
| 132 | |
Jeff Brown | 6669250 | 2012-10-18 16:13:44 -0700 | [diff] [blame] | 133 | // Called with SyncRoot lock held. |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 134 | 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 Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | @Override |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 141 | public void dumpLocked(PrintWriter pw) { |
| 142 | super.dumpLocked(pw); |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 143 | |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 144 | pw.println("mCurrentOverlaySetting=" + mCurrentOverlaySetting); |
| 145 | pw.println("mOverlays: size=" + mOverlays.size()); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 146 | for (OverlayDisplayHandle overlay : mOverlays) { |
| 147 | overlay.dumpLocked(pw); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 148 | } |
| 149 | } |
| 150 | |
| 151 | @Override |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 152 | public void registerLocked() { |
| 153 | super.registerLocked(); |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 154 | |
| 155 | getHandler().post(new Runnable() { |
| 156 | @Override |
| 157 | public void run() { |
| 158 | getContext().getContentResolver().registerContentObserver( |
Jeff Brown | d493596 | 2012-09-25 13:27:20 -0700 | [diff] [blame] | 159 | 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 Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 166 | |
Jeff Brown | d493596 | 2012-09-25 13:27:20 -0700 | [diff] [blame] | 167 | updateOverlayDisplayDevices(); |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 168 | } |
| 169 | }); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 170 | } |
| 171 | |
Jeff Brown | d493596 | 2012-09-25 13:27:20 -0700 | [diff] [blame] | 172 | private void updateOverlayDisplayDevices() { |
| 173 | synchronized (getSyncRoot()) { |
| 174 | updateOverlayDisplayDevicesLocked(); |
| 175 | } |
| 176 | } |
| 177 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 178 | private void updateOverlayDisplayDevicesLocked() { |
Jeff Brown | d493596 | 2012-09-25 13:27:20 -0700 | [diff] [blame] | 179 | String value = Settings.Global.getString(getContext().getContentResolver(), |
| 180 | Settings.Global.OVERLAY_DISPLAY_DEVICES); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 181 | 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 Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 192 | for (OverlayDisplayHandle overlay : mOverlays) { |
| 193 | overlay.dismissLocked(); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 194 | } |
| 195 | mOverlays.clear(); |
| 196 | } |
| 197 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 198 | int count = 0; |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 199 | for (String part : value.split(DISPLAY_SPLITTER)) { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 200 | Matcher displayMatcher = DISPLAY_PATTERN.matcher(part); |
| 201 | if (displayMatcher.matches()) { |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 202 | if (count >= 4) { |
| 203 | Slog.w(TAG, "Too many overlay display devices specified: " + value); |
| 204 | break; |
| 205 | } |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 206 | String modeString = displayMatcher.group(1); |
| 207 | String flagString = displayMatcher.group(2); |
| 208 | ArrayList<OverlayMode> modes = new ArrayList<>(); |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 209 | for (String mode : modeString.split(MODE_SPLITTER)) { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 210 | 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 Brown | fe4ad33 | 2015-06-09 18:26:31 -0700 | [diff] [blame] | 219 | && densityDpi <= DisplayMetrics.DENSITY_XXXHIGH) { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 220 | modes.add(new OverlayMode(width, height, densityDpi)); |
| 221 | continue; |
Jeff Brown | fe4ad33 | 2015-06-09 18:26:31 -0700 | [diff] [blame] | 222 | } else { |
| 223 | Slog.w(TAG, "Ignoring out-of-range overlay display mode: " + mode); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 224 | } |
| 225 | } catch (NumberFormatException ex) { |
| 226 | } |
| 227 | } else if (mode.isEmpty()) { |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 228 | continue; |
| 229 | } |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 230 | } |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 231 | 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 Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 237 | OverlayFlags flags = OverlayFlags.parseFlags(flagString); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 238 | |
| 239 | Slog.i(TAG, "Showing overlay display device #" + number |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 240 | + ": name=" + name + ", modes=" + Arrays.toString(modes.toArray()) |
| 241 | + ", flags=" + flags); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 242 | |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 243 | mOverlays.add(new OverlayDisplayHandle(name, modes, gravity, flags, number)); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 244 | continue; |
| 245 | } |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 246 | } |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 247 | Slog.w(TAG, "Malformed overlay display devices setting: " + value); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 248 | } |
| 249 | } |
| 250 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 251 | 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 Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 262 | } |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 263 | } |
| 264 | |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 265 | private abstract class OverlayDisplayDevice extends DisplayDevice { |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 266 | private final String mName; |
| 267 | private final float mRefreshRate; |
Andy McFadden | e8b1aeb | 2014-06-13 14:05:40 -0700 | [diff] [blame] | 268 | private final long mDisplayPresentationDeadlineNanos; |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 269 | private final OverlayFlags mFlags; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 270 | private final List<OverlayMode> mRawModes; |
| 271 | private final Display.Mode[] mModes; |
| 272 | private final int mDefaultMode; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 273 | |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 274 | private int mState; |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 275 | private SurfaceTexture mSurfaceTexture; |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 276 | private Surface mSurface; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 277 | private DisplayDeviceInfo mInfo; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 278 | private int mActiveMode; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 279 | |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 280 | OverlayDisplayDevice(IBinder displayToken, String name, |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 281 | List<OverlayMode> modes, int activeMode, int defaultMode, |
| 282 | float refreshRate, long presentationDeadlineNanos, |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 283 | OverlayFlags flags, int state, SurfaceTexture surfaceTexture, int number) { |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 284 | super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 285 | mName = name; |
| 286 | mRefreshRate = refreshRate; |
Andy McFadden | e8b1aeb | 2014-06-13 14:05:40 -0700 | [diff] [blame] | 287 | mDisplayPresentationDeadlineNanos = presentationDeadlineNanos; |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 288 | mFlags = flags; |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 289 | mState = state; |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 290 | mSurfaceTexture = surfaceTexture; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 291 | 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 Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 299 | } |
| 300 | |
Jesse Hall | 6a6bc21 | 2013-08-08 12:15:03 -0700 | [diff] [blame] | 301 | public void destroyLocked() { |
| 302 | mSurfaceTexture = null; |
| 303 | if (mSurface != null) { |
| 304 | mSurface.release(); |
| 305 | mSurface = null; |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 306 | } |
Jesse Hall | 6a6bc21 | 2013-08-08 12:15:03 -0700 | [diff] [blame] | 307 | SurfaceControl.destroyDisplay(getDisplayTokenLocked()); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 308 | } |
| 309 | |
| 310 | @Override |
Michael Wright | 1c9977b | 2016-07-12 13:30:10 -0700 | [diff] [blame] | 311 | public boolean hasStableUniqueId() { |
| 312 | return false; |
| 313 | } |
| 314 | |
| 315 | @Override |
Robert Carr | ae606b4 | 2018-02-15 15:36:23 -0800 | [diff] [blame] | 316 | public void performTraversalLocked(SurfaceControl.Transaction t) { |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 317 | if (mSurfaceTexture != null) { |
| 318 | if (mSurface == null) { |
| 319 | mSurface = new Surface(mSurfaceTexture); |
| 320 | } |
Robert Carr | ae606b4 | 2018-02-15 15:36:23 -0800 | [diff] [blame] | 321 | setSurfaceLocked(t, mSurface); |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 322 | } |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 323 | } |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 324 | |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 325 | public void setStateLocked(int state) { |
| 326 | mState = state; |
| 327 | mInfo = null; |
| 328 | } |
| 329 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 330 | @Override |
| 331 | public DisplayDeviceInfo getDisplayDeviceInfoLocked() { |
| 332 | if (mInfo == null) { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 333 | Display.Mode mode = mModes[mActiveMode]; |
| 334 | OverlayMode rawMode = mRawModes.get(mActiveMode); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 335 | mInfo = new DisplayDeviceInfo(); |
| 336 | mInfo.name = mName; |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 337 | mInfo.uniqueId = getUniqueId(); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 338 | 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 McFadden | e8b1aeb | 2014-06-13 14:05:40 -0700 | [diff] [blame] | 346 | mInfo.presentationDeadlineNanos = mDisplayPresentationDeadlineNanos + |
| 347 | 1000000000L / (int) mRefreshRate; // display's deadline + 1 frame |
Jeff Brown | 7d00aff | 2013-08-02 19:03:49 -0700 | [diff] [blame] | 348 | mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION; |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 349 | if (mFlags.mSecure) { |
Jeff Brown | 040f44d | 2013-08-02 18:14:46 -0700 | [diff] [blame] | 350 | mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; |
| 351 | } |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 352 | 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 Brown | 92130f6 | 2012-10-24 21:28:33 -0700 | [diff] [blame] | 358 | mInfo.type = Display.TYPE_OVERLAY; |
Arthur Hung | ba02556 | 2019-02-15 18:15:10 +0800 | [diff] [blame] | 359 | mInfo.touch = DisplayDeviceInfo.TOUCH_VIRTUAL; |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 360 | mInfo.state = mState; |
Charles Chen | b28fb72 | 2020-05-21 17:19:32 +0800 | [diff] [blame] | 361 | // The display is trusted since it is created by system. |
| 362 | mInfo.flags |= FLAG_TRUSTED; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 363 | } |
| 364 | return mInfo; |
| 365 | } |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 366 | |
| 367 | @Override |
Ana Krulec | a74a864 | 2019-11-14 00:51:00 +0100 | [diff] [blame] | 368 | public void setDesiredDisplayModeSpecsLocked( |
| 369 | DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) { |
Steven Thomas | ec16194 | 2020-01-03 12:46:28 -0800 | [diff] [blame] | 370 | final int id = displayModeSpecs.baseModeId; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 371 | 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 Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 402 | } |
| 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. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 411 | private static final int DEFAULT_MODE_INDEX = 0; |
| 412 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 413 | private final String mName; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 414 | private final List<OverlayMode> mModes; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 415 | private final int mGravity; |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 416 | private final OverlayFlags mFlags; |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 417 | private final int mNumber; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 418 | |
| 419 | private OverlayDisplayWindow mWindow; |
| 420 | private OverlayDisplayDevice mDevice; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 421 | private int mActiveMode; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 422 | |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 423 | OverlayDisplayHandle( |
| 424 | String name, |
| 425 | List<OverlayMode> modes, |
| 426 | int gravity, |
| 427 | OverlayFlags flags, |
| 428 | int number) { |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 429 | mName = name; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 430 | mModes = modes; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 431 | mGravity = gravity; |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 432 | mFlags = flags; |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 433 | mNumber = number; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 434 | |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 435 | mActiveMode = 0; |
| 436 | |
| 437 | showLocked(); |
| 438 | } |
| 439 | |
| 440 | private void showLocked() { |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 441 | mUiHandler.post(mShowRunnable); |
| 442 | } |
| 443 | |
| 444 | public void dismissLocked() { |
| 445 | mUiHandler.removeCallbacks(mShowRunnable); |
| 446 | mUiHandler.post(mDismissRunnable); |
| 447 | } |
| 448 | |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 449 | private void onActiveModeChangedLocked(int index) { |
| 450 | mUiHandler.removeCallbacks(mResizeRunnable); |
| 451 | mActiveMode = index; |
| 452 | if (mWindow != null) { |
| 453 | mUiHandler.post(mResizeRunnable); |
| 454 | } |
| 455 | } |
| 456 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 457 | // Called on the UI thread. |
| 458 | @Override |
Andy McFadden | e8b1aeb | 2014-06-13 14:05:40 -0700 | [diff] [blame] | 459 | public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate, |
| 460 | long presentationDeadlineNanos, int state) { |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 461 | synchronized (getSyncRoot()) { |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 462 | IBinder displayToken = SurfaceControl.createDisplay(mName, mFlags.mSecure); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 463 | mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode, |
| 464 | DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos, |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 465 | mFlags, state, surfaceTexture, mNumber) { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 466 | @Override |
| 467 | public void onModeChangedLocked(int index) { |
| 468 | onActiveModeChangedLocked(index); |
| 469 | } |
| 470 | }; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 471 | |
| 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 Hall | 6a6bc21 | 2013-08-08 12:15:03 -0700 | [diff] [blame] | 481 | mDevice.destroyLocked(); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 482 | sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED); |
| 483 | } |
| 484 | } |
| 485 | } |
| 486 | |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 487 | // 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 Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 498 | public void dumpLocked(PrintWriter pw) { |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 499 | pw.println(" " + mName + ":"); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 500 | pw.println(" mModes=" + Arrays.toString(mModes.toArray())); |
| 501 | pw.println(" mActiveMode=" + mActiveMode); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 502 | pw.println(" mGravity=" + mGravity); |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 503 | pw.println(" mFlags=" + mFlags); |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 504 | pw.println(" mNumber=" + mNumber); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 505 | |
| 506 | // Try to dump the window state. |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 507 | if (mWindow != null) { |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 508 | final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); |
| 509 | ipw.increaseIndent(); |
Dianne Hackborn | ae6688b | 2015-02-11 17:02:41 -0800 | [diff] [blame] | 510 | DumpUtils.dumpAsync(mUiHandler, mWindow, ipw, "", 200); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 511 | } |
| 512 | } |
| 513 | |
| 514 | // Runs on the UI thread. |
| 515 | private final Runnable mShowRunnable = new Runnable() { |
| 516 | @Override |
| 517 | public void run() { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 518 | OverlayMode mode = mModes.get(mActiveMode); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 519 | OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(), |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 520 | mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity, |
| 521 | mFlags.mSecure, OverlayDisplayHandle.this); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 522 | 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. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 545 | |
| 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 Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 587 | } |
Chris Li | 1ac23bb | 2020-04-20 22:39:53 -0700 | [diff] [blame] | 588 | |
| 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 Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 644 | } |