1 /* 2 * Copyright (C) 2007 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 android.content.res.CompatibilityInfo.Translator; 20 import android.graphics.*; 21 import android.os.Parcelable; 22 import android.os.Parcel; 23 import android.os.SystemProperties; 24 import android.util.Log; 25 26 /** 27 * Handle onto a raw buffer that is being managed by the screen compositor. 28 */ 29 public class Surface implements Parcelable { 30 private static final String LOG_TAG = "Surface"; 31 private static final boolean DEBUG_RELEASE = false; 32 33 /* orientations for setOrientation() */ 34 public static final int ROTATION_0 = 0; 35 public static final int ROTATION_90 = 1; 36 public static final int ROTATION_180 = 2; 37 public static final int ROTATION_270 = 3; 38 39 private static final boolean headless = "1".equals( 40 SystemProperties.get("ro.config.headless", "0")); 41 42 private static void checkHeadless() { 43 if(headless) { 44 throw new UnsupportedOperationException("Device is headless"); 45 } 46 } 47 48 /** 49 * Create Surface from a {@link SurfaceTexture}. 50 * 51 * Images drawn to the Surface will be made available to the {@link 52 * SurfaceTexture}, which can attach them an OpenGL ES texture via {@link 53 * SurfaceTexture#updateTexImage}. 54 * 55 * @param surfaceTexture The {@link SurfaceTexture} that is updated by this 56 * Surface. 57 */ 58 public Surface(SurfaceTexture surfaceTexture) { 59 checkHeadless(); 60 61 if (DEBUG_RELEASE) { 62 mCreationStack = new Exception(); 63 } 64 mCanvas = new CompatibleCanvas(); 65 initFromSurfaceTexture(surfaceTexture); 66 } 67 68 /** 69 * Does this object hold a valid surface? Returns true if it holds 70 * a physical surface, so lockCanvas() will succeed. Otherwise 71 * returns false. 72 */ 73 public native boolean isValid(); 74 75 /** Release the local reference to the server-side surface. 76 * Always call release() when you're done with a Surface. This will 77 * make the surface invalid. 78 */ 79 public native void release(); 80 81 /** draw into a surface */ 82 public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException { 83 /* 84 * the dirty rectangle may be expanded to the surface's size, if for 85 * instance it has been resized or if the bits were lost, since the last 86 * call. 87 */ 88 return lockCanvasNative(dirty); 89 } 90 91 /** unlock the surface and asks a page flip */ 92 public native void unlockCanvasAndPost(Canvas canvas); 93 94 /** 95 * unlock the surface. the screen won't be updated until 96 * post() or postAll() is called 97 */ 98 public native void unlockCanvas(Canvas canvas); 99 100 @Override 101 public String toString() { 102 return "Surface(name=" + mName + ", identity=" + getIdentity() + ")"; 103 } 104 105 public int describeContents() { 106 return 0; 107 } 108 109 public native void readFromParcel(Parcel source); 110 public native void writeToParcel(Parcel dest, int flags); 111 112 /** 113 * Exception thrown when a surface couldn't be created or resized 114 */ 115 public static class OutOfResourcesException extends Exception { 116 public OutOfResourcesException() { 117 } 118 public OutOfResourcesException(String name) { 119 super(name); 120 } 121 } 122 123 /* 124 * ----------------------------------------------------------------------- 125 * No user serviceable parts beyond this point 126 * ----------------------------------------------------------------------- 127 */ 128 129 /* flags used in constructor (keep in sync with ISurfaceComposer.h) */ 130 131 /** Surface is created hidden @hide */ 132 public static final int HIDDEN = 0x00000004; 133 134 /** The surface contains secure content, special measures will 135 * be taken to disallow the surface's content to be copied from 136 * another process. In particular, screenshots and VNC servers will 137 * be disabled, but other measures can take place, for instance the 138 * surface might not be hardware accelerated. 139 * @hide*/ 140 public static final int SECURE = 0x00000080; 141 142 /** Creates a surface where color components are interpreted as 143 * "non pre-multiplied" by their alpha channel. Of course this flag is 144 * meaningless for surfaces without an alpha channel. By default 145 * surfaces are pre-multiplied, which means that each color component is 146 * already multiplied by its alpha value. In this case the blending 147 * equation used is: 148 * 149 * DEST = SRC + DEST * (1-SRC_ALPHA) 150 * 151 * By contrast, non pre-multiplied surfaces use the following equation: 152 * 153 * DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA) 154 * 155 * pre-multiplied surfaces must always be used if transparent pixels are 156 * composited on top of each-other into the surface. A pre-multiplied 157 * surface can never lower the value of the alpha component of a given 158 * pixel. 159 * 160 * In some rare situations, a non pre-multiplied surface is preferable. 161 * 162 * @hide 163 */ 164 public static final int NON_PREMULTIPLIED = 0x00000100; 165 166 /** 167 * Indicates that the surface must be considered opaque, even if its 168 * pixel format is set to translucent. This can be useful if an 169 * application needs full RGBA 8888 support for instance but will 170 * still draw every pixel opaque. 171 * 172 * @hide 173 */ 174 public static final int OPAQUE = 0x00000400; 175 176 /** 177 * Application requires a hardware-protected path to an 178 * external display sink. If a hardware-protected path is not available, 179 * then this surface will not be displayed on the external sink. 180 * 181 * @hide 182 */ 183 public static final int PROTECTED_APP = 0x00000800; 184 185 // 0x1000 is reserved for an independent DRM protected flag in framework 186 187 /** Creates a normal surface. This is the default. @hide */ 188 public static final int FX_SURFACE_NORMAL = 0x00000000; 189 190 /** Creates a Blur surface. Everything behind this surface is blurred 191 * by some amount. The quality and refresh speed of the blur effect 192 * is not settable or guaranteed. 193 * It is an error to lock a Blur surface, since it doesn't have 194 * a backing store. 195 * @hide 196 * @deprecated 197 */ 198 @Deprecated 199 public static final int FX_SURFACE_BLUR = 0x00010000; 200 201 /** Creates a Dim surface. Everything behind this surface is dimmed 202 * by the amount specified in {@link #setAlpha}. 203 * It is an error to lock a Dim surface, since it doesn't have 204 * a backing store. 205 * @hide 206 */ 207 public static final int FX_SURFACE_DIM = 0x00020000; 208 209 /** @hide */ 210 public static final int FX_SURFACE_SCREENSHOT = 0x00030000; 211 212 /** Mask used for FX values above @hide */ 213 public static final int FX_SURFACE_MASK = 0x000F0000; 214 215 /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */ 216 217 /** Hide the surface. Equivalent to calling hide(). @hide */ 218 public static final int SURFACE_HIDDEN = 0x01; 219 220 /** Freeze the surface. Equivalent to calling freeze(). @hide */ 221 public static final int SURFACE_FROZEN = 0x02; 222 223 /** Enable dithering when compositing this surface @hide */ 224 public static final int SURFACE_DITHER = 0x04; 225 226 // The mSurfaceControl will only be present for Surfaces used by the window 227 // server or system processes. When this class is parceled we defer to the 228 // mSurfaceControl to do the parceling. Otherwise we parcel the 229 // mNativeSurface. 230 private int mSurfaceControl; 231 private int mSaveCount; 232 private Canvas mCanvas; 233 private int mNativeSurface; 234 private int mSurfaceGenerationId; 235 private String mName; 236 237 // The Translator for density compatibility mode. This is used for scaling 238 // the canvas to perform the appropriate density transformation. 239 private Translator mCompatibilityTranslator; 240 241 // A matrix to scale the matrix set by application. This is set to null for 242 // non compatibility mode. 243 private Matrix mCompatibleMatrix; 244 245 private Exception mCreationStack; 246 247 248 /* 249 * We use a class initializer to allow the native code to cache some 250 * field offsets. 251 */ 252 native private static void nativeClassInit(); 253 static { nativeClassInit(); } 254 255 /** create a surface @hide */ 256 public Surface(SurfaceSession s, 257 int pid, int display, int w, int h, int format, int flags) 258 throws OutOfResourcesException { 259 checkHeadless(); 260 261 if (DEBUG_RELEASE) { 262 mCreationStack = new Exception(); 263 } 264 mCanvas = new CompatibleCanvas(); 265 init(s,pid,null,display,w,h,format,flags); 266 } 267 268 /** create a surface with a name @hide */ 269 public Surface(SurfaceSession s, 270 int pid, String name, int display, int w, int h, int format, int flags) 271 throws OutOfResourcesException { 272 checkHeadless(); 273 274 if (DEBUG_RELEASE) { 275 mCreationStack = new Exception(); 276 } 277 mCanvas = new CompatibleCanvas(); 278 init(s,pid,name,display,w,h,format,flags); 279 mName = name; 280 } 281 282 /** 283 * Create an empty surface, which will later be filled in by 284 * readFromParcel(). 285 * @hide 286 */ 287 public Surface() { 288 checkHeadless(); 289 290 if (DEBUG_RELEASE) { 291 mCreationStack = new Exception(); 292 } 293 mCanvas = new CompatibleCanvas(); 294 } 295 296 private Surface(Parcel source) throws OutOfResourcesException { 297 init(source); 298 } 299 300 /** 301 * Copy another surface to this one. This surface now holds a reference 302 * to the same data as the original surface, and is -not- the owner. 303 * This is for use by the window manager when returning a window surface 304 * back from a client, converting it from the representation being managed 305 * by the window manager to the representation the client uses to draw 306 * in to it. 307 * @hide 308 */ 309 public native void copyFrom(Surface o); 310 311 /** 312 * Transfer the native state from 'o' to this surface, releasing it 313 * from 'o'. This is for use in the client side for drawing into a 314 * surface; not guaranteed to work on the window manager side. 315 * This is for use by the client to move the underlying surface from 316 * one Surface object to another, in particular in SurfaceFlinger. 317 * @hide. 318 */ 319 public native void transferFrom(Surface o); 320 321 /** @hide */ 322 public int getGenerationId() { 323 return mSurfaceGenerationId; 324 } 325 326 327 /** 328 * Whether the consumer of this Surface is running behind the producer; 329 * that is, isConsumerRunningBehind() returns true if the consumer is more 330 * than one buffer ahead of the producer. 331 * @hide 332 */ 333 public native boolean isConsumerRunningBehind(); 334 335 /** 336 * A Canvas class that can handle the compatibility mode. This does two 337 * things differently. 338 * <ul> 339 * <li>Returns the width and height of the target metrics, rather than 340 * native. For example, the canvas returns 320x480 even if an app is running 341 * in WVGA high density. 342 * <li>Scales the matrix in setMatrix by the application scale, except if 343 * the matrix looks like obtained from getMatrix. This is a hack to handle 344 * the case that an application uses getMatrix to keep the original matrix, 345 * set matrix of its own, then set the original matrix back. There is no 346 * perfect solution that works for all cases, and there are a lot of cases 347 * that this model does not work, but we hope this works for many apps. 348 * </ul> 349 */ 350 private class CompatibleCanvas extends Canvas { 351 // A temp matrix to remember what an application obtained via {@link getMatrix} 352 private Matrix mOrigMatrix = null; 353 354 @Override 355 public int getWidth() { 356 int w = super.getWidth(); 357 if (mCompatibilityTranslator != null) { 358 w = (int)(w * mCompatibilityTranslator.applicationInvertedScale + .5f); 359 } 360 return w; 361 } 362 363 @Override 364 public int getHeight() { 365 int h = super.getHeight(); 366 if (mCompatibilityTranslator != null) { 367 h = (int)(h * mCompatibilityTranslator.applicationInvertedScale + .5f); 368 } 369 return h; 370 } 371 372 @Override 373 public void setMatrix(Matrix matrix) { 374 if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) { 375 // don't scale the matrix if it's not compatibility mode, or 376 // the matrix was obtained from getMatrix. 377 super.setMatrix(matrix); 378 } else { 379 Matrix m = new Matrix(mCompatibleMatrix); 380 m.preConcat(matrix); 381 super.setMatrix(m); 382 } 383 } 384 385 @Override 386 public void getMatrix(Matrix m) { 387 super.getMatrix(m); 388 if (mOrigMatrix == null) { 389 mOrigMatrix = new Matrix(); 390 } 391 mOrigMatrix.set(m); 392 } 393 } 394 395 /** 396 * Sets the translator used to scale canvas's width/height in compatibility 397 * mode. 398 */ 399 void setCompatibilityTranslator(Translator translator) { 400 if (translator != null) { 401 float appScale = translator.applicationScale; 402 mCompatibleMatrix = new Matrix(); 403 mCompatibleMatrix.setScale(appScale, appScale); 404 } 405 } 406 407 /** Free all server-side state associated with this surface and 408 * release this object's reference. @hide */ 409 public native void destroy(); 410 411 private native Canvas lockCanvasNative(Rect dirty); 412 413 /* 414 * set display parameters & screenshots 415 */ 416 417 /** 418 * Freezes the specified display, No updating of the screen will occur 419 * until unfreezeDisplay() is called. Everything else works as usual though, 420 * in particular transactions. 421 * @param display 422 * @hide 423 */ 424 public static native void freezeDisplay(int display); 425 426 /** 427 * resume updating the specified display. 428 * @param display 429 * @hide 430 */ 431 public static native void unfreezeDisplay(int display); 432 433 /** 434 * set the orientation of the given display. 435 * @param display 436 * @param orientation 437 * @param flags Currently unused, set to 0. 438 * @hide 439 */ 440 public static native void setOrientation(int display, int orientation, int flags); 441 442 /** 443 * set the orientation of the given display. 444 * @param display 445 * @param orientation 446 * @hide 447 */ 448 public static void setOrientation(int display, int orientation) { 449 setOrientation(display, orientation, 0); 450 } 451 452 /** 453 * Like {@link #screenshot(int, int, int, int)} but includes all 454 * Surfaces in the screenshot. 455 * 456 * @hide 457 */ 458 public static native Bitmap screenshot(int width, int height); 459 460 /** 461 * Copy the current screen contents into a bitmap and return it. 462 * 463 * @param width The desired width of the returned bitmap; the raw 464 * screen will be scaled down to this size. 465 * @param height The desired height of the returned bitmap; the raw 466 * screen will be scaled down to this size. 467 * @param minLayer The lowest (bottom-most Z order) surface layer to 468 * include in the screenshot. 469 * @param maxLayer The highest (top-most Z order) surface layer to 470 * include in the screenshot. 471 * @return Returns a Bitmap containing the screen contents. 472 * 473 * @hide 474 */ 475 public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer); 476 477 478 /* 479 * set surface parameters. 480 * needs to be inside open/closeTransaction block 481 */ 482 483 /** start a transaction @hide */ 484 public static native void openTransaction(); 485 /** end a transaction @hide */ 486 public static native void closeTransaction(); 487 /** @hide */ 488 public native void setLayer(int zorder); 489 /** @hide */ 490 public void setPosition(int x, int y) { setPosition((float)x, (float)y); } 491 /** @hide */ 492 public native void setPosition(float x, float y); 493 /** @hide */ 494 public native void setSize(int w, int h); 495 /** @hide */ 496 public native void hide(); 497 /** @hide */ 498 public native void show(); 499 /** @hide */ 500 public native void setTransparentRegionHint(Region region); 501 /** @hide */ 502 public native void setAlpha(float alpha); 503 /** @hide */ 504 public native void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy); 505 /** @hide */ 506 public native void freeze(); 507 /** @hide */ 508 public native void unfreeze(); 509 /** @hide */ 510 public native void setFreezeTint(int tint); 511 /** @hide */ 512 public native void setFlags(int flags, int mask); 513 /** @hide */ 514 public native void setWindowCrop(Rect crop); 515 516 517 518 public static final Parcelable.Creator<Surface> CREATOR 519 = new Parcelable.Creator<Surface>() 520 { 521 public Surface createFromParcel(Parcel source) { 522 try { 523 return new Surface(source); 524 } catch (Exception e) { 525 Log.e(LOG_TAG, "Exception creating surface from parcel", e); 526 } 527 return null; 528 } 529 530 public Surface[] newArray(int size) { 531 return new Surface[size]; 532 } 533 }; 534 535 @Override 536 protected void finalize() throws Throwable { 537 try { 538 super.finalize(); 539 } finally { 540 if (mNativeSurface != 0 || mSurfaceControl != 0) { 541 if (DEBUG_RELEASE) { 542 Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" 543 + mNativeSurface + ", " + mSurfaceControl + ")", mCreationStack); 544 } else { 545 Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" 546 + mNativeSurface + ", " + mSurfaceControl + ")"); 547 } 548 } 549 release(); 550 } 551 } 552 553 private native void init(SurfaceSession s, 554 int pid, String name, int display, int w, int h, int format, int flags) 555 throws OutOfResourcesException; 556 557 private native void init(Parcel source); 558 559 private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture); 560 561 private native int getIdentity(); 562 } 563