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 static android.system.OsConstants.EINVAL; 20 21 import android.annotation.FloatRange; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.compat.annotation.UnsupportedAppUsage; 25 import android.content.pm.ActivityInfo; 26 import android.content.res.CompatibilityInfo.Translator; 27 import android.graphics.BLASTBufferQueue; 28 import android.graphics.Canvas; 29 import android.graphics.ColorSpace; 30 import android.graphics.HardwareRenderer; 31 import android.graphics.Matrix; 32 import android.graphics.Point; 33 import android.graphics.RecordingCanvas; 34 import android.graphics.Rect; 35 import android.graphics.RenderNode; 36 import android.graphics.SurfaceTexture; 37 import android.hardware.HardwareBuffer; 38 import android.os.Build; 39 import android.os.Parcel; 40 import android.os.Parcelable; 41 import android.util.Log; 42 import android.view.flags.Flags; 43 44 import dalvik.system.CloseGuard; 45 import dalvik.system.VMRuntime; 46 47 import java.lang.annotation.Retention; 48 import java.lang.annotation.RetentionPolicy; 49 50 /** 51 * Handle onto a raw buffer that is being managed by the screen compositor. 52 * 53 * <p>A Surface is generally created by or from a consumer of image buffers (such as a 54 * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or 55 * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as 56 * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL}, 57 * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or 58 * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw 59 * into.</p> 60 * 61 * <p><strong>Note:</strong> A Surface acts like a 62 * {@link java.lang.ref.WeakReference weak reference} to the consumer it is associated with. By 63 * itself it will not keep its parent consumer from being reclaimed.</p> 64 */ 65 public class Surface implements Parcelable { 66 private static final String TAG = "Surface"; 67 nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)68 private static native long nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture) 69 throws OutOfResourcesException; 70 nativeCreateFromSurfaceControl(long surfaceControlNativeObject)71 private static native long nativeCreateFromSurfaceControl(long surfaceControlNativeObject); nativeGetFromSurfaceControl(long surfaceObject, long surfaceControlNativeObject)72 private static native long nativeGetFromSurfaceControl(long surfaceObject, 73 long surfaceControlNativeObject); nativeGetFromBlastBufferQueue(long surfaceObject, long blastBufferQueueNativeObject)74 private static native long nativeGetFromBlastBufferQueue(long surfaceObject, 75 long blastBufferQueueNativeObject); 76 nativeLockCanvas(long nativeObject, Canvas canvas, Rect dirty)77 private static native long nativeLockCanvas(long nativeObject, Canvas canvas, Rect dirty) 78 throws OutOfResourcesException; nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas)79 private static native void nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas); 80 81 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) nativeRelease(long nativeObject)82 private static native void nativeRelease(long nativeObject); nativeIsValid(long nativeObject)83 private static native boolean nativeIsValid(long nativeObject); nativeIsConsumerRunningBehind(long nativeObject)84 private static native boolean nativeIsConsumerRunningBehind(long nativeObject); nativeReadFromParcel(long nativeObject, Parcel source)85 private static native long nativeReadFromParcel(long nativeObject, Parcel source); nativeWriteToParcel(long nativeObject, Parcel dest)86 private static native void nativeWriteToParcel(long nativeObject, Parcel dest); 87 nativeAllocateBuffers(long nativeObject)88 private static native void nativeAllocateBuffers(long nativeObject); 89 nativeGetWidth(long nativeObject)90 private static native int nativeGetWidth(long nativeObject); nativeGetHeight(long nativeObject)91 private static native int nativeGetHeight(long nativeObject); 92 nativeGetNextFrameNumber(long nativeObject)93 private static native long nativeGetNextFrameNumber(long nativeObject); nativeSetScalingMode(long nativeObject, int scalingMode)94 private static native int nativeSetScalingMode(long nativeObject, int scalingMode); nativeForceScopedDisconnect(long nativeObject)95 private static native int nativeForceScopedDisconnect(long nativeObject); nativeAttachAndQueueBufferWithColorSpace(long nativeObject, HardwareBuffer buffer, int colorSpaceId)96 private static native int nativeAttachAndQueueBufferWithColorSpace(long nativeObject, 97 HardwareBuffer buffer, int colorSpaceId); 98 nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled)99 private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled); nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled)100 private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled); 101 nativeSetFrameRate( long nativeObject, float frameRate, int compatibility, int changeFrameRateStrategy)102 private static native int nativeSetFrameRate( 103 long nativeObject, float frameRate, int compatibility, int changeFrameRateStrategy); nativeDestroy(long nativeObject)104 private static native void nativeDestroy(long nativeObject); 105 106 // 5KB is a balanced guess, since these are still pretty heavyweight objects, but if we make 107 // this too big, it can overwhelm the GC. 108 private static final long SURFACE_NATIVE_ALLOCATION_SIZE_BYTES = 5_000; 109 110 public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR = 111 new Parcelable.Creator<Surface>() { 112 @Override 113 public Surface createFromParcel(Parcel source) { 114 try { 115 Surface s = new Surface(); 116 s.readFromParcel(source); 117 return s; 118 } catch (Exception e) { 119 Log.e(TAG, "Exception creating surface from parcel", e); 120 return null; 121 } 122 } 123 124 @Override 125 public Surface[] newArray(int size) { 126 return new Surface[size]; 127 } 128 }; 129 130 private final CloseGuard mCloseGuard = CloseGuard.get(); 131 132 // Guarded state. 133 @UnsupportedAppUsage 134 final Object mLock = new Object(); // protects the native state 135 @UnsupportedAppUsage 136 private String mName; 137 @UnsupportedAppUsage 138 long mNativeObject; // package scope only for SurfaceControl access 139 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 140 private long mLockedObject; 141 private int mGenerationId; // incremented each time mNativeObject changes 142 private final Canvas mCanvas = new CompatibleCanvas(); 143 144 // A matrix to scale the matrix set by application. This is set to null for 145 // non compatibility mode. 146 private Matrix mCompatibleMatrix; 147 148 private HwuiContext mHwuiContext; 149 150 private boolean mIsSingleBuffered; 151 private boolean mIsSharedBufferModeEnabled; 152 private boolean mIsAutoRefreshEnabled; 153 154 /** @hide */ 155 @Retention(RetentionPolicy.SOURCE) 156 @IntDef(prefix = { "SCALING_MODE_" }, value = { 157 SCALING_MODE_FREEZE, 158 SCALING_MODE_SCALE_TO_WINDOW, 159 SCALING_MODE_SCALE_CROP, 160 SCALING_MODE_NO_SCALE_CROP 161 }) 162 public @interface ScalingMode {} 163 // From system/window.h 164 /** @hide */ 165 public static final int SCALING_MODE_FREEZE = 0; 166 /** @hide */ 167 public static final int SCALING_MODE_SCALE_TO_WINDOW = 1; 168 /** @hide */ 169 public static final int SCALING_MODE_SCALE_CROP = 2; 170 /** @hide */ 171 public static final int SCALING_MODE_NO_SCALE_CROP = 3; 172 173 /** @hide */ 174 @IntDef(prefix = { "ROTATION_" }, value = { 175 ROTATION_0, 176 ROTATION_90, 177 ROTATION_180, 178 ROTATION_270 179 }) 180 @Retention(RetentionPolicy.SOURCE) 181 public @interface Rotation {} 182 183 /** 184 * Rotation constant: 0 degree rotation (natural orientation) 185 */ 186 public static final int ROTATION_0 = 0; 187 188 /** 189 * Rotation constant: 90 degree rotation. 190 */ 191 public static final int ROTATION_90 = 1; 192 193 /** 194 * Rotation constant: 180 degree rotation. 195 */ 196 public static final int ROTATION_180 = 2; 197 198 /** 199 * Rotation constant: 270 degree rotation. 200 */ 201 public static final int ROTATION_270 = 3; 202 203 /** @hide */ 204 @Retention(RetentionPolicy.SOURCE) 205 @IntDef(prefix = {"FRAME_RATE_COMPATIBILITY_"}, 206 value = {FRAME_RATE_COMPATIBILITY_DEFAULT, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE}) 207 public @interface FrameRateCompatibility {} 208 209 // From native_window.h. Keep these in sync. 210 /** 211 * There are no inherent restrictions on the frame rate of this surface. When the 212 * system selects a frame rate other than what the app requested, the app will be able 213 * to run at the system frame rate without requiring pull down. This value should be 214 * used when displaying game content, UIs, and anything that isn't video. 215 */ 216 public static final int FRAME_RATE_COMPATIBILITY_DEFAULT = 0; 217 218 /** 219 * This surface is being used to display content with an inherently fixed frame rate, 220 * e.g. a video that has a specific frame rate. When the system selects a frame rate 221 * other than what the app requested, the app will need to do pull down or use some 222 * other technique to adapt to the system's frame rate. The user experience is likely 223 * to be worse (e.g. more frame stuttering) than it would be if the system had chosen 224 * the app's requested frame rate. This value should be used for video content. 225 */ 226 public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1; 227 228 /** 229 * This surface belongs to an app on the High Refresh Rate Deny list, and needs the display 230 * to operate at the exact frame rate. 231 * 232 * This is used internally by the platform and should not be used by apps. 233 * @hide 234 */ 235 public static final int FRAME_RATE_COMPATIBILITY_EXACT = 100; 236 237 // From window.h. Keep these in sync. 238 /** 239 * This surface is ignored while choosing the refresh rate. 240 * @hide 241 */ 242 public static final int FRAME_RATE_COMPATIBILITY_NO_VOTE = 101; 243 244 // From window.h. Keep these in sync. 245 /** 246 * This surface will vote for the minimum refresh rate. 247 * @hide 248 */ 249 public static final int FRAME_RATE_COMPATIBILITY_MIN = 102; 250 251 // From window.h. Keep these in sync. 252 /** 253 * The surface requests a frame rate that is greater than or equal to {@code frameRate}. 254 * @hide 255 */ 256 public static final int FRAME_RATE_COMPATIBILITY_GTE = 103; 257 258 /** @hide */ 259 @Retention(RetentionPolicy.SOURCE) 260 @IntDef(prefix = {"CHANGE_FRAME_RATE_"}, 261 value = {CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, CHANGE_FRAME_RATE_ALWAYS}) 262 public @interface ChangeFrameRateStrategy {} 263 264 /** 265 * Change the frame rate only if the transition is going to be seamless. 266 */ 267 public static final int CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS = 0; 268 269 /** 270 * Change the frame rate even if the transition is going to be non-seamless, i.e. with visual 271 * interruptions for the user. Non-seamless switches might be used when the benefit of matching 272 * the content's frame rate outweighs the cost of the transition, for example when 273 * displaying long-running video content. 274 */ 275 public static final int CHANGE_FRAME_RATE_ALWAYS = 1; 276 277 /** @hide */ 278 @Retention(RetentionPolicy.SOURCE) 279 @IntDef(prefix = {"FRAME_RATE_CATEGORY_"}, 280 value = {FRAME_RATE_CATEGORY_DEFAULT, FRAME_RATE_CATEGORY_NO_PREFERENCE, 281 FRAME_RATE_CATEGORY_LOW, FRAME_RATE_CATEGORY_NORMAL, 282 FRAME_RATE_CATEGORY_HIGH_HINT, FRAME_RATE_CATEGORY_HIGH}) 283 public @interface FrameRateCategory {} 284 285 // From native_window.h or window.h. Keep these in sync. 286 /** 287 * Default value. This value can also be set to return to default behavior, indicating that this 288 * layer has no data for the frame rate. 289 * @hide 290 */ 291 public static final int FRAME_RATE_CATEGORY_DEFAULT = 0; 292 293 /** 294 * The layer will explicitly not influence the frame rate. 295 * This may indicate a frame rate suitable for no animation updates (such as a cursor blinking 296 * or a sporadic update). 297 * @hide 298 */ 299 public static final int FRAME_RATE_CATEGORY_NO_PREFERENCE = 1; 300 301 /** 302 * Indicates a frame rate suitable for animations that looks fine even if played at a low frame 303 * rate. 304 * @hide 305 */ 306 public static final int FRAME_RATE_CATEGORY_LOW = 2; 307 308 /** 309 * Indicates a middle frame rate suitable for animations that do not require higher frame 310 * rates, or do not benefit from high smoothness. This is normally 60 Hz or close to it. 311 * @hide 312 */ 313 public static final int FRAME_RATE_CATEGORY_NORMAL = 3; 314 315 /** 316 * Hints that, as a result of a user interaction, an animation is likely to start. 317 * This category is a signal that a user interaction heuristic determined the need of a 318 * high refresh rate, and is not an explicit request from the app. 319 * As opposed to {@link #FRAME_RATE_CATEGORY_HIGH}, this vote may be ignored in favor of 320 * more explicit votes. 321 * @hide 322 */ 323 public static final int FRAME_RATE_CATEGORY_HIGH_HINT = 4; 324 325 /** 326 * Indicates a frame rate suitable for animations that require a high frame rate, which may 327 * increase smoothness but may also increase power usage. 328 * @hide 329 */ 330 public static final int FRAME_RATE_CATEGORY_HIGH = 5; 331 332 /** 333 * Create an empty surface, which will later be filled in by readFromParcel(). 334 * @hide 335 */ 336 @UnsupportedAppUsage Surface()337 public Surface() { 338 registerNativeMemoryUsage(); 339 } 340 341 /** 342 * Create a Surface associated with a given {@link SurfaceControl}. Buffers submitted to this 343 * surface will be displayed by the system compositor according to the parameters 344 * specified by the control. Multiple surfaces may be constructed from one SurfaceControl, 345 * but only one can be connected (e.g. have an active EGL context) at a time. 346 * 347 * @param from The SurfaceControl to associate this Surface with 348 */ Surface(@onNull SurfaceControl from)349 public Surface(@NonNull SurfaceControl from) { 350 copyFrom(from); 351 registerNativeMemoryUsage(); 352 } 353 354 /** 355 * Create Surface from a {@link SurfaceTexture}. 356 * 357 * Images drawn to the Surface will be made available to the {@link 358 * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link 359 * SurfaceTexture#updateTexImage}. 360 * 361 * Please note that holding onto the Surface created here is not enough to 362 * keep the provided SurfaceTexture from being reclaimed. In that sense, 363 * the Surface will act like a 364 * {@link java.lang.ref.WeakReference weak reference} to the SurfaceTexture. 365 * 366 * @param surfaceTexture The {@link SurfaceTexture} that is updated by this 367 * Surface. 368 * @throws OutOfResourcesException if the surface could not be created. 369 */ Surface(SurfaceTexture surfaceTexture)370 public Surface(SurfaceTexture surfaceTexture) { 371 if (surfaceTexture == null) { 372 throw new IllegalArgumentException("surfaceTexture must not be null"); 373 } 374 mIsSingleBuffered = surfaceTexture.isSingleBuffered(); 375 synchronized (mLock) { 376 mName = surfaceTexture.toString(); 377 setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture)); 378 } 379 registerNativeMemoryUsage(); 380 } 381 382 /* called from android_view_Surface_createFromIGraphicBufferProducer() */ 383 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Surface(long nativeObject)384 private Surface(long nativeObject) { 385 synchronized (mLock) { 386 setNativeObjectLocked(nativeObject); 387 } 388 registerNativeMemoryUsage(); 389 } 390 391 @Override finalize()392 protected void finalize() throws Throwable { 393 try { 394 if (mCloseGuard != null) { 395 mCloseGuard.warnIfOpen(); 396 } 397 release(); 398 } finally { 399 super.finalize(); 400 freeNativeMemoryUsage(); 401 } 402 } 403 404 /** 405 * Release the local reference to the server-side surface. 406 * Always call release() when you're done with a Surface. 407 * This will make the surface invalid. 408 */ release()409 public void release() { 410 synchronized (mLock) { 411 if (mHwuiContext != null) { 412 mHwuiContext.destroy(); 413 mHwuiContext = null; 414 } 415 if (mNativeObject != 0) { 416 nativeRelease(mNativeObject); 417 setNativeObjectLocked(0); 418 } 419 } 420 } 421 422 /** 423 * Free all server-side state associated with this surface and 424 * release this object's reference. This method can only be 425 * called from the process that created the service. 426 * @hide 427 */ 428 @UnsupportedAppUsage destroy()429 public void destroy() { 430 synchronized (mLock) { 431 if (mNativeObject != 0) { 432 nativeDestroy(mNativeObject); 433 } 434 release(); 435 } 436 } 437 438 /** 439 * Destroys the HwuiContext without completely 440 * releasing the Surface. 441 * @hide 442 */ hwuiDestroy()443 public void hwuiDestroy() { 444 if (mHwuiContext != null) { 445 mHwuiContext.destroy(); 446 mHwuiContext = null; 447 } 448 } 449 450 /** 451 * Returns true if this object holds a valid surface. 452 * 453 * @return True if it holds a physical surface, so lockCanvas() will succeed. 454 * Otherwise returns false. 455 */ isValid()456 public boolean isValid() { 457 synchronized (mLock) { 458 if (mNativeObject == 0) return false; 459 return nativeIsValid(mNativeObject); 460 } 461 } 462 463 /** 464 * Gets the generation number of this surface, incremented each time 465 * the native surface contained within this object changes. 466 * 467 * @return The current generation number. 468 * @hide 469 */ getGenerationId()470 public int getGenerationId() { 471 synchronized (mLock) { 472 return mGenerationId; 473 } 474 } 475 476 /** 477 * Returns the next frame number which will be dequeued for rendering. 478 * Intended for use with SurfaceFlinger's deferred transactions API. 479 * 480 * @hide 481 */ 482 @UnsupportedAppUsage getNextFrameNumber()483 public long getNextFrameNumber() { 484 synchronized (mLock) { 485 checkNotReleasedLocked(); 486 return nativeGetNextFrameNumber(mNativeObject); 487 } 488 } 489 490 /** 491 * Returns true if the consumer of this Surface is running behind the producer. 492 * 493 * @return True if the consumer is more than one buffer ahead of the producer. 494 * @hide 495 */ isConsumerRunningBehind()496 public boolean isConsumerRunningBehind() { 497 synchronized (mLock) { 498 checkNotReleasedLocked(); 499 return nativeIsConsumerRunningBehind(mNativeObject); 500 } 501 } 502 503 /** 504 * Returns the default size of this Surface provided by the consumer of the surface. 505 * Should only be used by the producer of the surface. 506 * 507 * @hide 508 */ 509 @NonNull getDefaultSize()510 public Point getDefaultSize() { 511 synchronized (mLock) { 512 checkNotReleasedLocked(); 513 return new Point(nativeGetWidth(mNativeObject), nativeGetHeight(mNativeObject)); 514 } 515 } 516 517 /** 518 * Gets a {@link Canvas} for drawing into this surface. 519 * 520 * After drawing into the provided {@link Canvas}, the caller must 521 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. 522 * 523 * @param inOutDirty A rectangle that represents the dirty region that the caller wants 524 * to redraw. This function may choose to expand the dirty rectangle if for example 525 * the surface has been resized or if the previous contents of the surface were 526 * not available. The caller must redraw the entire dirty region as represented 527 * by the contents of the inOutDirty rectangle upon return from this function. 528 * The caller may also pass <code>null</code> instead, in the case where the 529 * entire surface should be redrawn. 530 * @return A canvas for drawing into the surface. 531 * 532 * @throws IllegalArgumentException If the inOutDirty rectangle is not valid. 533 * @throws OutOfResourcesException If the canvas cannot be locked. 534 */ lockCanvas(Rect inOutDirty)535 public Canvas lockCanvas(Rect inOutDirty) 536 throws Surface.OutOfResourcesException, IllegalArgumentException { 537 synchronized (mLock) { 538 checkNotReleasedLocked(); 539 if (mLockedObject != 0) { 540 // Ideally, nativeLockCanvas() would throw in this situation and prevent the 541 // double-lock, but that won't happen if mNativeObject was updated. We can't 542 // abandon the old mLockedObject because it might still be in use, so instead 543 // we just refuse to re-lock the Surface. 544 throw new IllegalArgumentException("Surface was already locked"); 545 } 546 mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty); 547 return mCanvas; 548 } 549 } 550 551 /** 552 * Posts the new contents of the {@link Canvas} to the surface and 553 * releases the {@link Canvas}. 554 * 555 * @param canvas The canvas previously obtained from {@link #lockCanvas}. 556 */ unlockCanvasAndPost(Canvas canvas)557 public void unlockCanvasAndPost(Canvas canvas) { 558 synchronized (mLock) { 559 checkNotReleasedLocked(); 560 561 if (mHwuiContext != null) { 562 mHwuiContext.unlockAndPost(canvas); 563 } else { 564 unlockSwCanvasAndPost(canvas); 565 } 566 } 567 } 568 unlockSwCanvasAndPost(Canvas canvas)569 private void unlockSwCanvasAndPost(Canvas canvas) { 570 if (canvas != mCanvas) { 571 throw new IllegalArgumentException("canvas object must be the same instance that " 572 + "was previously returned by lockCanvas"); 573 } 574 if (mNativeObject != mLockedObject) { 575 Log.w(TAG, "WARNING: Surface's mNativeObject (0x" + 576 Long.toHexString(mNativeObject) + ") != mLockedObject (0x" + 577 Long.toHexString(mLockedObject) +")"); 578 } 579 if (mLockedObject == 0) { 580 throw new IllegalStateException("Surface was not locked"); 581 } 582 try { 583 nativeUnlockCanvasAndPost(mLockedObject, canvas); 584 } finally { 585 nativeRelease(mLockedObject); 586 mLockedObject = 0; 587 } 588 } 589 590 /** 591 * Gets a {@link Canvas} for drawing into this surface. 592 * 593 * After drawing into the provided {@link Canvas}, the caller must 594 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. 595 * 596 * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated 597 * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported"> 598 * unsupported drawing operations</a> for a list of what is and isn't 599 * supported in a hardware-accelerated canvas. It is also required to 600 * fully cover the surface every time {@link #lockHardwareCanvas()} is 601 * called as the buffer is not preserved between frames. Partial updates 602 * are not supported. 603 * 604 * @return A canvas for drawing into the surface. 605 * 606 * @throws IllegalStateException If the canvas cannot be locked. 607 */ lockHardwareCanvas()608 public Canvas lockHardwareCanvas() { 609 synchronized (mLock) { 610 checkNotReleasedLocked(); 611 if (mHwuiContext == null) { 612 mHwuiContext = new HwuiContext(false); 613 } 614 return mHwuiContext.lockCanvas( 615 nativeGetWidth(mNativeObject), 616 nativeGetHeight(mNativeObject)); 617 } 618 } 619 620 /** 621 * Gets a {@link Canvas} for drawing into this surface that supports wide color gamut. 622 * 623 * After drawing into the provided {@link Canvas}, the caller must 624 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. 625 * 626 * Unlike {@link #lockCanvas(Rect)} and {@link #lockHardwareCanvas()}, 627 * this will return a hardware-accelerated canvas that supports wide color gamut. 628 * See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported"> 629 * unsupported drawing operations</a> for a list of what is and isn't 630 * supported in a hardware-accelerated canvas. It is also required to 631 * fully cover the surface every time {@link #lockHardwareCanvas()} is 632 * called as the buffer is not preserved between frames. Partial updates 633 * are not supported. 634 * 635 * @return A canvas for drawing into the surface. 636 * 637 * @throws IllegalStateException If the canvas cannot be locked. 638 * 639 * @hide 640 */ lockHardwareWideColorGamutCanvas()641 public Canvas lockHardwareWideColorGamutCanvas() { 642 synchronized (mLock) { 643 checkNotReleasedLocked(); 644 if (mHwuiContext != null && !mHwuiContext.isWideColorGamut()) { 645 mHwuiContext.destroy(); 646 mHwuiContext = null; 647 } 648 if (mHwuiContext == null) { 649 mHwuiContext = new HwuiContext(true); 650 } 651 return mHwuiContext.lockCanvas( 652 nativeGetWidth(mNativeObject), 653 nativeGetHeight(mNativeObject)); 654 } 655 } 656 657 /** 658 * @deprecated This API has been removed and is not supported. Do not use. 659 */ 660 @Deprecated unlockCanvas(Canvas canvas)661 public void unlockCanvas(Canvas canvas) { 662 throw new UnsupportedOperationException(); 663 } 664 665 /** 666 * Sets the translator used to scale canvas's width/height in compatibility 667 * mode. 668 */ setCompatibilityTranslator(Translator translator)669 void setCompatibilityTranslator(Translator translator) { 670 if (translator != null) { 671 float appScale = translator.applicationScale; 672 mCompatibleMatrix = new Matrix(); 673 mCompatibleMatrix.setScale(appScale, appScale); 674 } 675 } 676 updateNativeObject(long newNativeObject)677 private void updateNativeObject(long newNativeObject) { 678 synchronized (mLock) { 679 if (newNativeObject == mNativeObject) { 680 return; 681 } 682 if (mNativeObject != 0) { 683 nativeRelease(mNativeObject); 684 } 685 setNativeObjectLocked(newNativeObject); 686 } 687 } 688 689 /** 690 * Copy another surface to this one. This surface now holds a reference 691 * to the same data as the original surface, and is -not- the owner. 692 * This is for use by the window manager when returning a window surface 693 * back from a client, converting it from the representation being managed 694 * by the window manager to the representation the client uses to draw 695 * in to it. 696 * 697 * @param other {@link SurfaceControl} to copy from. 698 * @hide 699 */ 700 @UnsupportedAppUsage copyFrom(SurfaceControl other)701 public void copyFrom(SurfaceControl other) { 702 if (other == null) { 703 throw new IllegalArgumentException("other must not be null"); 704 } 705 706 long surfaceControlPtr = other.mNativeObject; 707 if (surfaceControlPtr == 0) { 708 throw new NullPointerException( 709 "null SurfaceControl native object. Are you using a released SurfaceControl?"); 710 } 711 long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr); 712 updateNativeObject(newNativeObject); 713 } 714 715 /** 716 * Update the surface if the BLASTBufferQueue IGraphicBufferProducer is different from this 717 * surface's IGraphicBufferProducer. 718 * 719 * @param queue {@link BLASTBufferQueue} to copy from. 720 * @hide 721 */ copyFrom(BLASTBufferQueue queue)722 public void copyFrom(BLASTBufferQueue queue) { 723 if (queue == null) { 724 throw new IllegalArgumentException("queue must not be null"); 725 } 726 727 long blastBufferQueuePtr = queue.mNativeObject; 728 if (blastBufferQueuePtr == 0) { 729 throw new NullPointerException("Null BLASTBufferQueue native object"); 730 } 731 long newNativeObject = nativeGetFromBlastBufferQueue(mNativeObject, blastBufferQueuePtr); 732 updateNativeObject(newNativeObject); 733 } 734 735 /** 736 * Gets a reference a surface created from this one. This surface now holds a reference 737 * to the same data as the original surface, and is -not- the owner. 738 * This is for use by the window manager when returning a window surface 739 * back from a client, converting it from the representation being managed 740 * by the window manager to the representation the client uses to draw 741 * in to it. 742 * 743 * @param other {@link SurfaceControl} to create surface from. 744 * 745 * @hide 746 */ createFrom(SurfaceControl other)747 public void createFrom(SurfaceControl other) { 748 if (other == null) { 749 throw new IllegalArgumentException("other must not be null"); 750 } 751 752 long surfaceControlPtr = other.mNativeObject; 753 if (surfaceControlPtr == 0) { 754 throw new NullPointerException( 755 "null SurfaceControl native object. Are you using a released SurfaceControl?"); 756 } 757 long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr); 758 759 synchronized (mLock) { 760 if (mNativeObject != 0) { 761 nativeRelease(mNativeObject); 762 } 763 setNativeObjectLocked(newNativeObject); 764 } 765 } 766 767 /** 768 * This is intended to be used by {@link SurfaceView#updateWindow} only. 769 * @param other access is not thread safe 770 * @hide 771 * @deprecated 772 */ 773 @Deprecated 774 @UnsupportedAppUsage transferFrom(Surface other)775 public void transferFrom(Surface other) { 776 if (other == null) { 777 throw new IllegalArgumentException("other must not be null"); 778 } 779 if (other != this) { 780 final long newPtr; 781 synchronized (other.mLock) { 782 newPtr = other.mNativeObject; 783 other.setNativeObjectLocked(0); 784 } 785 786 synchronized (mLock) { 787 if (mNativeObject != 0) { 788 nativeRelease(mNativeObject); 789 } 790 setNativeObjectLocked(newPtr); 791 } 792 } 793 } 794 795 @Override describeContents()796 public int describeContents() { 797 return 0; 798 } 799 readFromParcel(Parcel source)800 public void readFromParcel(Parcel source) { 801 if (source == null) { 802 throw new IllegalArgumentException("source must not be null"); 803 } 804 805 synchronized (mLock) { 806 // nativeReadFromParcel() will either return mNativeObject, or 807 // create a new native Surface and return it after reducing 808 // the reference count on mNativeObject. Either way, it is 809 // not necessary to call nativeRelease() here. 810 // NOTE: This must be kept synchronized with the native parceling code 811 // in frameworks/native/libs/Surface.cpp 812 mName = source.readString(); 813 mIsSingleBuffered = source.readInt() != 0; 814 setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source)); 815 } 816 } 817 818 @Override writeToParcel(Parcel dest, int flags)819 public void writeToParcel(Parcel dest, int flags) { 820 if (dest == null) { 821 throw new IllegalArgumentException("dest must not be null"); 822 } 823 synchronized (mLock) { 824 // NOTE: This must be kept synchronized with the native parceling code 825 // in frameworks/native/libs/Surface.cpp 826 dest.writeString(mName); 827 dest.writeInt(mIsSingleBuffered ? 1 : 0); 828 nativeWriteToParcel(mNativeObject, dest); 829 } 830 if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) { 831 release(); 832 } 833 } 834 835 @Override toString()836 public String toString() { 837 synchronized (mLock) { 838 return "Surface(name=" + mName + " mNativeObject=" + mNativeObject + ")/@0x" 839 + Integer.toHexString(System.identityHashCode(this)); 840 } 841 } 842 setNativeObjectLocked(long ptr)843 private void setNativeObjectLocked(long ptr) { 844 if (mNativeObject != ptr) { 845 if (mNativeObject == 0 && ptr != 0) { 846 mCloseGuard.open("Surface.release"); 847 } else if (mNativeObject != 0 && ptr == 0) { 848 mCloseGuard.close(); 849 } 850 mNativeObject = ptr; 851 mGenerationId += 1; 852 if (mHwuiContext != null) { 853 mHwuiContext.updateSurface(); 854 } 855 } 856 } 857 checkNotReleasedLocked()858 private void checkNotReleasedLocked() { 859 if (mNativeObject == 0) { 860 throw new IllegalStateException("Surface has already been released."); 861 } 862 } 863 864 /** 865 * Allocate buffers ahead of time to avoid allocation delays during rendering 866 * @hide 867 */ allocateBuffers()868 public void allocateBuffers() { 869 synchronized (mLock) { 870 checkNotReleasedLocked(); 871 nativeAllocateBuffers(mNativeObject); 872 } 873 } 874 875 /** 876 * Set the scaling mode to be used for this surfaces buffers 877 * @hide 878 */ setScalingMode(@calingMode int scalingMode)879 public void setScalingMode(@ScalingMode int scalingMode) { 880 synchronized (mLock) { 881 checkNotReleasedLocked(); 882 int err = nativeSetScalingMode(mNativeObject, scalingMode); 883 if (err != 0) { 884 throw new IllegalArgumentException("Invalid scaling mode: " + scalingMode); 885 } 886 } 887 } 888 forceScopedDisconnect()889 void forceScopedDisconnect() { 890 synchronized (mLock) { 891 checkNotReleasedLocked(); 892 int err = nativeForceScopedDisconnect(mNativeObject); 893 if (err != 0) { 894 throw new RuntimeException("Failed to disconnect Surface instance (bad object?)"); 895 } 896 } 897 } 898 899 /** 900 * Transfer ownership of buffer with a color space and present it on the Surface. 901 * The supported color spaces are SRGB and Display P3, other color spaces will be 902 * treated as SRGB. 903 * @hide 904 */ attachAndQueueBufferWithColorSpace(HardwareBuffer buffer, ColorSpace colorSpace)905 public void attachAndQueueBufferWithColorSpace(HardwareBuffer buffer, ColorSpace colorSpace) { 906 synchronized (mLock) { 907 checkNotReleasedLocked(); 908 if (colorSpace == null) { 909 colorSpace = ColorSpace.get(ColorSpace.Named.SRGB); 910 } 911 int err = nativeAttachAndQueueBufferWithColorSpace(mNativeObject, buffer, 912 colorSpace.getId()); 913 if (err != 0) { 914 throw new RuntimeException( 915 "Failed to attach and queue buffer to Surface (bad object?), " 916 + "native error: " + err); 917 } 918 } 919 } 920 921 /** 922 * Returns whether or not this Surface is backed by a single-buffered SurfaceTexture 923 * @hide 924 */ isSingleBuffered()925 public boolean isSingleBuffered() { 926 return mIsSingleBuffered; 927 } 928 929 /** 930 * <p>The shared buffer mode allows both the application and the surface compositor 931 * (SurfaceFlinger) to concurrently access this surface's buffer. While the 932 * application is still required to issue a present request 933 * (see {@link #unlockCanvasAndPost(Canvas)}) to the compositor when an update is required, 934 * the compositor may trigger an update at any time. Since the surface's buffer is shared 935 * between the application and the compositor, updates triggered by the compositor may 936 * cause visible tearing.</p> 937 * 938 * <p>The shared buffer mode can be used with 939 * {@link #setAutoRefreshEnabled(boolean) auto-refresh} to avoid the overhead of 940 * issuing present requests.</p> 941 * 942 * <p>If the application uses the shared buffer mode to reduce latency, it is 943 * recommended to use software rendering (see {@link #lockCanvas(Rect)} to ensure 944 * the graphics workloads are not affected by other applications and/or the system 945 * using the GPU. When using software rendering, the application should update the 946 * smallest possible region of the surface required.</p> 947 * 948 * <p class="note">The shared buffer mode might not be supported by the underlying 949 * hardware. Enabling shared buffer mode on hardware that does not support it will 950 * not yield an error but the application will not benefit from lower latency (and 951 * tearing will not be visible).</p> 952 * 953 * <p class="note">Depending on how many and what kind of surfaces are visible, the 954 * surface compositor may need to copy the shared buffer before it is displayed. When 955 * this happens, the latency benefits of shared buffer mode will be reduced.</p> 956 * 957 * @param enabled True to enable the shared buffer mode on this surface, false otherwise 958 * 959 * @see #isSharedBufferModeEnabled() 960 * @see #setAutoRefreshEnabled(boolean) 961 * 962 * @hide 963 */ setSharedBufferModeEnabled(boolean enabled)964 public void setSharedBufferModeEnabled(boolean enabled) { 965 if (mIsSharedBufferModeEnabled != enabled) { 966 int error = nativeSetSharedBufferModeEnabled(mNativeObject, enabled); 967 if (error != 0) { 968 throw new RuntimeException( 969 "Failed to set shared buffer mode on Surface (bad object?)"); 970 } else { 971 mIsSharedBufferModeEnabled = enabled; 972 } 973 } 974 } 975 976 /** 977 * @return True if shared buffer mode is enabled on this surface, false otherwise 978 * 979 * @see #setSharedBufferModeEnabled(boolean) 980 * 981 * @hide 982 */ isSharedBufferModeEnabled()983 public boolean isSharedBufferModeEnabled() { 984 return mIsSharedBufferModeEnabled; 985 } 986 987 /** 988 * <p>When auto-refresh is enabled, the surface compositor (SurfaceFlinger) 989 * automatically updates the display on a regular refresh cycle. The application 990 * can continue to issue present requests but it is not required. Enabling 991 * auto-refresh may result in visible tearing.</p> 992 * 993 * <p>Auto-refresh has no effect if the {@link #setSharedBufferModeEnabled(boolean) 994 * shared buffer mode} is not enabled.</p> 995 * 996 * <p>Because auto-refresh will trigger continuous updates of the display, it is 997 * recommended to turn it on only when necessary. For example, in a drawing/painting 998 * application auto-refresh should be enabled on finger/pen down and disabled on 999 * finger/pen up.</p> 1000 * 1001 * @param enabled True to enable auto-refresh on this surface, false otherwise 1002 * 1003 * @see #isAutoRefreshEnabled() 1004 * @see #setSharedBufferModeEnabled(boolean) 1005 * 1006 * @hide 1007 */ setAutoRefreshEnabled(boolean enabled)1008 public void setAutoRefreshEnabled(boolean enabled) { 1009 if (mIsAutoRefreshEnabled != enabled) { 1010 int error = nativeSetAutoRefreshEnabled(mNativeObject, enabled); 1011 if (error != 0) { 1012 throw new RuntimeException("Failed to set auto refresh on Surface (bad object?)"); 1013 } else { 1014 mIsAutoRefreshEnabled = enabled; 1015 } 1016 } 1017 } 1018 1019 /** 1020 * @return True if auto-refresh is enabled on this surface, false otherwise 1021 * 1022 * @hide 1023 */ isAutoRefreshEnabled()1024 public boolean isAutoRefreshEnabled() { 1025 return mIsAutoRefreshEnabled; 1026 } 1027 1028 /** 1029 * Sets the intended frame rate for this surface. 1030 * 1031 * <p>On devices that are capable of running the display at different refresh rates, 1032 * the system may choose a display refresh rate to better match this surface's frame 1033 * rate. Usage of this API won't introduce frame rate throttling, or affect other 1034 * aspects of the application's frame production pipeline. However, because the system 1035 * may change the display refresh rate, calls to this function may result in changes 1036 * to Choreographer callback timings, and changes to the time interval at which the 1037 * system releases buffers back to the application.</p> 1038 * 1039 * <p>Note that this only has an effect for surfaces presented on the display. If this 1040 * surface is consumed by something other than the system compositor, e.g. a media 1041 * codec, this call has no effect.</p> 1042 * 1043 * @param frameRate The intended frame rate of this surface, in frames per second. 0 1044 * is a special value that indicates the app will accept the system's choice for the 1045 * display frame rate, which is the default behavior if this function isn't 1046 * called. The <code>frameRate</code> parameter does <em>not</em> need to be a valid refresh 1047 * rate for this device's display - e.g., it's fine to pass 30fps to a device that can only run 1048 * the display at 60fps. 1049 * 1050 * @param compatibility The frame rate compatibility of this surface. The 1051 * compatibility value may influence the system's choice of display frame rate. 1052 * This parameter is ignored when <code>frameRate</code> is 0. 1053 * 1054 * @param changeFrameRateStrategy Whether display refresh rate transitions caused by this 1055 * surface should be seamless. A seamless transition is one that doesn't have any visual 1056 * interruptions, such as a black screen for a second or two. This parameter is ignored when 1057 * <code>frameRate</code> is 0. 1058 * 1059 * @throws IllegalArgumentException If <code>frameRate</code>, <code>compatibility</code> or 1060 * <code>changeFrameRateStrategy</code> are invalid. 1061 * 1062 * @see #clearFrameRate() 1063 */ setFrameRate(@loatRangefrom = 0.0) float frameRate, @FrameRateCompatibility int compatibility, @ChangeFrameRateStrategy int changeFrameRateStrategy)1064 public void setFrameRate(@FloatRange(from = 0.0) float frameRate, 1065 @FrameRateCompatibility int compatibility, 1066 @ChangeFrameRateStrategy int changeFrameRateStrategy) { 1067 synchronized (mLock) { 1068 checkNotReleasedLocked(); 1069 int error = nativeSetFrameRate(mNativeObject, frameRate, compatibility, 1070 changeFrameRateStrategy); 1071 if (error == -EINVAL) { 1072 throw new IllegalArgumentException("Invalid argument to Surface.setFrameRate()"); 1073 } else if (error != 0) { 1074 Log.e(TAG, "Failed to set frame rate on Surface. Native error: " + error); 1075 } 1076 } 1077 } 1078 1079 /** 1080 * Clears the frame rate which was set for this surface. 1081 * 1082 * <p>This is equivalent to calling {@link #setFrameRate(float, int, int)} using {@code 0} for 1083 * {@code frameRate}. 1084 * <p>Note that this only has an effect for surfaces presented on the display. If this 1085 * surface is consumed by something other than the system compositor, e.g. a media 1086 * codec, this call has no effect.</p> 1087 * 1088 * @see #setFrameRate(float, int, int) 1089 */ clearFrameRate()1090 public void clearFrameRate() { 1091 synchronized (mLock) { 1092 checkNotReleasedLocked(); 1093 // The values FRAME_RATE_COMPATIBILITY_DEFAULT and CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS 1094 // are ignored because the value of frameRate is 0 1095 int error = nativeSetFrameRate(mNativeObject, 0, 1096 FRAME_RATE_COMPATIBILITY_DEFAULT, CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); 1097 if (error != 0) { 1098 throw new RuntimeException("Failed to clear the frame rate on Surface. Native error" 1099 + ": " + error); 1100 } 1101 } 1102 } 1103 1104 /** 1105 * Sets the intended frame rate for this surface. Any switching of refresh rates is 1106 * most probably going to be seamless. 1107 * 1108 * @see #setFrameRate(float, int, int) 1109 */ setFrameRate( @loatRangefrom = 0.0) float frameRate, @FrameRateCompatibility int compatibility)1110 public void setFrameRate( 1111 @FloatRange(from = 0.0) float frameRate, @FrameRateCompatibility int compatibility) { 1112 setFrameRate(frameRate, compatibility, CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); 1113 } 1114 1115 /** 1116 * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or 1117 * when a SurfaceTexture could not successfully be allocated. 1118 */ 1119 @SuppressWarnings("serial") 1120 public static class OutOfResourcesException extends RuntimeException { OutOfResourcesException()1121 public OutOfResourcesException() { 1122 } OutOfResourcesException(String name)1123 public OutOfResourcesException(String name) { 1124 super(name); 1125 } 1126 } 1127 1128 /** 1129 * Returns a human readable representation of a rotation. 1130 * 1131 * @param rotation The rotation. 1132 * @return The rotation symbolic name. 1133 * 1134 * @hide 1135 */ rotationToString(int rotation)1136 public static String rotationToString(int rotation) { 1137 switch (rotation) { 1138 case Surface.ROTATION_0: { 1139 return "ROTATION_0"; 1140 } 1141 case Surface.ROTATION_90: { 1142 return "ROTATION_90"; 1143 } 1144 case Surface.ROTATION_180: { 1145 return "ROTATION_180"; 1146 } 1147 case Surface.ROTATION_270: { 1148 return "ROTATION_270"; 1149 } 1150 default: { 1151 return Integer.toString(rotation); 1152 } 1153 } 1154 } 1155 1156 /** 1157 * A Canvas class that can handle the compatibility mode. 1158 * This does two things differently. 1159 * <ul> 1160 * <li>Returns the width and height of the target metrics, rather than 1161 * native. For example, the canvas returns 320x480 even if an app is running 1162 * in WVGA high density. 1163 * <li>Scales the matrix in setMatrix by the application scale, except if 1164 * the matrix looks like obtained from getMatrix. This is a hack to handle 1165 * the case that an application uses getMatrix to keep the original matrix, 1166 * set matrix of its own, then set the original matrix back. There is no 1167 * perfect solution that works for all cases, and there are a lot of cases 1168 * that this model does not work, but we hope this works for many apps. 1169 * </ul> 1170 */ 1171 private final class CompatibleCanvas extends Canvas { 1172 // A temp matrix to remember what an application obtained via {@link getMatrix} 1173 private Matrix mOrigMatrix = null; 1174 1175 @Override setMatrix(Matrix matrix)1176 public void setMatrix(Matrix matrix) { 1177 if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) { 1178 // don't scale the matrix if it's not compatibility mode, or 1179 // the matrix was obtained from getMatrix. 1180 super.setMatrix(matrix); 1181 } else { 1182 Matrix m = new Matrix(mCompatibleMatrix); 1183 m.preConcat(matrix); 1184 super.setMatrix(m); 1185 } 1186 } 1187 1188 @SuppressWarnings("deprecation") 1189 @Override getMatrix(Matrix m)1190 public void getMatrix(Matrix m) { 1191 super.getMatrix(m); 1192 if (mOrigMatrix == null) { 1193 mOrigMatrix = new Matrix(); 1194 } 1195 mOrigMatrix.set(m); 1196 } 1197 } 1198 1199 private final class HwuiContext { 1200 private final RenderNode mRenderNode; 1201 private HardwareRenderer mHardwareRenderer; 1202 private RecordingCanvas mCanvas; 1203 private final boolean mIsWideColorGamut; 1204 HwuiContext(boolean isWideColorGamut)1205 HwuiContext(boolean isWideColorGamut) { 1206 mRenderNode = RenderNode.create("HwuiCanvas", null); 1207 mRenderNode.setClipToBounds(false); 1208 mRenderNode.setForceDarkAllowed(false); 1209 mIsWideColorGamut = isWideColorGamut; 1210 1211 mHardwareRenderer = new HardwareRenderer(); 1212 mHardwareRenderer.setContentRoot(mRenderNode); 1213 mHardwareRenderer.setSurface(Surface.this, true); 1214 mHardwareRenderer.setColorMode( 1215 isWideColorGamut 1216 ? ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT 1217 : ActivityInfo.COLOR_MODE_DEFAULT); 1218 mHardwareRenderer.setLightSourceAlpha(0.0f, 0.0f); 1219 mHardwareRenderer.setLightSourceGeometry(0.0f, 0.0f, 0.0f, 0.0f); 1220 } 1221 lockCanvas(int width, int height)1222 Canvas lockCanvas(int width, int height) { 1223 if (mCanvas != null) { 1224 throw new IllegalStateException("Surface was already locked!"); 1225 } 1226 mCanvas = mRenderNode.beginRecording(width, height); 1227 return mCanvas; 1228 } 1229 unlockAndPost(Canvas canvas)1230 void unlockAndPost(Canvas canvas) { 1231 if (canvas != mCanvas) { 1232 throw new IllegalArgumentException("canvas object must be the same instance that " 1233 + "was previously returned by lockCanvas"); 1234 } 1235 mRenderNode.endRecording(); 1236 mCanvas = null; 1237 mHardwareRenderer.createRenderRequest() 1238 .setVsyncTime(System.nanoTime()) 1239 .syncAndDraw(); 1240 } 1241 updateSurface()1242 void updateSurface() { 1243 mHardwareRenderer.setSurface(Surface.this, true); 1244 } 1245 destroy()1246 void destroy() { 1247 mHardwareRenderer.destroy(); 1248 } 1249 isWideColorGamut()1250 boolean isWideColorGamut() { 1251 return mIsWideColorGamut; 1252 } 1253 } 1254 registerNativeMemoryUsage()1255 private static void registerNativeMemoryUsage() { 1256 if (Flags.enableSurfaceNativeAllocRegistrationRo()) { 1257 VMRuntime.getRuntime().registerNativeAllocation(SURFACE_NATIVE_ALLOCATION_SIZE_BYTES); 1258 } 1259 } 1260 freeNativeMemoryUsage()1261 private static void freeNativeMemoryUsage() { 1262 if (Flags.enableSurfaceNativeAllocRegistrationRo()) { 1263 VMRuntime.getRuntime().registerNativeFree(SURFACE_NATIVE_ALLOCATION_SIZE_BYTES); 1264 } 1265 } 1266 } 1267