SurfaceControl.java revision 36bef0bf30d6bae48cf3837df351075ca4fce654
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 17package android.view; 18 19import dalvik.system.CloseGuard; 20import android.graphics.Bitmap; 21import android.graphics.Rect; 22import android.graphics.Region; 23import android.view.Surface; 24import android.os.IBinder; 25import android.util.Log; 26import android.view.Surface.OutOfResourcesException; 27 28/** 29 * SurfaceControl 30 * @hide 31 */ 32public class SurfaceControl { 33 private static final String TAG = "SurfaceControl"; 34 35 private static native long nativeCreate(SurfaceSession session, String name, 36 int w, int h, int format, int flags) 37 throws OutOfResourcesException; 38 private static native void nativeRelease(long nativeObject); 39 private static native void nativeDestroy(long nativeObject); 40 41 private static native Bitmap nativeScreenshot(IBinder displayToken, 42 int width, int height, int minLayer, int maxLayer, boolean allLayers); 43 private static native void nativeScreenshot(IBinder displayToken, Surface consumer, 44 int width, int height, int minLayer, int maxLayer, boolean allLayers); 45 46 private static native void nativeOpenTransaction(); 47 private static native void nativeCloseTransaction(); 48 private static native void nativeSetAnimationTransaction(); 49 50 private static native void nativeSetLayer(long nativeObject, int zorder); 51 private static native void nativeSetPosition(long nativeObject, float x, float y); 52 private static native void nativeSetSize(long nativeObject, int w, int h); 53 private static native void nativeSetTransparentRegionHint(long nativeObject, Region region); 54 private static native void nativeSetAlpha(long nativeObject, float alpha); 55 private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx, float dsdy, float dtdy); 56 private static native void nativeSetFlags(long nativeObject, int flags, int mask); 57 private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b); 58 private static native void nativeSetLayerStack(long nativeObject, int layerStack); 59 60 private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId); 61 private static native IBinder nativeCreateDisplay(String name, boolean secure); 62 private static native void nativeDestroyDisplay(IBinder displayToken); 63 private static native void nativeSetDisplaySurface( 64 IBinder displayToken, long nativeSurfaceObject); 65 private static native void nativeSetDisplayLayerStack( 66 IBinder displayToken, int layerStack); 67 private static native void nativeSetDisplayProjection( 68 IBinder displayToken, int orientation, 69 int l, int t, int r, int b, 70 int L, int T, int R, int B); 71 private static native boolean nativeGetDisplayInfo( 72 IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo); 73 private static native void nativeBlankDisplay(IBinder displayToken); 74 private static native void nativeUnblankDisplay(IBinder displayToken); 75 76 77 private final CloseGuard mCloseGuard = CloseGuard.get(); 78 private final String mName; 79 long mNativeObject; // package visibility only for Surface.java access 80 81 /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */ 82 83 /** 84 * Surface creation flag: Surface is created hidden 85 */ 86 public static final int HIDDEN = 0x00000004; 87 88 /** 89 * Surface creation flag: The surface contains secure content, special 90 * measures will be taken to disallow the surface's content to be copied 91 * from another process. In particular, screenshots and VNC servers will 92 * be disabled, but other measures can take place, for instance the 93 * surface might not be hardware accelerated. 94 * 95 */ 96 public static final int SECURE = 0x00000080; 97 98 /** 99 * Surface creation flag: Creates a surface where color components are interpreted 100 * as "non pre-multiplied" by their alpha channel. Of course this flag is 101 * meaningless for surfaces without an alpha channel. By default 102 * surfaces are pre-multiplied, which means that each color component is 103 * already multiplied by its alpha value. In this case the blending 104 * equation used is: 105 * 106 * DEST = SRC + DEST * (1-SRC_ALPHA) 107 * 108 * By contrast, non pre-multiplied surfaces use the following equation: 109 * 110 * DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA) 111 * 112 * pre-multiplied surfaces must always be used if transparent pixels are 113 * composited on top of each-other into the surface. A pre-multiplied 114 * surface can never lower the value of the alpha component of a given 115 * pixel. 116 * 117 * In some rare situations, a non pre-multiplied surface is preferable. 118 * 119 */ 120 public static final int NON_PREMULTIPLIED = 0x00000100; 121 122 /** 123 * Surface creation flag: Indicates that the surface must be considered opaque, 124 * even if its pixel format is set to translucent. This can be useful if an 125 * application needs full RGBA 8888 support for instance but will 126 * still draw every pixel opaque. 127 * 128 */ 129 public static final int OPAQUE = 0x00000400; 130 131 /** 132 * Surface creation flag: Application requires a hardware-protected path to an 133 * external display sink. If a hardware-protected path is not available, 134 * then this surface will not be displayed on the external sink. 135 * 136 */ 137 public static final int PROTECTED_APP = 0x00000800; 138 139 // 0x1000 is reserved for an independent DRM protected flag in framework 140 141 /** 142 * Surface creation flag: Creates a normal surface. 143 * This is the default. 144 * 145 */ 146 public static final int FX_SURFACE_NORMAL = 0x00000000; 147 148 /** 149 * Surface creation flag: Creates a Dim surface. 150 * Everything behind this surface is dimmed by the amount specified 151 * in {@link #setAlpha}. It is an error to lock a Dim surface, since it 152 * doesn't have a backing store. 153 * 154 */ 155 public static final int FX_SURFACE_DIM = 0x00020000; 156 157 /** 158 * Mask used for FX values above. 159 * 160 */ 161 public static final int FX_SURFACE_MASK = 0x000F0000; 162 163 /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */ 164 165 /** 166 * Surface flag: Hide the surface. 167 * Equivalent to calling hide(). 168 */ 169 public static final int SURFACE_HIDDEN = 0x01; 170 171 172 /* built-in physical display ids (keep in sync with ISurfaceComposer.h) 173 * these are different from the logical display ids used elsewhere in the framework */ 174 175 /** 176 * Built-in physical display id: Main display. 177 * Use only with {@link SurfaceControl#getBuiltInDisplay()}. 178 */ 179 public static final int BUILT_IN_DISPLAY_ID_MAIN = 0; 180 181 /** 182 * Built-in physical display id: Attached HDMI display. 183 * Use only with {@link SurfaceControl#getBuiltInDisplay()}. 184 */ 185 public static final int BUILT_IN_DISPLAY_ID_HDMI = 1; 186 187 188 189 /** 190 * Create a surface with a name. 191 * 192 * The surface creation flags specify what kind of surface to create and 193 * certain options such as whether the surface can be assumed to be opaque 194 * and whether it should be initially hidden. Surfaces should always be 195 * created with the {@link #HIDDEN} flag set to ensure that they are not 196 * made visible prematurely before all of the surface's properties have been 197 * configured. 198 * 199 * Good practice is to first create the surface with the {@link #HIDDEN} flag 200 * specified, open a transaction, set the surface layer, layer stack, alpha, 201 * and position, call {@link #show} if appropriate, and close the transaction. 202 * 203 * @param session The surface session, must not be null. 204 * @param name The surface name, must not be null. 205 * @param w The surface initial width. 206 * @param h The surface initial height. 207 * @param flags The surface creation flags. Should always include {@link #HIDDEN} 208 * in the creation flags. 209 * 210 * @throws throws OutOfResourcesException If the SurfaceControl cannot be created. 211 */ 212 public SurfaceControl(SurfaceSession session, 213 String name, int w, int h, int format, int flags) 214 throws OutOfResourcesException { 215 if (session == null) { 216 throw new IllegalArgumentException("session must not be null"); 217 } 218 if (name == null) { 219 throw new IllegalArgumentException("name must not be null"); 220 } 221 222 if ((flags & SurfaceControl.HIDDEN) == 0) { 223 Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set " 224 + "to ensure that they are not made visible prematurely before " 225 + "all of the surface's properties have been configured. " 226 + "Set the other properties and make the surface visible within " 227 + "a transaction. New surface name: " + name, 228 new Throwable()); 229 } 230 231 mName = name; 232 mNativeObject = nativeCreate(session, name, w, h, format, flags); 233 if (mNativeObject == 0) { 234 throw new OutOfResourcesException( 235 "Couldn't allocate SurfaceControl native object"); 236 } 237 238 mCloseGuard.open("release"); 239 } 240 241 @Override 242 protected void finalize() throws Throwable { 243 try { 244 if (mCloseGuard != null) { 245 mCloseGuard.warnIfOpen(); 246 } 247 if (mNativeObject != 0) { 248 nativeRelease(mNativeObject); 249 } 250 } finally { 251 super.finalize(); 252 } 253 } 254 255 @Override 256 public String toString() { 257 return "Surface(name=" + mName + ")"; 258 } 259 260 /** 261 * Release the local reference to the server-side surface. 262 * Always call release() when you're done with a Surface. 263 * This will make the surface invalid. 264 */ 265 public void release() { 266 if (mNativeObject != 0) { 267 nativeRelease(mNativeObject); 268 mNativeObject = 0; 269 } 270 mCloseGuard.close(); 271 } 272 273 /** 274 * Free all server-side state associated with this surface and 275 * release this object's reference. This method can only be 276 * called from the process that created the service. 277 */ 278 public void destroy() { 279 if (mNativeObject != 0) { 280 nativeDestroy(mNativeObject); 281 mNativeObject = 0; 282 } 283 mCloseGuard.close(); 284 } 285 286 private void checkNotReleased() { 287 if (mNativeObject == 0) throw new NullPointerException( 288 "mNativeObject is null. Have you called release() already?"); 289 } 290 291 /* 292 * set surface parameters. 293 * needs to be inside open/closeTransaction block 294 */ 295 296 /** start a transaction */ 297 public static void openTransaction() { 298 nativeOpenTransaction(); 299 } 300 301 /** end a transaction */ 302 public static void closeTransaction() { 303 nativeCloseTransaction(); 304 } 305 306 /** flag the transaction as an animation */ 307 public static void setAnimationTransaction() { 308 nativeSetAnimationTransaction(); 309 } 310 311 public void setLayer(int zorder) { 312 checkNotReleased(); 313 nativeSetLayer(mNativeObject, zorder); 314 } 315 316 public void setPosition(float x, float y) { 317 checkNotReleased(); 318 nativeSetPosition(mNativeObject, x, y); 319 } 320 321 public void setSize(int w, int h) { 322 checkNotReleased(); 323 nativeSetSize(mNativeObject, w, h); 324 } 325 326 public void hide() { 327 checkNotReleased(); 328 nativeSetFlags(mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN); 329 } 330 331 public void show() { 332 checkNotReleased(); 333 nativeSetFlags(mNativeObject, 0, SURFACE_HIDDEN); 334 } 335 336 public void setTransparentRegionHint(Region region) { 337 checkNotReleased(); 338 nativeSetTransparentRegionHint(mNativeObject, region); 339 } 340 341 public void setAlpha(float alpha) { 342 checkNotReleased(); 343 nativeSetAlpha(mNativeObject, alpha); 344 } 345 346 public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { 347 checkNotReleased(); 348 nativeSetMatrix(mNativeObject, dsdx, dtdx, dsdy, dtdy); 349 } 350 351 public void setFlags(int flags, int mask) { 352 checkNotReleased(); 353 nativeSetFlags(mNativeObject, flags, mask); 354 } 355 356 public void setWindowCrop(Rect crop) { 357 checkNotReleased(); 358 if (crop != null) { 359 nativeSetWindowCrop(mNativeObject, 360 crop.left, crop.top, crop.right, crop.bottom); 361 } else { 362 nativeSetWindowCrop(mNativeObject, 0, 0, 0, 0); 363 } 364 } 365 366 public void setLayerStack(int layerStack) { 367 checkNotReleased(); 368 nativeSetLayerStack(mNativeObject, layerStack); 369 } 370 371 /* 372 * set display parameters. 373 * needs to be inside open/closeTransaction block 374 */ 375 376 /** 377 * Describes the properties of a physical display known to surface flinger. 378 */ 379 public static final class PhysicalDisplayInfo { 380 public int width; 381 public int height; 382 public float refreshRate; 383 public float density; 384 public float xDpi; 385 public float yDpi; 386 public boolean secure; 387 388 public PhysicalDisplayInfo() { 389 } 390 391 public PhysicalDisplayInfo(PhysicalDisplayInfo other) { 392 copyFrom(other); 393 } 394 395 @Override 396 public boolean equals(Object o) { 397 return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o); 398 } 399 400 public boolean equals(PhysicalDisplayInfo other) { 401 return other != null 402 && width == other.width 403 && height == other.height 404 && refreshRate == other.refreshRate 405 && density == other.density 406 && xDpi == other.xDpi 407 && yDpi == other.yDpi 408 && secure == other.secure; 409 } 410 411 @Override 412 public int hashCode() { 413 return 0; // don't care 414 } 415 416 public void copyFrom(PhysicalDisplayInfo other) { 417 width = other.width; 418 height = other.height; 419 refreshRate = other.refreshRate; 420 density = other.density; 421 xDpi = other.xDpi; 422 yDpi = other.yDpi; 423 secure = other.secure; 424 } 425 426 // For debugging purposes 427 @Override 428 public String toString() { 429 return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, " 430 + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure 431 + "}"; 432 } 433 } 434 435 public static void unblankDisplay(IBinder displayToken) { 436 if (displayToken == null) { 437 throw new IllegalArgumentException("displayToken must not be null"); 438 } 439 nativeUnblankDisplay(displayToken); 440 } 441 442 public static void blankDisplay(IBinder displayToken) { 443 if (displayToken == null) { 444 throw new IllegalArgumentException("displayToken must not be null"); 445 } 446 nativeBlankDisplay(displayToken); 447 } 448 449 public static boolean getDisplayInfo(IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo) { 450 if (displayToken == null) { 451 throw new IllegalArgumentException("displayToken must not be null"); 452 } 453 if (outInfo == null) { 454 throw new IllegalArgumentException("outInfo must not be null"); 455 } 456 return nativeGetDisplayInfo(displayToken, outInfo); 457 } 458 459 public static void setDisplayProjection(IBinder displayToken, 460 int orientation, Rect layerStackRect, Rect displayRect) { 461 if (displayToken == null) { 462 throw new IllegalArgumentException("displayToken must not be null"); 463 } 464 if (layerStackRect == null) { 465 throw new IllegalArgumentException("layerStackRect must not be null"); 466 } 467 if (displayRect == null) { 468 throw new IllegalArgumentException("displayRect must not be null"); 469 } 470 nativeSetDisplayProjection(displayToken, orientation, 471 layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom, 472 displayRect.left, displayRect.top, displayRect.right, displayRect.bottom); 473 } 474 475 public static void setDisplayLayerStack(IBinder displayToken, int layerStack) { 476 if (displayToken == null) { 477 throw new IllegalArgumentException("displayToken must not be null"); 478 } 479 nativeSetDisplayLayerStack(displayToken, layerStack); 480 } 481 482 public static void setDisplaySurface(IBinder displayToken, Surface surface) { 483 if (displayToken == null) { 484 throw new IllegalArgumentException("displayToken must not be null"); 485 } 486 487 if (surface != null) { 488 synchronized (surface.mLock) { 489 nativeSetDisplaySurface(displayToken, surface.mNativeObject); 490 } 491 } else { 492 nativeSetDisplaySurface(displayToken, 0); 493 } 494 } 495 496 public static IBinder createDisplay(String name, boolean secure) { 497 if (name == null) { 498 throw new IllegalArgumentException("name must not be null"); 499 } 500 return nativeCreateDisplay(name, secure); 501 } 502 503 public static void destroyDisplay(IBinder displayToken) { 504 if (displayToken == null) { 505 throw new IllegalArgumentException("displayToken must not be null"); 506 } 507 nativeDestroyDisplay(displayToken); 508 } 509 510 public static IBinder getBuiltInDisplay(int builtInDisplayId) { 511 return nativeGetBuiltInDisplay(builtInDisplayId); 512 } 513 514 515 /** 516 * Copy the current screen contents into the provided {@link Surface} 517 * 518 * @param display The display to take the screenshot of. 519 * @param consumer The {@link Surface} to take the screenshot into. 520 * @param width The desired width of the returned bitmap; the raw 521 * screen will be scaled down to this size. 522 * @param height The desired height of the returned bitmap; the raw 523 * screen will be scaled down to this size. 524 * @param minLayer The lowest (bottom-most Z order) surface layer to 525 * include in the screenshot. 526 * @param maxLayer The highest (top-most Z order) surface layer to 527 * include in the screenshot. 528 */ 529 public static void screenshot(IBinder display, Surface consumer, 530 int width, int height, int minLayer, int maxLayer) { 531 screenshot(display, consumer, width, height, minLayer, maxLayer, false); 532 } 533 534 /** 535 * Copy the current screen contents into the provided {@link Surface} 536 * 537 * @param display The display to take the screenshot of. 538 * @param consumer The {@link Surface} to take the screenshot into. 539 * @param width The desired width of the returned bitmap; the raw 540 * screen will be scaled down to this size. 541 * @param height The desired height of the returned bitmap; the raw 542 * screen will be scaled down to this size. 543 */ 544 public static void screenshot(IBinder display, Surface consumer, 545 int width, int height) { 546 screenshot(display, consumer, width, height, 0, 0, true); 547 } 548 549 /** 550 * Copy the current screen contents into the provided {@link Surface} 551 * 552 * @param display The display to take the screenshot of. 553 * @param consumer The {@link Surface} to take the screenshot into. 554 */ 555 public static void screenshot(IBinder display, Surface consumer) { 556 screenshot(display, consumer, 0, 0, 0, 0, true); 557 } 558 559 560 /** 561 * Copy the current screen contents into a bitmap and return it. 562 * 563 * CAVEAT: Versions of screenshot that return a {@link Bitmap} can 564 * be extremely slow; avoid use unless absolutely necessary; prefer 565 * the versions that use a {@link Surface} instead, such as 566 * {@link SurfaceControl#screenshot(IBinder, Surface)}. 567 * 568 * @param width The desired width of the returned bitmap; the raw 569 * screen will be scaled down to this size. 570 * @param height The desired height of the returned bitmap; the raw 571 * screen will be scaled down to this size. 572 * @param minLayer The lowest (bottom-most Z order) surface layer to 573 * include in the screenshot. 574 * @param maxLayer The highest (top-most Z order) surface layer to 575 * include in the screenshot. 576 * @return Returns a Bitmap containing the screen contents, or null 577 * if an error occurs. Make sure to call Bitmap.recycle() as soon as 578 * possible, once its content is not needed anymore. 579 */ 580 public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) { 581 // TODO: should take the display as a parameter 582 IBinder displayToken = SurfaceControl.getBuiltInDisplay( 583 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN); 584 return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false); 585 } 586 587 /** 588 * Like {@link SurfaceControl#screenshot(int, int, int, int)} but includes all 589 * Surfaces in the screenshot. 590 * 591 * @param width The desired width of the returned bitmap; the raw 592 * screen will be scaled down to this size. 593 * @param height The desired height of the returned bitmap; the raw 594 * screen will be scaled down to this size. 595 * @return Returns a Bitmap containing the screen contents, or null 596 * if an error occurs. Make sure to call Bitmap.recycle() as soon as 597 * possible, once its content is not needed anymore. 598 */ 599 public static Bitmap screenshot(int width, int height) { 600 // TODO: should take the display as a parameter 601 IBinder displayToken = SurfaceControl.getBuiltInDisplay( 602 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN); 603 return nativeScreenshot(displayToken, width, height, 0, 0, true); 604 } 605 606 private static void screenshot(IBinder display, Surface consumer, 607 int width, int height, int minLayer, int maxLayer, boolean allLayers) { 608 if (display == null) { 609 throw new IllegalArgumentException("displayToken must not be null"); 610 } 611 if (consumer == null) { 612 throw new IllegalArgumentException("consumer must not be null"); 613 } 614 nativeScreenshot(display, consumer, width, height, minLayer, maxLayer, allLayers); 615 } 616} 617