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