• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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