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