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