1 /* 2 * Copyright (C) 2013 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 19 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED; 20 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 21 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; 22 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL; 23 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP; 24 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; 25 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS; 26 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION; 27 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; 28 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT; 29 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; 30 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; 31 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED; 32 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH; 33 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED; 34 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; 35 36 import static com.android.server.display.DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED; 37 import static com.android.server.display.DisplayDeviceInfo.FLAG_DEVICE_DISPLAY_GROUP; 38 import static com.android.server.display.DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP; 39 import static com.android.server.display.DisplayDeviceInfo.FLAG_STEAL_TOP_FOCUS_DISABLED; 40 import static com.android.server.display.DisplayDeviceInfo.FLAG_TOUCH_FEEDBACK_DISABLED; 41 import static com.android.server.display.DisplayDeviceInfo.FLAG_TRUSTED; 42 43 import android.annotation.Nullable; 44 import android.content.Context; 45 import android.graphics.Point; 46 import android.hardware.display.IVirtualDisplayCallback; 47 import android.hardware.display.VirtualDisplayConfig; 48 import android.media.projection.IMediaProjection; 49 import android.media.projection.IMediaProjectionCallback; 50 import android.os.Handler; 51 import android.os.IBinder; 52 import android.os.IBinder.DeathRecipient; 53 import android.os.Message; 54 import android.os.RemoteException; 55 import android.os.SystemProperties; 56 import android.util.ArrayMap; 57 import android.util.Slog; 58 import android.view.Display; 59 import android.view.DisplayShape; 60 import android.view.Surface; 61 import android.view.SurfaceControl; 62 63 import com.android.internal.annotations.VisibleForTesting; 64 65 import java.io.PrintWriter; 66 import java.util.Iterator; 67 68 /** 69 * A display adapter that provides virtual displays on behalf of applications. 70 * <p> 71 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. 72 * </p> 73 */ 74 @VisibleForTesting 75 public class VirtualDisplayAdapter extends DisplayAdapter { 76 static final String TAG = "VirtualDisplayAdapter"; 77 static final boolean DEBUG = false; 78 79 // Unique id prefix for virtual displays 80 @VisibleForTesting 81 static final String UNIQUE_ID_PREFIX = "virtual:"; 82 83 private final ArrayMap<IBinder, VirtualDisplayDevice> mVirtualDisplayDevices = 84 new ArrayMap<IBinder, VirtualDisplayDevice>(); 85 private final Handler mHandler; 86 private final SurfaceControlDisplayFactory mSurfaceControlDisplayFactory; 87 88 // Called with SyncRoot lock held. VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, Context context, Handler handler, Listener listener)89 public VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 90 Context context, Handler handler, Listener listener) { 91 this(syncRoot, context, handler, listener, new SurfaceControlDisplayFactory() { 92 @Override 93 public IBinder createDisplay(String name, boolean secure, float requestedRefreshRate) { 94 return DisplayControl.createDisplay(name, secure, requestedRefreshRate); 95 } 96 97 @Override 98 public void destroyDisplay(IBinder displayToken) { 99 DisplayControl.destroyDisplay(displayToken); 100 } 101 }); 102 } 103 104 @VisibleForTesting VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, Context context, Handler handler, Listener listener, SurfaceControlDisplayFactory surfaceControlDisplayFactory)105 VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 106 Context context, Handler handler, Listener listener, 107 SurfaceControlDisplayFactory surfaceControlDisplayFactory) { 108 super(syncRoot, context, handler, listener, TAG); 109 mHandler = handler; 110 mSurfaceControlDisplayFactory = surfaceControlDisplayFactory; 111 } 112 createVirtualDisplayLocked(IVirtualDisplayCallback callback, IMediaProjection projection, int ownerUid, String ownerPackageName, Surface surface, int flags, VirtualDisplayConfig virtualDisplayConfig)113 public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback, 114 IMediaProjection projection, int ownerUid, String ownerPackageName, Surface surface, 115 int flags, VirtualDisplayConfig virtualDisplayConfig) { 116 String name = virtualDisplayConfig.getName(); 117 boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0; 118 IBinder appToken = callback.asBinder(); 119 IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure, 120 virtualDisplayConfig.getRequestedRefreshRate()); 121 final String baseUniqueId = 122 UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ","; 123 final int uniqueIndex = getNextUniqueIndex(baseUniqueId); 124 String uniqueId = virtualDisplayConfig.getUniqueId(); 125 if (uniqueId == null) { 126 uniqueId = baseUniqueId + uniqueIndex; 127 } else { 128 uniqueId = UNIQUE_ID_PREFIX + ownerPackageName + ":" + uniqueId; 129 } 130 MediaProjectionCallback mediaProjectionCallback = null; 131 if (projection != null) { 132 mediaProjectionCallback = new MediaProjectionCallback(appToken); 133 } 134 VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken, 135 ownerUid, ownerPackageName, surface, flags, 136 new Callback(callback, mHandler), projection, mediaProjectionCallback, 137 uniqueId, uniqueIndex, virtualDisplayConfig); 138 139 mVirtualDisplayDevices.put(appToken, device); 140 141 try { 142 if (projection != null) { 143 projection.registerCallback(mediaProjectionCallback); 144 Slog.d(TAG, "Virtual Display: registered media projection callback for new " 145 + "VirtualDisplayDevice"); 146 } 147 appToken.linkToDeath(device, 0); 148 } catch (RemoteException ex) { 149 Slog.e(TAG, "Virtual Display: error while setting up VirtualDisplayDevice", ex); 150 mVirtualDisplayDevices.remove(appToken); 151 device.destroyLocked(false); 152 return null; 153 } 154 155 // Return the display device without actually sending the event indicating 156 // that it was added. The caller will handle it. 157 return device; 158 } 159 resizeVirtualDisplayLocked(IBinder appToken, int width, int height, int densityDpi)160 public void resizeVirtualDisplayLocked(IBinder appToken, 161 int width, int height, int densityDpi) { 162 VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); 163 if (device != null) { 164 Slog.v(TAG, "Resize VirtualDisplay " + device.mName + " to " + width 165 + " " + height); 166 device.resizeLocked(width, height, densityDpi); 167 } 168 } 169 170 @VisibleForTesting getVirtualDisplaySurfaceLocked(IBinder appToken)171 Surface getVirtualDisplaySurfaceLocked(IBinder appToken) { 172 VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); 173 if (device != null) { 174 return device.getSurfaceLocked(); 175 } 176 return null; 177 } 178 setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface)179 public void setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface) { 180 VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); 181 if (device != null) { 182 Slog.v(TAG, "Update surface for VirtualDisplay " + device.mName); 183 device.setSurfaceLocked(surface); 184 } 185 } 186 setDisplayIdToMirror(IBinder appToken, int displayId)187 void setDisplayIdToMirror(IBinder appToken, int displayId) { 188 VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); 189 if (device != null) { 190 device.setDisplayIdToMirror(displayId); 191 } 192 } 193 releaseVirtualDisplayLocked(IBinder appToken)194 public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) { 195 VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken); 196 if (device != null) { 197 Slog.v(TAG, "Release VirtualDisplay " + device.mName); 198 device.destroyLocked(true); 199 appToken.unlinkToDeath(device, 0); 200 } 201 202 // Return the display device that was removed without actually sending the 203 // event indicating that it was removed. The caller will handle it. 204 return device; 205 } 206 setVirtualDisplayStateLocked(IBinder appToken, boolean isOn)207 void setVirtualDisplayStateLocked(IBinder appToken, boolean isOn) { 208 VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); 209 if (device != null) { 210 device.setDisplayState(isOn); 211 } 212 } 213 214 /** 215 * Returns the next unique index for the uniqueIdPrefix 216 */ getNextUniqueIndex(String uniqueIdPrefix)217 private int getNextUniqueIndex(String uniqueIdPrefix) { 218 if (mVirtualDisplayDevices.isEmpty()) { 219 return 0; 220 } 221 222 int nextUniqueIndex = 0; 223 Iterator<VirtualDisplayDevice> it = mVirtualDisplayDevices.values().iterator(); 224 while (it.hasNext()) { 225 VirtualDisplayDevice device = it.next(); 226 if (device.getUniqueId().startsWith(uniqueIdPrefix) 227 && device.mUniqueIndex >= nextUniqueIndex) { 228 // Increment the next unique index to be greater than ones we have already ran 229 // across for displays that have the same unique Id prefix. 230 nextUniqueIndex = device.mUniqueIndex + 1; 231 } 232 } 233 234 return nextUniqueIndex; 235 } 236 handleBinderDiedLocked(IBinder appToken)237 private void handleBinderDiedLocked(IBinder appToken) { 238 mVirtualDisplayDevices.remove(appToken); 239 } 240 handleMediaProjectionStoppedLocked(IBinder appToken)241 private void handleMediaProjectionStoppedLocked(IBinder appToken) { 242 VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); 243 if (device != null) { 244 Slog.i(TAG, "Virtual display device released because media projection stopped: " 245 + device.mName); 246 device.stopLocked(); 247 } 248 } 249 250 private final class VirtualDisplayDevice extends DisplayDevice implements DeathRecipient { 251 private static final int PENDING_SURFACE_CHANGE = 0x01; 252 private static final int PENDING_RESIZE = 0x02; 253 254 private static final float REFRESH_RATE = 60.0f; 255 256 private final IBinder mAppToken; 257 private final int mOwnerUid; 258 final String mOwnerPackageName; 259 final String mName; 260 private final int mFlags; 261 private final Callback mCallback; 262 @Nullable private final IMediaProjection mProjection; 263 @Nullable private final IMediaProjectionCallback mMediaProjectionCallback; 264 265 private int mWidth; 266 private int mHeight; 267 private int mDensityDpi; 268 private float mRequestedRefreshRate; 269 private Surface mSurface; 270 private DisplayDeviceInfo mInfo; 271 private int mDisplayState; 272 private boolean mStopped; 273 private int mPendingChanges; 274 private int mUniqueIndex; 275 private Display.Mode mMode; 276 private boolean mIsDisplayOn; 277 private int mDisplayIdToMirror; 278 private boolean mIsWindowManagerMirroring; 279 VirtualDisplayDevice(IBinder displayToken, IBinder appToken, int ownerUid, String ownerPackageName, Surface surface, int flags, Callback callback, IMediaProjection projection, IMediaProjectionCallback mediaProjectionCallback, String uniqueId, int uniqueIndex, VirtualDisplayConfig virtualDisplayConfig)280 public VirtualDisplayDevice(IBinder displayToken, IBinder appToken, 281 int ownerUid, String ownerPackageName, Surface surface, int flags, 282 Callback callback, IMediaProjection projection, 283 IMediaProjectionCallback mediaProjectionCallback, String uniqueId, int uniqueIndex, 284 VirtualDisplayConfig virtualDisplayConfig) { 285 super(VirtualDisplayAdapter.this, displayToken, uniqueId, getContext()); 286 mAppToken = appToken; 287 mOwnerUid = ownerUid; 288 mOwnerPackageName = ownerPackageName; 289 mName = virtualDisplayConfig.getName(); 290 mWidth = virtualDisplayConfig.getWidth(); 291 mHeight = virtualDisplayConfig.getHeight(); 292 mDensityDpi = virtualDisplayConfig.getDensityDpi(); 293 mRequestedRefreshRate = virtualDisplayConfig.getRequestedRefreshRate(); 294 mMode = createMode(mWidth, mHeight, getRefreshRate()); 295 mSurface = surface; 296 mFlags = flags; 297 mCallback = callback; 298 mProjection = projection; 299 mMediaProjectionCallback = mediaProjectionCallback; 300 mDisplayState = Display.STATE_UNKNOWN; 301 mPendingChanges |= PENDING_SURFACE_CHANGE; 302 mUniqueIndex = uniqueIndex; 303 mIsDisplayOn = surface != null; 304 mDisplayIdToMirror = virtualDisplayConfig.getDisplayIdToMirror(); 305 mIsWindowManagerMirroring = virtualDisplayConfig.isWindowManagerMirroringEnabled(); 306 } 307 308 @Override binderDied()309 public void binderDied() { 310 synchronized (getSyncRoot()) { 311 handleBinderDiedLocked(mAppToken); 312 Slog.i(TAG, "Virtual display device released because application token died: " 313 + mOwnerPackageName); 314 destroyLocked(false); 315 if (mProjection != null && mMediaProjectionCallback != null) { 316 try { 317 mProjection.unregisterCallback(mMediaProjectionCallback); 318 } catch (RemoteException e) { 319 Slog.w(TAG, "Failed to unregister callback in binderDied", e); 320 } 321 } 322 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_REMOVED); 323 } 324 } 325 destroyLocked(boolean binderAlive)326 public void destroyLocked(boolean binderAlive) { 327 if (mSurface != null) { 328 mSurface.release(); 329 mSurface = null; 330 } 331 mSurfaceControlDisplayFactory.destroyDisplay(getDisplayTokenLocked()); 332 if (mProjection != null && mMediaProjectionCallback != null) { 333 try { 334 mProjection.unregisterCallback(mMediaProjectionCallback); 335 } catch (RemoteException e) { 336 Slog.w(TAG, "Failed to unregister callback in destroy", e); 337 } 338 } 339 if (binderAlive) { 340 mCallback.dispatchDisplayStopped(); 341 } 342 } 343 344 @Override getDisplayIdToMirrorLocked()345 public int getDisplayIdToMirrorLocked() { 346 return mDisplayIdToMirror; 347 } 348 setDisplayIdToMirror(int displayIdToMirror)349 void setDisplayIdToMirror(int displayIdToMirror) { 350 if (mDisplayIdToMirror != displayIdToMirror) { 351 mDisplayIdToMirror = displayIdToMirror; 352 mInfo = null; 353 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); 354 sendTraversalRequestLocked(); 355 } 356 } 357 358 @Override isWindowManagerMirroringLocked()359 public boolean isWindowManagerMirroringLocked() { 360 return mIsWindowManagerMirroring; 361 } 362 363 @Override setWindowManagerMirroringLocked(boolean mirroring)364 public void setWindowManagerMirroringLocked(boolean mirroring) { 365 if (mIsWindowManagerMirroring != mirroring) { 366 mIsWindowManagerMirroring = mirroring; 367 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); 368 sendTraversalRequestLocked(); 369 } 370 } 371 372 @Override getDisplaySurfaceDefaultSizeLocked()373 public Point getDisplaySurfaceDefaultSizeLocked() { 374 if (mSurface == null) { 375 return null; 376 } 377 return mSurface.getDefaultSize(); 378 } 379 380 @VisibleForTesting getSurfaceLocked()381 Surface getSurfaceLocked() { 382 return mSurface; 383 } 384 385 @Override hasStableUniqueId()386 public boolean hasStableUniqueId() { 387 return false; 388 } 389 390 @Override requestDisplayStateLocked(int state, float brightnessState, float sdrBrightnessState)391 public Runnable requestDisplayStateLocked(int state, float brightnessState, 392 float sdrBrightnessState) { 393 if (state != mDisplayState) { 394 mDisplayState = state; 395 if (state == Display.STATE_OFF) { 396 mCallback.dispatchDisplayPaused(); 397 } else { 398 mCallback.dispatchDisplayResumed(); 399 } 400 } 401 return null; 402 } 403 404 @Override performTraversalLocked(SurfaceControl.Transaction t)405 public void performTraversalLocked(SurfaceControl.Transaction t) { 406 if ((mPendingChanges & PENDING_RESIZE) != 0) { 407 t.setDisplaySize(getDisplayTokenLocked(), mWidth, mHeight); 408 } 409 if ((mPendingChanges & PENDING_SURFACE_CHANGE) != 0) { 410 setSurfaceLocked(t, mSurface); 411 } 412 mPendingChanges = 0; 413 } 414 setSurfaceLocked(Surface surface)415 public void setSurfaceLocked(Surface surface) { 416 if (!mStopped && mSurface != surface) { 417 if ((mSurface != null) != (surface != null)) { 418 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); 419 } 420 sendTraversalRequestLocked(); 421 mSurface = surface; 422 mInfo = null; 423 mPendingChanges |= PENDING_SURFACE_CHANGE; 424 } 425 } 426 resizeLocked(int width, int height, int densityDpi)427 public void resizeLocked(int width, int height, int densityDpi) { 428 if (mWidth != width || mHeight != height || mDensityDpi != densityDpi) { 429 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); 430 sendTraversalRequestLocked(); 431 mWidth = width; 432 mHeight = height; 433 mMode = createMode(width, height, getRefreshRate()); 434 mDensityDpi = densityDpi; 435 mInfo = null; 436 mPendingChanges |= PENDING_RESIZE; 437 } 438 } 439 setDisplayState(boolean isOn)440 void setDisplayState(boolean isOn) { 441 if (mIsDisplayOn != isOn) { 442 mIsDisplayOn = isOn; 443 mInfo = null; 444 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); 445 } 446 } 447 stopLocked()448 public void stopLocked() { 449 Slog.d(TAG, "Virtual Display: stopping device " + mName); 450 setSurfaceLocked(null); 451 mStopped = true; 452 } 453 454 @Override dumpLocked(PrintWriter pw)455 public void dumpLocked(PrintWriter pw) { 456 super.dumpLocked(pw); 457 pw.println("mFlags=" + mFlags); 458 pw.println("mDisplayState=" + Display.stateToString(mDisplayState)); 459 pw.println("mStopped=" + mStopped); 460 pw.println("mDisplayIdToMirror=" + mDisplayIdToMirror); 461 pw.println("mWindowManagerMirroring=" + mIsWindowManagerMirroring); 462 pw.println("mRequestedRefreshRate=" + mRequestedRefreshRate); 463 } 464 465 @Override getDisplayDeviceInfoLocked()466 public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 467 if (mInfo == null) { 468 mInfo = new DisplayDeviceInfo(); 469 mInfo.name = mName; 470 mInfo.uniqueId = getUniqueId(); 471 mInfo.width = mWidth; 472 mInfo.height = mHeight; 473 mInfo.modeId = mMode.getModeId(); 474 mInfo.renderFrameRate = mMode.getRefreshRate(); 475 mInfo.defaultModeId = mMode.getModeId(); 476 mInfo.supportedModes = new Display.Mode[] { mMode }; 477 mInfo.densityDpi = mDensityDpi; 478 mInfo.xDpi = mDensityDpi; 479 mInfo.yDpi = mDensityDpi; 480 mInfo.presentationDeadlineNanos = 1000000000L / (int) getRefreshRate(); // 1 frame 481 mInfo.flags = 0; 482 if ((mFlags & VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) { 483 mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE 484 | DisplayDeviceInfo.FLAG_NEVER_BLANK; 485 } 486 if ((mFlags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { 487 mInfo.flags &= ~DisplayDeviceInfo.FLAG_NEVER_BLANK; 488 } else { 489 mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; 490 491 if ((mFlags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) { 492 mInfo.flags |= FLAG_OWN_DISPLAY_GROUP; 493 } 494 } 495 if ((mFlags & VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP) != 0) { 496 mInfo.flags |= FLAG_DEVICE_DISPLAY_GROUP; 497 } 498 499 if ((mFlags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { 500 mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; 501 } 502 if ((mFlags & VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) { 503 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION; 504 505 if ((mFlags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { 506 // For demonstration purposes, allow rotation of the external display. 507 // In the future we might allow the user to configure this directly. 508 if ("portrait".equals(SystemProperties.get( 509 "persist.demo.remoterotation"))) { 510 mInfo.rotation = Surface.ROTATION_270; 511 } 512 } 513 } 514 if ((mFlags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 515 mInfo.flags |= DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; 516 } 517 if ((mFlags & VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT) != 0) { 518 mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT; 519 } 520 if ((mFlags & VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL) != 0) { 521 mInfo.flags |= DisplayDeviceInfo.FLAG_DESTROY_CONTENT_ON_REMOVAL; 522 } 523 if ((mFlags & VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) { 524 mInfo.flags |= DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; 525 } 526 if ((mFlags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) { 527 mInfo.flags |= FLAG_TRUSTED; 528 } 529 if ((mFlags & VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED) != 0) { 530 if ((mInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0 531 || (mFlags & VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP) != 0) { 532 mInfo.flags |= FLAG_ALWAYS_UNLOCKED; 533 } else { 534 Slog.w( 535 TAG, 536 "Ignoring VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED as it requires" 537 + " VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP or" 538 + " VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP."); 539 } 540 } 541 if ((mFlags & VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { 542 mInfo.flags |= FLAG_TOUCH_FEEDBACK_DISABLED; 543 } 544 if ((mFlags & VIRTUAL_DISPLAY_FLAG_OWN_FOCUS) != 0) { 545 if ((mFlags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) { 546 mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_FOCUS; 547 } else { 548 Slog.w(TAG, "Ignoring VIRTUAL_DISPLAY_FLAG_OWN_FOCUS as it requires " 549 + "VIRTUAL_DISPLAY_FLAG_TRUSTED."); 550 } 551 } 552 if ((mFlags & VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED) != 0) { 553 if ((mFlags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0 554 && (mFlags & VIRTUAL_DISPLAY_FLAG_OWN_FOCUS) != 0) { 555 mInfo.flags |= FLAG_STEAL_TOP_FOCUS_DISABLED; 556 } else { 557 Slog.w(TAG, 558 "Ignoring VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED as it " 559 + "requires VIRTUAL_DISPLAY_FLAG_OWN_FOCUS which requires " 560 + "VIRTUAL_DISPLAY_FLAG_TRUSTED."); 561 } 562 } 563 564 mInfo.type = Display.TYPE_VIRTUAL; 565 mInfo.touch = ((mFlags & VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH) == 0) ? 566 DisplayDeviceInfo.TOUCH_NONE : DisplayDeviceInfo.TOUCH_VIRTUAL; 567 568 mInfo.state = mIsDisplayOn ? Display.STATE_ON : Display.STATE_OFF; 569 570 mInfo.ownerUid = mOwnerUid; 571 mInfo.ownerPackageName = mOwnerPackageName; 572 573 mInfo.displayShape = 574 DisplayShape.createDefaultDisplayShape(mInfo.width, mInfo.height, false); 575 } 576 return mInfo; 577 } 578 getRefreshRate()579 private float getRefreshRate() { 580 return (mRequestedRefreshRate != 0.0f) ? mRequestedRefreshRate : REFRESH_RATE; 581 } 582 } 583 584 private static class Callback extends Handler { 585 private static final int MSG_ON_DISPLAY_PAUSED = 0; 586 private static final int MSG_ON_DISPLAY_RESUMED = 1; 587 private static final int MSG_ON_DISPLAY_STOPPED = 2; 588 589 private final IVirtualDisplayCallback mCallback; 590 Callback(IVirtualDisplayCallback callback, Handler handler)591 public Callback(IVirtualDisplayCallback callback, Handler handler) { 592 super(handler.getLooper()); 593 mCallback = callback; 594 } 595 596 @Override handleMessage(Message msg)597 public void handleMessage(Message msg) { 598 try { 599 switch (msg.what) { 600 case MSG_ON_DISPLAY_PAUSED: 601 mCallback.onPaused(); 602 break; 603 case MSG_ON_DISPLAY_RESUMED: 604 mCallback.onResumed(); 605 break; 606 case MSG_ON_DISPLAY_STOPPED: 607 mCallback.onStopped(); 608 break; 609 } 610 } catch (RemoteException e) { 611 Slog.w(TAG, "Failed to notify listener of virtual display event.", e); 612 } 613 } 614 dispatchDisplayPaused()615 public void dispatchDisplayPaused() { 616 sendEmptyMessage(MSG_ON_DISPLAY_PAUSED); 617 } 618 dispatchDisplayResumed()619 public void dispatchDisplayResumed() { 620 sendEmptyMessage(MSG_ON_DISPLAY_RESUMED); 621 } 622 dispatchDisplayStopped()623 public void dispatchDisplayStopped() { 624 sendEmptyMessage(MSG_ON_DISPLAY_STOPPED); 625 } 626 } 627 628 private final class MediaProjectionCallback extends IMediaProjectionCallback.Stub { 629 private IBinder mAppToken; MediaProjectionCallback(IBinder appToken)630 public MediaProjectionCallback(IBinder appToken) { 631 mAppToken = appToken; 632 } 633 634 @Override onStop()635 public void onStop() { 636 synchronized (getSyncRoot()) { 637 handleMediaProjectionStoppedLocked(mAppToken); 638 } 639 } 640 641 @Override onCapturedContentResize(int width, int height)642 public void onCapturedContentResize(int width, int height) { 643 // Do nothing when we tell the client that the content is resized - it is up to them 644 // to decide to update the VirtualDisplay and Surface. 645 // We could only update the VirtualDisplay size, anyway (which the client wouldn't 646 // expect), and there will still be letterboxing on the output content since the 647 // Surface and VirtualDisplay would then have different aspect ratios. 648 } 649 650 @Override onCapturedContentVisibilityChanged(boolean isVisible)651 public void onCapturedContentVisibilityChanged(boolean isVisible) { 652 // Do nothing when we tell the client that the content has a visibility change - it is 653 // up to them to decide to pause recording, and update their own UI, depending on their 654 // use case. 655 } 656 } 657 658 @VisibleForTesting 659 public interface SurfaceControlDisplayFactory { 660 /** 661 * Create a virtual display in SurfaceFlinger. 662 * 663 * @param name The name of the display 664 * @param secure Whether this display is secure. 665 * @param requestedRefreshRate 666 * The refresh rate, frames per second, to request on the virtual display. 667 * It should be a divisor of refresh rate of the leader physical display 668 * that drives VSYNC, e.g. 30/60fps on 120fps display. If an arbitrary refresh 669 * rate is specified, SurfaceFlinger rounds up or down to match a divisor of 670 * the refresh rate of the leader physical display. 671 * @return The token reference for the display in SurfaceFlinger. 672 */ createDisplay(String name, boolean secure, float requestedRefreshRate)673 IBinder createDisplay(String name, boolean secure, float requestedRefreshRate); 674 675 /** 676 * Destroy a display in SurfaceFlinger. 677 * 678 * @param displayToken The display token for the display to be destroyed. 679 */ destroyDisplay(IBinder displayToken)680 void destroyDisplay(IBinder displayToken); 681 } 682 } 683