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