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