Surface.java revision fa25bf5382467b1018bd9af7f1cb30a23d7d59f7
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 17package android.view; 18 19import android.content.res.CompatibilityInfo.Translator; 20import android.graphics.*; 21import android.os.Parcelable; 22import android.os.Parcel; 23import android.os.SystemProperties; 24import android.util.Log; 25 26/** 27 * Handle onto a raw buffer that is being managed by the screen compositor. 28 */ 29public 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 // The mSurfaceControl will only be present for Surfaces used by the window 221 // server or system processes. When this class is parceled we defer to the 222 // mSurfaceControl to do the parceling. Otherwise we parcel the 223 // mNativeSurface. 224 private int mSurfaceControl; 225 private int mSaveCount; 226 private Canvas mCanvas; 227 private int mNativeSurface; 228 private int mSurfaceGenerationId; 229 private String mName; 230 231 // The Translator for density compatibility mode. This is used for scaling 232 // the canvas to perform the appropriate density transformation. 233 private Translator mCompatibilityTranslator; 234 235 // A matrix to scale the matrix set by application. This is set to null for 236 // non compatibility mode. 237 private Matrix mCompatibleMatrix; 238 239 private Exception mCreationStack; 240 241 242 /* 243 * We use a class initializer to allow the native code to cache some 244 * field offsets. 245 */ 246 native private static void nativeClassInit(); 247 static { nativeClassInit(); } 248 249 /** create a surface @hide */ 250 public Surface(SurfaceSession s, 251 int pid, int display, int w, int h, int format, int flags) 252 throws OutOfResourcesException { 253 checkHeadless(); 254 255 if (DEBUG_RELEASE) { 256 mCreationStack = new Exception(); 257 } 258 mCanvas = new CompatibleCanvas(); 259 init(s,pid,null,display,w,h,format,flags); 260 } 261 262 /** create a surface with a name @hide */ 263 public Surface(SurfaceSession s, 264 int pid, String name, int display, int w, int h, int format, int flags) 265 throws OutOfResourcesException { 266 checkHeadless(); 267 268 if (DEBUG_RELEASE) { 269 mCreationStack = new Exception(); 270 } 271 mCanvas = new CompatibleCanvas(); 272 init(s,pid,name,display,w,h,format,flags); 273 mName = name; 274 } 275 276 /** 277 * Create an empty surface, which will later be filled in by 278 * readFromParcel(). 279 * @hide 280 */ 281 public Surface() { 282 checkHeadless(); 283 284 if (DEBUG_RELEASE) { 285 mCreationStack = new Exception(); 286 } 287 mCanvas = new CompatibleCanvas(); 288 } 289 290 private Surface(Parcel source) throws OutOfResourcesException { 291 init(source); 292 } 293 294 /** 295 * Copy another surface to this one. This surface now holds a reference 296 * to the same data as the original surface, and is -not- the owner. 297 * This is for use by the window manager when returning a window surface 298 * back from a client, converting it from the representation being managed 299 * by the window manager to the representation the client uses to draw 300 * in to it. 301 * @hide 302 */ 303 public native void copyFrom(Surface o); 304 305 /** 306 * Transfer the native state from 'o' to this surface, releasing it 307 * from 'o'. This is for use in the client side for drawing into a 308 * surface; not guaranteed to work on the window manager side. 309 * This is for use by the client to move the underlying surface from 310 * one Surface object to another, in particular in SurfaceFlinger. 311 * @hide. 312 */ 313 public native void transferFrom(Surface o); 314 315 /** @hide */ 316 public int getGenerationId() { 317 return mSurfaceGenerationId; 318 } 319 320 321 /** 322 * Whether the consumer of this Surface is running behind the producer; 323 * that is, isConsumerRunningBehind() returns true if the consumer is more 324 * than one buffer ahead of the producer. 325 * @hide 326 */ 327 public native boolean isConsumerRunningBehind(); 328 329 /** 330 * A Canvas class that can handle the compatibility mode. This does two 331 * things differently. 332 * <ul> 333 * <li>Returns the width and height of the target metrics, rather than 334 * native. For example, the canvas returns 320x480 even if an app is running 335 * in WVGA high density. 336 * <li>Scales the matrix in setMatrix by the application scale, except if 337 * the matrix looks like obtained from getMatrix. This is a hack to handle 338 * the case that an application uses getMatrix to keep the original matrix, 339 * set matrix of its own, then set the original matrix back. There is no 340 * perfect solution that works for all cases, and there are a lot of cases 341 * that this model does not work, but we hope this works for many apps. 342 * </ul> 343 */ 344 private class CompatibleCanvas extends Canvas { 345 // A temp matrix to remember what an application obtained via {@link getMatrix} 346 private Matrix mOrigMatrix = null; 347 348 @Override 349 public int getWidth() { 350 int w = super.getWidth(); 351 if (mCompatibilityTranslator != null) { 352 w = (int)(w * mCompatibilityTranslator.applicationInvertedScale + .5f); 353 } 354 return w; 355 } 356 357 @Override 358 public int getHeight() { 359 int h = super.getHeight(); 360 if (mCompatibilityTranslator != null) { 361 h = (int)(h * mCompatibilityTranslator.applicationInvertedScale + .5f); 362 } 363 return h; 364 } 365 366 @Override 367 public void setMatrix(Matrix matrix) { 368 if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) { 369 // don't scale the matrix if it's not compatibility mode, or 370 // the matrix was obtained from getMatrix. 371 super.setMatrix(matrix); 372 } else { 373 Matrix m = new Matrix(mCompatibleMatrix); 374 m.preConcat(matrix); 375 super.setMatrix(m); 376 } 377 } 378 379 @Override 380 public void getMatrix(Matrix m) { 381 super.getMatrix(m); 382 if (mOrigMatrix == null) { 383 mOrigMatrix = new Matrix(); 384 } 385 mOrigMatrix.set(m); 386 } 387 } 388 389 /** 390 * Sets the translator used to scale canvas's width/height in compatibility 391 * mode. 392 */ 393 void setCompatibilityTranslator(Translator translator) { 394 if (translator != null) { 395 float appScale = translator.applicationScale; 396 mCompatibleMatrix = new Matrix(); 397 mCompatibleMatrix.setScale(appScale, appScale); 398 } 399 } 400 401 /** Free all server-side state associated with this surface and 402 * release this object's reference. @hide */ 403 public native void destroy(); 404 405 private native Canvas lockCanvasNative(Rect dirty); 406 407 /** 408 * set the orientation of the given display. 409 * @param display 410 * @param orientation 411 * @hide 412 */ 413 public static native void setOrientation(int display, int orientation); 414 415 /** 416 * Like {@link #screenshot(int, int, int, int)} but includes all 417 * Surfaces in the screenshot. 418 * 419 * @hide 420 */ 421 public static native Bitmap screenshot(int width, int height); 422 423 /** 424 * Copy the current screen contents into a bitmap and return it. 425 * 426 * @param width The desired width of the returned bitmap; the raw 427 * screen will be scaled down to this size. 428 * @param height The desired height of the returned bitmap; the raw 429 * screen will be scaled down to this size. 430 * @param minLayer The lowest (bottom-most Z order) surface layer to 431 * include in the screenshot. 432 * @param maxLayer The highest (top-most Z order) surface layer to 433 * include in the screenshot. 434 * @return Returns a Bitmap containing the screen contents. 435 * 436 * @hide 437 */ 438 public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer); 439 440 441 /* 442 * set surface parameters. 443 * needs to be inside open/closeTransaction block 444 */ 445 446 /** start a transaction @hide */ 447 public static native void openTransaction(); 448 /** end a transaction @hide */ 449 public static native void closeTransaction(); 450 /** @hide */ 451 public native void setLayer(int zorder); 452 /** @hide */ 453 public void setPosition(int x, int y) { setPosition((float)x, (float)y); } 454 /** @hide */ 455 public native void setPosition(float x, float y); 456 /** @hide */ 457 public native void setSize(int w, int h); 458 /** @hide */ 459 public native void hide(); 460 /** @hide */ 461 public native void show(); 462 /** @hide */ 463 public native void setTransparentRegionHint(Region region); 464 /** @hide */ 465 public native void setAlpha(float alpha); 466 /** @hide */ 467 public native void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy); 468 /** @hide */ 469 public native void setFlags(int flags, int mask); 470 /** @hide */ 471 public native void setWindowCrop(Rect crop); 472 473 474 475 public static final Parcelable.Creator<Surface> CREATOR 476 = new Parcelable.Creator<Surface>() 477 { 478 public Surface createFromParcel(Parcel source) { 479 try { 480 return new Surface(source); 481 } catch (Exception e) { 482 Log.e(LOG_TAG, "Exception creating surface from parcel", e); 483 } 484 return null; 485 } 486 487 public Surface[] newArray(int size) { 488 return new Surface[size]; 489 } 490 }; 491 492 @Override 493 protected void finalize() throws Throwable { 494 try { 495 super.finalize(); 496 } finally { 497 if (mNativeSurface != 0 || mSurfaceControl != 0) { 498 if (DEBUG_RELEASE) { 499 Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" 500 + mNativeSurface + ", " + mSurfaceControl + ")", mCreationStack); 501 } else { 502 Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" 503 + mNativeSurface + ", " + mSurfaceControl + ")"); 504 } 505 } 506 release(); 507 } 508 } 509 510 private native void init(SurfaceSession s, 511 int pid, String name, int display, int w, int h, int format, int flags) 512 throws OutOfResourcesException; 513 514 private native void init(Parcel source); 515 516 private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture); 517 518 private native int getIdentity(); 519} 520