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