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 | |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 19 | import com.android.internal.util.DumpUtils; |
| 20 | import com.android.internal.util.IndentingPrintWriter; |
| 21 | |
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; |
| 28 | import android.util.DisplayMetrics; |
| 29 | import android.util.Slog; |
Jeff Brown | 92130f6 | 2012-10-24 21:28:33 -0700 | [diff] [blame] | 30 | import android.view.Display; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 31 | import android.view.Gravity; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 32 | import android.view.Surface; |
Mathias Agopian | 3866f0d | 2013-02-11 22:08:48 -0800 | [diff] [blame] | 33 | import android.view.SurfaceControl; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 34 | |
| 35 | import java.io.PrintWriter; |
| 36 | import java.util.ArrayList; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 37 | import java.util.Arrays; |
| 38 | import java.util.List; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 39 | import java.util.regex.Matcher; |
| 40 | import java.util.regex.Pattern; |
| 41 | |
| 42 | /** |
| 43 | * A display adapter that uses overlay windows to simulate secondary displays |
| 44 | * for development purposes. Use Development Settings to enable one or more |
| 45 | * overlay displays. |
| 46 | * <p> |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 47 | * This object has two different handlers (which may be the same) which must not |
| 48 | * get confused. The main handler is used to posting messages to the display manager |
| 49 | * service as usual. The UI handler is only used by the {@link OverlayDisplayWindow}. |
| 50 | * </p><p> |
| 51 | * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 52 | * </p><p> |
| 53 | * This adapter is configured via the |
| 54 | * {@link android.provider.Settings.Global#OVERLAY_DISPLAY_DEVICES} setting. This setting should be |
| 55 | * formatted as follows: |
| 56 | * <pre> |
| 57 | * [mode1]|[mode2]|...,[flag1],[flag2],... |
| 58 | * </pre> |
| 59 | * with each mode specified as: |
| 60 | * <pre> |
| 61 | * [width]x[height]/[densityDpi] |
| 62 | * </pre> |
| 63 | * Supported flags: |
| 64 | * <ul> |
| 65 | * <li><pre>secure</pre>: creates a secure display</li> |
| 66 | * </ul> |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 67 | * </p> |
| 68 | */ |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 69 | final class OverlayDisplayAdapter extends DisplayAdapter { |
| 70 | static final String TAG = "OverlayDisplayAdapter"; |
| 71 | static final boolean DEBUG = false; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 72 | |
| 73 | private static final int MIN_WIDTH = 100; |
| 74 | private static final int MIN_HEIGHT = 100; |
| 75 | private static final int MAX_WIDTH = 4096; |
| 76 | private static final int MAX_HEIGHT = 4096; |
| 77 | |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 78 | private static final Pattern DISPLAY_PATTERN = |
| 79 | Pattern.compile("([^,]+)(,[a-z]+)*"); |
| 80 | private static final Pattern MODE_PATTERN = |
| 81 | Pattern.compile("(\\d+)x(\\d+)/(\\d+)"); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 82 | |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 83 | // Unique id prefix for overlay displays. |
| 84 | private static final String UNIQUE_ID_PREFIX = "overlay:"; |
| 85 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 86 | private final Handler mUiHandler; |
| 87 | private final ArrayList<OverlayDisplayHandle> mOverlays = |
| 88 | new ArrayList<OverlayDisplayHandle>(); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 89 | private String mCurrentOverlaySetting = ""; |
| 90 | |
Jeff Brown | 6669250 | 2012-10-18 16:13:44 -0700 | [diff] [blame] | 91 | // Called with SyncRoot lock held. |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 92 | public OverlayDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, |
| 93 | Context context, Handler handler, Listener listener, Handler uiHandler) { |
| 94 | super(syncRoot, context, handler, listener, TAG); |
| 95 | mUiHandler = uiHandler; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | @Override |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 99 | public void dumpLocked(PrintWriter pw) { |
| 100 | super.dumpLocked(pw); |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 101 | |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 102 | pw.println("mCurrentOverlaySetting=" + mCurrentOverlaySetting); |
| 103 | pw.println("mOverlays: size=" + mOverlays.size()); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 104 | for (OverlayDisplayHandle overlay : mOverlays) { |
| 105 | overlay.dumpLocked(pw); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 106 | } |
| 107 | } |
| 108 | |
| 109 | @Override |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 110 | public void registerLocked() { |
| 111 | super.registerLocked(); |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 112 | |
| 113 | getHandler().post(new Runnable() { |
| 114 | @Override |
| 115 | public void run() { |
| 116 | getContext().getContentResolver().registerContentObserver( |
Jeff Brown | d493596 | 2012-09-25 13:27:20 -0700 | [diff] [blame] | 117 | Settings.Global.getUriFor(Settings.Global.OVERLAY_DISPLAY_DEVICES), |
| 118 | true, new ContentObserver(getHandler()) { |
| 119 | @Override |
| 120 | public void onChange(boolean selfChange) { |
| 121 | updateOverlayDisplayDevices(); |
| 122 | } |
| 123 | }); |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 124 | |
Jeff Brown | d493596 | 2012-09-25 13:27:20 -0700 | [diff] [blame] | 125 | updateOverlayDisplayDevices(); |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 126 | } |
| 127 | }); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 128 | } |
| 129 | |
Jeff Brown | d493596 | 2012-09-25 13:27:20 -0700 | [diff] [blame] | 130 | private void updateOverlayDisplayDevices() { |
| 131 | synchronized (getSyncRoot()) { |
| 132 | updateOverlayDisplayDevicesLocked(); |
| 133 | } |
| 134 | } |
| 135 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 136 | private void updateOverlayDisplayDevicesLocked() { |
Jeff Brown | d493596 | 2012-09-25 13:27:20 -0700 | [diff] [blame] | 137 | String value = Settings.Global.getString(getContext().getContentResolver(), |
| 138 | Settings.Global.OVERLAY_DISPLAY_DEVICES); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 139 | if (value == null) { |
| 140 | value = ""; |
| 141 | } |
| 142 | |
| 143 | if (value.equals(mCurrentOverlaySetting)) { |
| 144 | return; |
| 145 | } |
| 146 | mCurrentOverlaySetting = value; |
| 147 | |
| 148 | if (!mOverlays.isEmpty()) { |
| 149 | Slog.i(TAG, "Dismissing all overlay display devices."); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 150 | for (OverlayDisplayHandle overlay : mOverlays) { |
| 151 | overlay.dismissLocked(); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 152 | } |
| 153 | mOverlays.clear(); |
| 154 | } |
| 155 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 156 | int count = 0; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 157 | for (String part : value.split(";")) { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 158 | Matcher displayMatcher = DISPLAY_PATTERN.matcher(part); |
| 159 | if (displayMatcher.matches()) { |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 160 | if (count >= 4) { |
| 161 | Slog.w(TAG, "Too many overlay display devices specified: " + value); |
| 162 | break; |
| 163 | } |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 164 | String modeString = displayMatcher.group(1); |
| 165 | String flagString = displayMatcher.group(2); |
| 166 | ArrayList<OverlayMode> modes = new ArrayList<>(); |
| 167 | for (String mode : modeString.split("\\|")) { |
| 168 | Matcher modeMatcher = MODE_PATTERN.matcher(mode); |
| 169 | if (modeMatcher.matches()) { |
| 170 | try { |
| 171 | int width = Integer.parseInt(modeMatcher.group(1), 10); |
| 172 | int height = Integer.parseInt(modeMatcher.group(2), 10); |
| 173 | int densityDpi = Integer.parseInt(modeMatcher.group(3), 10); |
| 174 | if (width >= MIN_WIDTH && width <= MAX_WIDTH |
| 175 | && height >= MIN_HEIGHT && height <= MAX_HEIGHT |
| 176 | && densityDpi >= DisplayMetrics.DENSITY_LOW |
Jeff Brown | fe4ad33 | 2015-06-09 18:26:31 -0700 | [diff] [blame] | 177 | && densityDpi <= DisplayMetrics.DENSITY_XXXHIGH) { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 178 | modes.add(new OverlayMode(width, height, densityDpi)); |
| 179 | continue; |
Jeff Brown | fe4ad33 | 2015-06-09 18:26:31 -0700 | [diff] [blame] | 180 | } else { |
| 181 | Slog.w(TAG, "Ignoring out-of-range overlay display mode: " + mode); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 182 | } |
| 183 | } catch (NumberFormatException ex) { |
| 184 | } |
| 185 | } else if (mode.isEmpty()) { |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 186 | continue; |
| 187 | } |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 188 | } |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 189 | if (!modes.isEmpty()) { |
| 190 | int number = ++count; |
| 191 | String name = getContext().getResources().getString( |
| 192 | com.android.internal.R.string.display_manager_overlay_display_name, |
| 193 | number); |
| 194 | int gravity = chooseOverlayGravity(number); |
| 195 | boolean secure = flagString != null && flagString.contains(",secure"); |
| 196 | |
| 197 | Slog.i(TAG, "Showing overlay display device #" + number |
| 198 | + ": name=" + name + ", modes=" + Arrays.toString(modes.toArray())); |
| 199 | |
| 200 | mOverlays.add(new OverlayDisplayHandle(name, modes, gravity, secure, number)); |
| 201 | continue; |
| 202 | } |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 203 | } |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 204 | Slog.w(TAG, "Malformed overlay display devices setting: " + value); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 205 | } |
| 206 | } |
| 207 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 208 | private static int chooseOverlayGravity(int overlayNumber) { |
| 209 | switch (overlayNumber) { |
| 210 | case 1: |
| 211 | return Gravity.TOP | Gravity.LEFT; |
| 212 | case 2: |
| 213 | return Gravity.BOTTOM | Gravity.RIGHT; |
| 214 | case 3: |
| 215 | return Gravity.TOP | Gravity.RIGHT; |
| 216 | case 4: |
| 217 | default: |
| 218 | return Gravity.BOTTOM | Gravity.LEFT; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 219 | } |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 220 | } |
| 221 | |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 222 | private abstract class OverlayDisplayDevice extends DisplayDevice { |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 223 | private final String mName; |
| 224 | private final float mRefreshRate; |
Andy McFadden | e8b1aeb | 2014-06-13 14:05:40 -0700 | [diff] [blame] | 225 | private final long mDisplayPresentationDeadlineNanos; |
Jeff Brown | 040f44d | 2013-08-02 18:14:46 -0700 | [diff] [blame] | 226 | private final boolean mSecure; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 227 | private final List<OverlayMode> mRawModes; |
| 228 | private final Display.Mode[] mModes; |
| 229 | private final int mDefaultMode; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 230 | |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 231 | private int mState; |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 232 | private SurfaceTexture mSurfaceTexture; |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 233 | private Surface mSurface; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 234 | private DisplayDeviceInfo mInfo; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 235 | private int mActiveMode; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 236 | |
| 237 | public OverlayDisplayDevice(IBinder displayToken, String name, |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 238 | List<OverlayMode> modes, int activeMode, int defaultMode, |
| 239 | float refreshRate, long presentationDeadlineNanos, |
| 240 | boolean secure, int state, |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 241 | SurfaceTexture surfaceTexture, int number) { |
| 242 | super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 243 | mName = name; |
| 244 | mRefreshRate = refreshRate; |
Andy McFadden | e8b1aeb | 2014-06-13 14:05:40 -0700 | [diff] [blame] | 245 | mDisplayPresentationDeadlineNanos = presentationDeadlineNanos; |
Jeff Brown | 040f44d | 2013-08-02 18:14:46 -0700 | [diff] [blame] | 246 | mSecure = secure; |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 247 | mState = state; |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 248 | mSurfaceTexture = surfaceTexture; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 249 | mRawModes = modes; |
| 250 | mModes = new Display.Mode[modes.size()]; |
| 251 | for (int i = 0; i < modes.size(); i++) { |
| 252 | OverlayMode mode = modes.get(i); |
| 253 | mModes[i] = createMode(mode.mWidth, mode.mHeight, refreshRate); |
| 254 | } |
| 255 | mActiveMode = activeMode; |
| 256 | mDefaultMode = defaultMode; |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 257 | } |
| 258 | |
Jesse Hall | 6a6bc21 | 2013-08-08 12:15:03 -0700 | [diff] [blame] | 259 | public void destroyLocked() { |
| 260 | mSurfaceTexture = null; |
| 261 | if (mSurface != null) { |
| 262 | mSurface.release(); |
| 263 | mSurface = null; |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 264 | } |
Jesse Hall | 6a6bc21 | 2013-08-08 12:15:03 -0700 | [diff] [blame] | 265 | SurfaceControl.destroyDisplay(getDisplayTokenLocked()); |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 266 | } |
| 267 | |
| 268 | @Override |
Michael Wright | 1c9977b | 2016-07-12 13:30:10 -0700 | [diff] [blame] | 269 | public boolean hasStableUniqueId() { |
| 270 | return false; |
| 271 | } |
| 272 | |
| 273 | @Override |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 274 | public void performTraversalInTransactionLocked() { |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 275 | if (mSurfaceTexture != null) { |
| 276 | if (mSurface == null) { |
| 277 | mSurface = new Surface(mSurfaceTexture); |
| 278 | } |
| 279 | setSurfaceInTransactionLocked(mSurface); |
Craig Mautner | d5523dc | 2012-10-02 13:49:22 -0700 | [diff] [blame] | 280 | } |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 281 | } |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 282 | |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 283 | public void setStateLocked(int state) { |
| 284 | mState = state; |
| 285 | mInfo = null; |
| 286 | } |
| 287 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 288 | @Override |
| 289 | public DisplayDeviceInfo getDisplayDeviceInfoLocked() { |
| 290 | if (mInfo == null) { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 291 | Display.Mode mode = mModes[mActiveMode]; |
| 292 | OverlayMode rawMode = mRawModes.get(mActiveMode); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 293 | mInfo = new DisplayDeviceInfo(); |
| 294 | mInfo.name = mName; |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 295 | mInfo.uniqueId = getUniqueId(); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 296 | mInfo.width = mode.getPhysicalWidth(); |
| 297 | mInfo.height = mode.getPhysicalHeight(); |
| 298 | mInfo.modeId = mode.getModeId(); |
| 299 | mInfo.defaultModeId = mModes[0].getModeId(); |
| 300 | mInfo.supportedModes = mModes; |
| 301 | mInfo.densityDpi = rawMode.mDensityDpi; |
| 302 | mInfo.xDpi = rawMode.mDensityDpi; |
| 303 | mInfo.yDpi = rawMode.mDensityDpi; |
Andy McFadden | e8b1aeb | 2014-06-13 14:05:40 -0700 | [diff] [blame] | 304 | mInfo.presentationDeadlineNanos = mDisplayPresentationDeadlineNanos + |
| 305 | 1000000000L / (int) mRefreshRate; // display's deadline + 1 frame |
Jeff Brown | 7d00aff | 2013-08-02 19:03:49 -0700 | [diff] [blame] | 306 | mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION; |
Jeff Brown | 040f44d | 2013-08-02 18:14:46 -0700 | [diff] [blame] | 307 | if (mSecure) { |
| 308 | mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; |
| 309 | } |
Jeff Brown | 92130f6 | 2012-10-24 21:28:33 -0700 | [diff] [blame] | 310 | mInfo.type = Display.TYPE_OVERLAY; |
Jeff Brown | d728bf5 | 2012-09-08 18:05:28 -0700 | [diff] [blame] | 311 | mInfo.touch = DisplayDeviceInfo.TOUCH_NONE; |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 312 | mInfo.state = mState; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 313 | } |
| 314 | return mInfo; |
| 315 | } |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 316 | |
| 317 | @Override |
Michael Wright | 1c9977b | 2016-07-12 13:30:10 -0700 | [diff] [blame] | 318 | public void requestDisplayModesInTransactionLocked(int color, int id) { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 319 | int index = -1; |
| 320 | if (id == 0) { |
| 321 | // Use the default. |
| 322 | index = 0; |
| 323 | } else { |
| 324 | for (int i = 0; i < mModes.length; i++) { |
| 325 | if (mModes[i].getModeId() == id) { |
| 326 | index = i; |
| 327 | break; |
| 328 | } |
| 329 | } |
| 330 | } |
| 331 | if (index == -1) { |
| 332 | Slog.w(TAG, "Unable to locate mode " + id + ", reverting to default."); |
| 333 | index = mDefaultMode; |
| 334 | } |
| 335 | if (mActiveMode == index) { |
| 336 | return; |
| 337 | } |
| 338 | mActiveMode = index; |
| 339 | mInfo = null; |
| 340 | sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); |
| 341 | onModeChangedLocked(index); |
| 342 | } |
| 343 | |
| 344 | /** |
| 345 | * Called when the device switched to a new mode. |
| 346 | * |
| 347 | * @param index index of the mode in the list of modes |
| 348 | */ |
| 349 | public abstract void onModeChangedLocked(int index); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 350 | } |
| 351 | |
| 352 | /** |
| 353 | * Functions as a handle for overlay display devices which are created and |
| 354 | * destroyed asynchronously. |
| 355 | * |
| 356 | * Guarded by the {@link DisplayManagerService.SyncRoot} lock. |
| 357 | */ |
| 358 | private final class OverlayDisplayHandle implements OverlayDisplayWindow.Listener { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 359 | private static final int DEFAULT_MODE_INDEX = 0; |
| 360 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 361 | private final String mName; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 362 | private final List<OverlayMode> mModes; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 363 | private final int mGravity; |
Jeff Brown | 040f44d | 2013-08-02 18:14:46 -0700 | [diff] [blame] | 364 | private final boolean mSecure; |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 365 | private final int mNumber; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 366 | |
| 367 | private OverlayDisplayWindow mWindow; |
| 368 | private OverlayDisplayDevice mDevice; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 369 | private int mActiveMode; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 370 | |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 371 | public OverlayDisplayHandle(String name, List<OverlayMode> modes, int gravity, |
| 372 | boolean secure, int number) { |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 373 | mName = name; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 374 | mModes = modes; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 375 | mGravity = gravity; |
Jeff Brown | 040f44d | 2013-08-02 18:14:46 -0700 | [diff] [blame] | 376 | mSecure = secure; |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 377 | mNumber = number; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 378 | |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 379 | mActiveMode = 0; |
| 380 | |
| 381 | showLocked(); |
| 382 | } |
| 383 | |
| 384 | private void showLocked() { |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 385 | mUiHandler.post(mShowRunnable); |
| 386 | } |
| 387 | |
| 388 | public void dismissLocked() { |
| 389 | mUiHandler.removeCallbacks(mShowRunnable); |
| 390 | mUiHandler.post(mDismissRunnable); |
| 391 | } |
| 392 | |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 393 | private void onActiveModeChangedLocked(int index) { |
| 394 | mUiHandler.removeCallbacks(mResizeRunnable); |
| 395 | mActiveMode = index; |
| 396 | if (mWindow != null) { |
| 397 | mUiHandler.post(mResizeRunnable); |
| 398 | } |
| 399 | } |
| 400 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 401 | // Called on the UI thread. |
| 402 | @Override |
Andy McFadden | e8b1aeb | 2014-06-13 14:05:40 -0700 | [diff] [blame] | 403 | public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate, |
| 404 | long presentationDeadlineNanos, int state) { |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 405 | synchronized (getSyncRoot()) { |
Jeff Brown | 040f44d | 2013-08-02 18:14:46 -0700 | [diff] [blame] | 406 | IBinder displayToken = SurfaceControl.createDisplay(mName, mSecure); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 407 | mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode, |
| 408 | DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos, |
| 409 | mSecure, state, surfaceTexture, mNumber) { |
| 410 | @Override |
| 411 | public void onModeChangedLocked(int index) { |
| 412 | onActiveModeChangedLocked(index); |
| 413 | } |
| 414 | }; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 415 | |
| 416 | sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED); |
| 417 | } |
| 418 | } |
| 419 | |
| 420 | // Called on the UI thread. |
| 421 | @Override |
| 422 | public void onWindowDestroyed() { |
| 423 | synchronized (getSyncRoot()) { |
| 424 | if (mDevice != null) { |
Jesse Hall | 6a6bc21 | 2013-08-08 12:15:03 -0700 | [diff] [blame] | 425 | mDevice.destroyLocked(); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 426 | sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED); |
| 427 | } |
| 428 | } |
| 429 | } |
| 430 | |
Jeff Brown | 037c33e | 2014-04-09 00:31:55 -0700 | [diff] [blame] | 431 | // Called on the UI thread. |
| 432 | @Override |
| 433 | public void onStateChanged(int state) { |
| 434 | synchronized (getSyncRoot()) { |
| 435 | if (mDevice != null) { |
| 436 | mDevice.setStateLocked(state); |
| 437 | sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_CHANGED); |
| 438 | } |
| 439 | } |
| 440 | } |
| 441 | |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 442 | public void dumpLocked(PrintWriter pw) { |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 443 | pw.println(" " + mName + ":"); |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 444 | pw.println(" mModes=" + Arrays.toString(mModes.toArray())); |
| 445 | pw.println(" mActiveMode=" + mActiveMode); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 446 | pw.println(" mGravity=" + mGravity); |
Jeff Brown | 040f44d | 2013-08-02 18:14:46 -0700 | [diff] [blame] | 447 | pw.println(" mSecure=" + mSecure); |
Wale Ogunwale | 361ca21 | 2014-11-20 11:42:38 -0800 | [diff] [blame] | 448 | pw.println(" mNumber=" + mNumber); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 449 | |
| 450 | // Try to dump the window state. |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 451 | if (mWindow != null) { |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 452 | final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); |
| 453 | ipw.increaseIndent(); |
Dianne Hackborn | ae6688b | 2015-02-11 17:02:41 -0800 | [diff] [blame] | 454 | DumpUtils.dumpAsync(mUiHandler, mWindow, ipw, "", 200); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 455 | } |
| 456 | } |
| 457 | |
| 458 | // Runs on the UI thread. |
| 459 | private final Runnable mShowRunnable = new Runnable() { |
| 460 | @Override |
| 461 | public void run() { |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 462 | OverlayMode mode = mModes.get(mActiveMode); |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 463 | OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(), |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 464 | mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity, mSecure, |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 465 | OverlayDisplayHandle.this); |
| 466 | window.show(); |
| 467 | |
| 468 | synchronized (getSyncRoot()) { |
| 469 | mWindow = window; |
| 470 | } |
| 471 | } |
| 472 | }; |
| 473 | |
| 474 | // Runs on the UI thread. |
| 475 | private final Runnable mDismissRunnable = new Runnable() { |
| 476 | @Override |
| 477 | public void run() { |
| 478 | OverlayDisplayWindow window; |
| 479 | synchronized (getSyncRoot()) { |
| 480 | window = mWindow; |
| 481 | mWindow = null; |
| 482 | } |
| 483 | |
| 484 | if (window != null) { |
| 485 | window.dismiss(); |
| 486 | } |
| 487 | } |
| 488 | }; |
P.Y. Laligand | 1018881 | 2015-05-06 14:50:52 -0700 | [diff] [blame] | 489 | |
| 490 | // Runs on the UI thread. |
| 491 | private final Runnable mResizeRunnable = new Runnable() { |
| 492 | @Override |
| 493 | public void run() { |
| 494 | OverlayMode mode; |
| 495 | OverlayDisplayWindow window; |
| 496 | synchronized (getSyncRoot()) { |
| 497 | if (mWindow == null) { |
| 498 | return; |
| 499 | } |
| 500 | mode = mModes.get(mActiveMode); |
| 501 | window = mWindow; |
| 502 | } |
| 503 | window.resize(mode.mWidth, mode.mHeight, mode.mDensityDpi); |
| 504 | } |
| 505 | }; |
| 506 | } |
| 507 | |
| 508 | /** |
| 509 | * A display mode for an overlay display. |
| 510 | */ |
| 511 | private static final class OverlayMode { |
| 512 | final int mWidth; |
| 513 | final int mHeight; |
| 514 | final int mDensityDpi; |
| 515 | |
| 516 | OverlayMode(int width, int height, int densityDpi) { |
| 517 | mWidth = width; |
| 518 | mHeight = height; |
| 519 | mDensityDpi = densityDpi; |
| 520 | } |
| 521 | |
| 522 | @Override |
| 523 | public String toString() { |
| 524 | return new StringBuilder("{") |
| 525 | .append("width=").append(mWidth) |
| 526 | .append(", height=").append(mHeight) |
| 527 | .append(", densityDpi=").append(mDensityDpi) |
| 528 | .append("}") |
| 529 | .toString(); |
| 530 | } |
Jeff Brown | bd6e150 | 2012-08-28 03:27:37 -0700 | [diff] [blame] | 531 | } |
| 532 | } |