blob: 13d6dd67bb1951d220c11c9547eebfb6a6767b8f [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package android.view;
18
Steven Thomasdd7bf2f2020-01-31 18:50:02 -080019import static android.system.OsConstants.EINVAL;
20
Steven Thomas6cf051e2020-01-14 11:37:21 -080021import android.annotation.FloatRange;
Tor Norbyed9273d62013-05-30 15:59:53 -070022import android.annotation.IntDef;
Robert Carrda1d2422019-03-07 15:54:37 -080023import android.annotation.NonNull;
Artur Satayevad9254c2019-12-10 17:47:54 +000024import android.compat.annotation.UnsupportedAppUsage;
Mitsuru Oshima240f8a72009-07-22 20:39:14 -070025import android.content.res.CompatibilityInfo.Translator;
Jeff Brown0b722fe2012-08-24 22:40:14 -070026import android.graphics.Canvas;
Peiyong Linccc06b62019-06-25 17:31:09 -070027import android.graphics.ColorSpace;
Robert Carra35e5de2017-03-03 17:04:54 -080028import android.graphics.GraphicBuffer;
Derek Sollenberger4aa30d02019-08-30 13:53:29 -040029import android.graphics.HardwareRenderer;
Jeff Brown0b722fe2012-08-24 22:40:14 -070030import android.graphics.Matrix;
John Reck32f140aa62018-10-04 15:08:24 -070031import android.graphics.RecordingCanvas;
Jeff Brown0b722fe2012-08-24 22:40:14 -070032import android.graphics.Rect;
John Reck32f140aa62018-10-04 15:08:24 -070033import android.graphics.RenderNode;
Jeff Brown0b722fe2012-08-24 22:40:14 -070034import android.graphics.SurfaceTexture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.os.Parcel;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080036import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.util.Log;
Tor Norbyed9273d62013-05-30 15:59:53 -070038
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070039import dalvik.system.CloseGuard;
40
Tor Norbyed9273d62013-05-30 15:59:53 -070041import java.lang.annotation.Retention;
42import java.lang.annotation.RetentionPolicy;
43
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044/**
Glenn Kasten334031c2010-11-09 21:54:38 -080045 * Handle onto a raw buffer that is being managed by the screen compositor.
Eino-Ville Talvalac4faf0c2016-09-16 13:34:52 -070046 *
47 * <p>A Surface is generally created by or from a consumer of image buffers (such as a
48 * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or
49 * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as
50 * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL},
51 * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or
52 * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw
53 * into.</p>
54 *
55 * <p><strong>Note:</strong> A Surface acts like a
56 * {@link java.lang.ref.WeakReference weak reference} to the consumer it is associated with. By
57 * itself it will not keep its parent consumer from being reclaimed.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 */
59public class Surface implements Parcelable {
Jeff Brown64a55af2012-08-26 02:47:39 -070060 private static final String TAG = "Surface";
Mathias Agopianb9230662011-08-03 14:44:48 -070061
Ashok Bhat36bef0b2014-01-20 20:08:01 +000062 private static native long nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
Mathias Agopian29479eb2013-02-14 14:36:04 -080063 throws OutOfResourcesException;
Bryce Lee02949f12017-06-16 07:20:34 -070064
Ashok Bhat36bef0b2014-01-20 20:08:01 +000065 private static native long nativeCreateFromSurfaceControl(long surfaceControlNativeObject);
Robert Carrd5686722019-01-25 14:30:52 -080066 private static native long nativeGetFromSurfaceControl(long surfaceObject,
67 long surfaceControlNativeObject);
Mathias Agopian52800612013-02-14 17:11:20 -080068
Ashok Bhat36bef0b2014-01-20 20:08:01 +000069 private static native long nativeLockCanvas(long nativeObject, Canvas canvas, Rect dirty)
Jeff Brownfc0ebd72013-04-30 16:33:00 -070070 throws OutOfResourcesException;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000071 private static native void nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas);
Mathias Agopian29479eb2013-02-14 14:36:04 -080072
Mathew Inwooda570dee2018-08-17 14:56:00 +010073 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +000074 private static native void nativeRelease(long nativeObject);
75 private static native boolean nativeIsValid(long nativeObject);
76 private static native boolean nativeIsConsumerRunningBehind(long nativeObject);
77 private static native long nativeReadFromParcel(long nativeObject, Parcel source);
78 private static native void nativeWriteToParcel(long nativeObject, Parcel dest);
Mathias Agopian29479eb2013-02-14 14:36:04 -080079
Dan Stoza5795d642014-06-20 13:01:36 -070080 private static native void nativeAllocateBuffers(long nativeObject);
81
John Reckb35c9602014-11-13 16:15:08 -080082 private static native int nativeGetWidth(long nativeObject);
83 private static native int nativeGetHeight(long nativeObject);
84
Rob Carr64e516f2015-10-29 00:20:45 +000085 private static native long nativeGetNextFrameNumber(long nativeObject);
Robert Carrcd9a18c2015-12-16 18:16:21 -080086 private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
Robert Carr387838b2016-09-07 14:12:44 -070087 private static native int nativeForceScopedDisconnect(long nativeObject);
Peiyong Linccc06b62019-06-25 17:31:09 -070088 private static native int nativeAttachAndQueueBufferWithColorSpace(long nativeObject,
89 GraphicBuffer buffer, int colorSpaceId);
Rob Carr64e516f2015-10-29 00:20:45 +000090
Romain Guy0bbf0b42017-07-20 08:57:07 -070091 private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled);
92 private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
93
Steven Thomasdd7bf2f2020-01-31 18:50:02 -080094 private static native int nativeSetFrameRate(
95 long nativeObject, float frameRate, int compatibility);
Steven Thomas6cf051e2020-01-14 11:37:21 -080096
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -070097 public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR =
Jeff Brown64a55af2012-08-26 02:47:39 -070098 new Parcelable.Creator<Surface>() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -070099 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -0700100 public Surface createFromParcel(Parcel source) {
101 try {
102 Surface s = new Surface();
103 s.readFromParcel(source);
104 return s;
105 } catch (Exception e) {
106 Log.e(TAG, "Exception creating surface from parcel", e);
107 return null;
108 }
Kevin Hesterb85c9332012-03-08 17:06:56 -0800109 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700110
111 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -0700112 public Surface[] newArray(int size) {
113 return new Surface[size];
114 }
115 };
Kevin Hesterb85c9332012-03-08 17:06:56 -0800116
Jeff Brown64a55af2012-08-26 02:47:39 -0700117 private final CloseGuard mCloseGuard = CloseGuard.get();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700118
119 // Guarded state.
Mathew Inwooda570dee2018-08-17 14:56:00 +0100120 @UnsupportedAppUsage
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700121 final Object mLock = new Object(); // protects the native state
Mathew Inwooda570dee2018-08-17 14:56:00 +0100122 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700123 private String mName;
Mathew Inwooda570dee2018-08-17 14:56:00 +0100124 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000125 long mNativeObject; // package scope only for SurfaceControl access
Mathew Inwooda570dee2018-08-17 14:56:00 +0100126 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000127 private long mLockedObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700128 private int mGenerationId; // incremented each time mNativeObject changes
Jeff Brown64a55af2012-08-26 02:47:39 -0700129 private final Canvas mCanvas = new CompatibleCanvas();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700131 // A matrix to scale the matrix set by application. This is set to null for
132 // non compatibility mode.
133 private Matrix mCompatibleMatrix;
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700134
John Reckbb2d0cc2014-10-21 10:09:36 -0700135 private HwuiContext mHwuiContext;
136
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700137 private boolean mIsSingleBuffered;
Romain Guy0bbf0b42017-07-20 08:57:07 -0700138 private boolean mIsSharedBufferModeEnabled;
139 private boolean mIsAutoRefreshEnabled;
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700140
Tor Norbyed9273d62013-05-30 15:59:53 -0700141 /** @hide */
Robert Carrcd9a18c2015-12-16 18:16:21 -0800142 @Retention(RetentionPolicy.SOURCE)
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700143 @IntDef(prefix = { "SCALING_MODE_" }, value = {
144 SCALING_MODE_FREEZE,
145 SCALING_MODE_SCALE_TO_WINDOW,
146 SCALING_MODE_SCALE_CROP,
147 SCALING_MODE_NO_SCALE_CROP
148 })
Robert Carrcd9a18c2015-12-16 18:16:21 -0800149 public @interface ScalingMode {}
150 // From system/window.h
151 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700152 public static final int SCALING_MODE_FREEZE = 0;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800153 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700154 public static final int SCALING_MODE_SCALE_TO_WINDOW = 1;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800155 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700156 public static final int SCALING_MODE_SCALE_CROP = 2;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800157 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700158 public static final int SCALING_MODE_NO_SCALE_CROP = 3;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800159
160 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700161 @IntDef(prefix = { "ROTATION_" }, value = {
162 ROTATION_0,
163 ROTATION_90,
164 ROTATION_180,
165 ROTATION_270
166 })
Tor Norbyed9273d62013-05-30 15:59:53 -0700167 @Retention(RetentionPolicy.SOURCE)
168 public @interface Rotation {}
169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 /**
Mathias Agopian29479eb2013-02-14 14:36:04 -0800171 * Rotation constant: 0 degree rotation (natural orientation)
172 */
173 public static final int ROTATION_0 = 0;
174
175 /**
176 * Rotation constant: 90 degree rotation.
177 */
178 public static final int ROTATION_90 = 1;
179
180 /**
181 * Rotation constant: 180 degree rotation.
182 */
183 public static final int ROTATION_180 = 2;
184
185 /**
186 * Rotation constant: 270 degree rotation.
187 */
188 public static final int ROTATION_270 = 3;
189
Steven Thomasdd7bf2f2020-01-31 18:50:02 -0800190 /** @hide */
191 @Retention(RetentionPolicy.SOURCE)
192 @IntDef(prefix = {"FRAME_RATE_COMPATIBILITY_"},
193 value = {FRAME_RATE_COMPATIBILITY_DEFAULT, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE})
194 public @interface FrameRateCompatibility {}
195
196 // From native_window.h. Keep these in sync.
197 /**
198 * There are no inherent restrictions on the frame rate of this surface.
199 */
200 public static final int FRAME_RATE_COMPATIBILITY_DEFAULT = 0;
201
202 /**
203 * This surface is being used to display content with an inherently fixed frame rate,
204 * e.g. a video that has a specific frame rate. When the system selects a frame rate
205 * other than what the app requested, the app will need to do pull down or use some
206 * other technique to adapt to the system's frame rate. The user experience is likely
207 * to be worse (e.g. more frame stuttering) than it would be if the system had chosen
208 * the app's requested frame rate.
209 */
210 public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1;
211
Mathias Agopian29479eb2013-02-14 14:36:04 -0800212 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700213 * Create an empty surface, which will later be filled in by readFromParcel().
Mathias Agopianb9230662011-08-03 14:44:48 -0700214 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100216 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 public Surface() {
Jeff Brown64a55af2012-08-26 02:47:39 -0700218 }
219
220 /**
Robert Carr76907ee2019-01-11 13:38:19 -0800221 * Create a Surface assosciated with a given {@link SurfaceControl}. Buffers submitted to this
222 * surface will be displayed by the system compositor according to the parameters
223 * specified by the control. Multiple surfaces may be constructed from one SurfaceControl,
224 * but only one can be connected (e.g. have an active EGL context) at a time.
225 *
226 * @param from The SurfaceControl to assosciate this Surface with
227 */
Robert Carrda1d2422019-03-07 15:54:37 -0800228 public Surface(@NonNull SurfaceControl from) {
Robert Carr76907ee2019-01-11 13:38:19 -0800229 copyFrom(from);
230 }
231
232 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700233 * Create Surface from a {@link SurfaceTexture}.
234 *
235 * Images drawn to the Surface will be made available to the {@link
236 * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
237 * SurfaceTexture#updateTexImage}.
238 *
Eino-Ville Talvalaec99efa2017-11-29 15:35:42 -0800239 * Please note that holding onto the Surface created here is not enough to
240 * keep the provided SurfaceTexture from being reclaimed. In that sense,
241 * the Surface will act like a
242 * {@link java.lang.ref.WeakReference weak reference} to the SurfaceTexture.
243 *
Jeff Brown64a55af2012-08-26 02:47:39 -0700244 * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
245 * Surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700246 * @throws OutOfResourcesException if the surface could not be created.
Jeff Brown64a55af2012-08-26 02:47:39 -0700247 */
248 public Surface(SurfaceTexture surfaceTexture) {
249 if (surfaceTexture == null) {
250 throw new IllegalArgumentException("surfaceTexture must not be null");
251 }
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700252 mIsSingleBuffered = surfaceTexture.isSingleBuffered();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700253 synchronized (mLock) {
254 mName = surfaceTexture.toString();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700255 setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
Jeff Brown64a55af2012-08-26 02:47:39 -0700256 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700257 }
258
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700259 /* called from android_view_Surface_createFromIGraphicBufferProducer() */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100260 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000261 private Surface(long nativeObject) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700262 synchronized (mLock) {
263 setNativeObjectLocked(nativeObject);
264 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800265 }
266
Jeff Brown64a55af2012-08-26 02:47:39 -0700267 @Override
268 protected void finalize() throws Throwable {
269 try {
270 if (mCloseGuard != null) {
271 mCloseGuard.warnIfOpen();
272 }
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700273 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700274 } finally {
275 super.finalize();
276 }
277 }
278
279 /**
280 * Release the local reference to the server-side surface.
281 * Always call release() when you're done with a Surface.
282 * This will make the surface invalid.
283 */
284 public void release() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700285 synchronized (mLock) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700286 if (mHwuiContext != null) {
287 mHwuiContext.destroy();
288 mHwuiContext = null;
289 }
Steven Thomas408dc962020-02-07 15:30:10 -0800290 if (mNativeObject != 0) {
291 nativeRelease(mNativeObject);
292 setNativeObjectLocked(0);
293 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800294 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700295 }
296
297 /**
298 * Free all server-side state associated with this surface and
299 * release this object's reference. This method can only be
300 * called from the process that created the service.
301 * @hide
302 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100303 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700304 public void destroy() {
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700305 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700306 }
307
308 /**
Lucas Dupin41c25ce2018-03-27 09:50:19 -0700309 * Destroys the HwuiContext without completely
310 * releasing the Surface.
311 * @hide
312 */
313 public void hwuiDestroy() {
314 if (mHwuiContext != null) {
315 mHwuiContext.destroy();
316 mHwuiContext = null;
317 }
318 }
319
320 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700321 * Returns true if this object holds a valid surface.
322 *
323 * @return True if it holds a physical surface, so lockCanvas() will succeed.
324 * Otherwise returns false.
325 */
326 public boolean isValid() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700327 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700328 if (mNativeObject == 0) return false;
329 return nativeIsValid(mNativeObject);
330 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700331 }
332
333 /**
334 * Gets the generation number of this surface, incremented each time
335 * the native surface contained within this object changes.
336 *
337 * @return The current generation number.
338 * @hide
339 */
340 public int getGenerationId() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700341 synchronized (mLock) {
342 return mGenerationId;
343 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700344 }
345
346 /**
Rob Carr64e516f2015-10-29 00:20:45 +0000347 * Returns the next frame number which will be dequeued for rendering.
348 * Intended for use with SurfaceFlinger's deferred transactions API.
349 *
350 * @hide
351 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100352 @UnsupportedAppUsage
Rob Carr64e516f2015-10-29 00:20:45 +0000353 public long getNextFrameNumber() {
354 synchronized (mLock) {
Jorim Jaggi388090f2018-01-22 17:03:59 +0100355 checkNotReleasedLocked();
Rob Carr64e516f2015-10-29 00:20:45 +0000356 return nativeGetNextFrameNumber(mNativeObject);
357 }
358 }
359
360 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700361 * Returns true if the consumer of this Surface is running behind the producer.
362 *
363 * @return True if the consumer is more than one buffer ahead of the producer.
364 * @hide
365 */
366 public boolean isConsumerRunningBehind() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700367 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700368 checkNotReleasedLocked();
369 return nativeIsConsumerRunningBehind(mNativeObject);
370 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700371 }
372
373 /**
374 * Gets a {@link Canvas} for drawing into this surface.
375 *
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700376 * After drawing into the provided {@link Canvas}, the caller must
Jeff Brown64a55af2012-08-26 02:47:39 -0700377 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
378 *
Mathias Agopian30d7ab92013-02-14 15:38:40 -0800379 * @param inOutDirty A rectangle that represents the dirty region that the caller wants
Jeff Brown64a55af2012-08-26 02:47:39 -0700380 * to redraw. This function may choose to expand the dirty rectangle if for example
381 * the surface has been resized or if the previous contents of the surface were
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700382 * not available. The caller must redraw the entire dirty region as represented
383 * by the contents of the inOutDirty rectangle upon return from this function.
Jeff Brown64a55af2012-08-26 02:47:39 -0700384 * The caller may also pass <code>null</code> instead, in the case where the
385 * entire surface should be redrawn.
386 * @return A canvas for drawing into the surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700387 *
388 * @throws IllegalArgumentException If the inOutDirty rectangle is not valid.
389 * @throws OutOfResourcesException If the canvas cannot be locked.
Jeff Brown64a55af2012-08-26 02:47:39 -0700390 */
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800391 public Canvas lockCanvas(Rect inOutDirty)
Igor Murashkina86ab6402013-08-30 12:58:36 -0700392 throws Surface.OutOfResourcesException, IllegalArgumentException {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700393 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700394 checkNotReleasedLocked();
Andy McFaddened55c8d2013-08-20 10:05:51 -0700395 if (mLockedObject != 0) {
396 // Ideally, nativeLockCanvas() would throw in this situation and prevent the
397 // double-lock, but that won't happen if mNativeObject was updated. We can't
398 // abandon the old mLockedObject because it might still be in use, so instead
399 // we just refuse to re-lock the Surface.
Jesse Halld7e55962014-10-13 11:01:15 -0700400 throw new IllegalArgumentException("Surface was already locked");
Andy McFaddened55c8d2013-08-20 10:05:51 -0700401 }
402 mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700403 return mCanvas;
Mathias Agopian7c116b52013-03-18 20:27:02 -0700404 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700405 }
406
407 /**
408 * Posts the new contents of the {@link Canvas} to the surface and
409 * releases the {@link Canvas}.
410 *
411 * @param canvas The canvas previously obtained from {@link #lockCanvas}.
412 */
413 public void unlockCanvasAndPost(Canvas canvas) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700414 synchronized (mLock) {
415 checkNotReleasedLocked();
416
417 if (mHwuiContext != null) {
418 mHwuiContext.unlockAndPost(canvas);
419 } else {
420 unlockSwCanvasAndPost(canvas);
421 }
422 }
423 }
424
425 private void unlockSwCanvasAndPost(Canvas canvas) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700426 if (canvas != mCanvas) {
427 throw new IllegalArgumentException("canvas object must be the same instance that "
428 + "was previously returned by lockCanvas");
429 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700430 if (mNativeObject != mLockedObject) {
431 Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
432 Long.toHexString(mNativeObject) + ") != mLockedObject (0x" +
433 Long.toHexString(mLockedObject) +")");
434 }
435 if (mLockedObject == 0) {
436 throw new IllegalStateException("Surface was not locked");
437 }
438 try {
439 nativeUnlockCanvasAndPost(mLockedObject, canvas);
440 } finally {
441 nativeRelease(mLockedObject);
442 mLockedObject = 0;
443 }
444 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700445
John Reckbb2d0cc2014-10-21 10:09:36 -0700446 /**
447 * Gets a {@link Canvas} for drawing into this surface.
448 *
449 * After drawing into the provided {@link Canvas}, the caller must
450 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
451 *
452 * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated
453 * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
454 * unsupported drawing operations</a> for a list of what is and isn't
John Reck43a53282014-10-23 13:56:03 -0700455 * supported in a hardware-accelerated canvas. It is also required to
456 * fully cover the surface every time {@link #lockHardwareCanvas()} is
457 * called as the buffer is not preserved between frames. Partial updates
458 * are not supported.
John Reckbb2d0cc2014-10-21 10:09:36 -0700459 *
460 * @return A canvas for drawing into the surface.
461 *
462 * @throws IllegalStateException If the canvas cannot be locked.
463 */
464 public Canvas lockHardwareCanvas() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700465 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700466 checkNotReleasedLocked();
John Reckbb2d0cc2014-10-21 10:09:36 -0700467 if (mHwuiContext == null) {
Peiyong Lind8b68712018-03-06 18:34:21 -0800468 mHwuiContext = new HwuiContext(false);
469 }
470 return mHwuiContext.lockCanvas(
471 nativeGetWidth(mNativeObject),
472 nativeGetHeight(mNativeObject));
473 }
474 }
475
476 /**
477 * Gets a {@link Canvas} for drawing into this surface that supports wide color gamut.
478 *
479 * After drawing into the provided {@link Canvas}, the caller must
480 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
481 *
482 * Unlike {@link #lockCanvas(Rect)} and {@link #lockHardwareCanvas()},
483 * this will return a hardware-accelerated canvas that supports wide color gamut.
484 * See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
485 * unsupported drawing operations</a> for a list of what is and isn't
486 * supported in a hardware-accelerated canvas. It is also required to
487 * fully cover the surface every time {@link #lockHardwareCanvas()} is
488 * called as the buffer is not preserved between frames. Partial updates
489 * are not supported.
490 *
491 * @return A canvas for drawing into the surface.
492 *
493 * @throws IllegalStateException If the canvas cannot be locked.
494 *
495 * @hide
496 */
497 public Canvas lockHardwareWideColorGamutCanvas() {
498 synchronized (mLock) {
499 checkNotReleasedLocked();
500 if (mHwuiContext != null && !mHwuiContext.isWideColorGamut()) {
501 mHwuiContext.destroy();
502 mHwuiContext = null;
503 }
504 if (mHwuiContext == null) {
505 mHwuiContext = new HwuiContext(true);
Andy McFaddened55c8d2013-08-20 10:05:51 -0700506 }
John Reckb35c9602014-11-13 16:15:08 -0800507 return mHwuiContext.lockCanvas(
508 nativeGetWidth(mNativeObject),
509 nativeGetHeight(mNativeObject));
Mathias Agopian7c116b52013-03-18 20:27:02 -0700510 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700511 }
512
Andy McFaddened55c8d2013-08-20 10:05:51 -0700513 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700514 * @deprecated This API has been removed and is not supported. Do not use.
515 */
516 @Deprecated
517 public void unlockCanvas(Canvas canvas) {
518 throw new UnsupportedOperationException();
519 }
520
521 /**
522 * Sets the translator used to scale canvas's width/height in compatibility
523 * mode.
524 */
525 void setCompatibilityTranslator(Translator translator) {
526 if (translator != null) {
527 float appScale = translator.applicationScale;
528 mCompatibleMatrix = new Matrix();
529 mCompatibleMatrix.setScale(appScale, appScale);
530 }
531 }
532
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700533 /**
Mathias Agopianb9230662011-08-03 14:44:48 -0700534 * Copy another surface to this one. This surface now holds a reference
535 * to the same data as the original surface, and is -not- the owner.
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800536 * This is for use by the window manager when returning a window surface
537 * back from a client, converting it from the representation being managed
538 * by the window manager to the representation the client uses to draw
539 * in to it.
Bryce Lee02949f12017-06-16 07:20:34 -0700540 *
541 * @param other {@link SurfaceControl} to copy from.
Mathias Agopianb9230662011-08-03 14:44:48 -0700542 * @hide
543 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100544 @UnsupportedAppUsage
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800545 public void copyFrom(SurfaceControl other) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700546 if (other == null) {
547 throw new IllegalArgumentException("other must not be null");
548 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700549
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000550 long surfaceControlPtr = other.mNativeObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700551 if (surfaceControlPtr == 0) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800552 throw new NullPointerException(
Bryce Lee02949f12017-06-16 07:20:34 -0700553 "null SurfaceControl native object. Are you using a released SurfaceControl?");
554 }
Robert Carrd5686722019-01-25 14:30:52 -0800555 long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr);
Bryce Lee02949f12017-06-16 07:20:34 -0700556
557 synchronized (mLock) {
Robert Carrd5686722019-01-25 14:30:52 -0800558 if (newNativeObject == mNativeObject) {
559 return;
560 }
Bryce Lee02949f12017-06-16 07:20:34 -0700561 if (mNativeObject != 0) {
562 nativeRelease(mNativeObject);
563 }
564 setNativeObjectLocked(newNativeObject);
565 }
566 }
567
568 /**
569 * Gets a reference a surface created from this one. This surface now holds a reference
570 * to the same data as the original surface, and is -not- the owner.
571 * This is for use by the window manager when returning a window surface
572 * back from a client, converting it from the representation being managed
573 * by the window manager to the representation the client uses to draw
574 * in to it.
575 *
576 * @param other {@link SurfaceControl} to create surface from.
577 *
578 * @hide
579 */
580 public void createFrom(SurfaceControl other) {
581 if (other == null) {
582 throw new IllegalArgumentException("other must not be null");
583 }
584
585 long surfaceControlPtr = other.mNativeObject;
586 if (surfaceControlPtr == 0) {
587 throw new NullPointerException(
588 "null SurfaceControl native object. Are you using a released SurfaceControl?");
Jeff Brown64a55af2012-08-26 02:47:39 -0700589 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000590 long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700591
592 synchronized (mLock) {
593 if (mNativeObject != 0) {
594 nativeRelease(mNativeObject);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700595 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700596 setNativeObjectLocked(newNativeObject);
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700597 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700598 }
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800599
600 /**
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700601 * This is intended to be used by {@link SurfaceView#updateWindow} only.
Mathias Agopian7c116b52013-03-18 20:27:02 -0700602 * @param other access is not thread safe
603 * @hide
604 * @deprecated
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800605 */
Mathias Agopian7c116b52013-03-18 20:27:02 -0700606 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +0100607 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700608 public void transferFrom(Surface other) {
609 if (other == null) {
610 throw new IllegalArgumentException("other must not be null");
611 }
612 if (other != this) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000613 final long newPtr;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700614 synchronized (other.mLock) {
615 newPtr = other.mNativeObject;
616 other.setNativeObjectLocked(0);
617 }
618
619 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700620 if (mNativeObject != 0) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700621 nativeRelease(mNativeObject);
622 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700623 setNativeObjectLocked(newPtr);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800624 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700625 }
Mathias Agopianb9230662011-08-03 14:44:48 -0700626 }
627
Jeff Brown64a55af2012-08-26 02:47:39 -0700628 @Override
629 public int describeContents() {
630 return 0;
631 }
632
633 public void readFromParcel(Parcel source) {
634 if (source == null) {
635 throw new IllegalArgumentException("source must not be null");
636 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700637
638 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700639 // nativeReadFromParcel() will either return mNativeObject, or
640 // create a new native Surface and return it after reducing
641 // the reference count on mNativeObject. Either way, it is
642 // not necessary to call nativeRelease() here.
Eino-Ville Talvalaf005f5e2016-08-29 17:51:23 -0700643 // NOTE: This must be kept synchronized with the native parceling code
644 // in frameworks/native/libs/Surface.cpp
Mathias Agopian7c116b52013-03-18 20:27:02 -0700645 mName = source.readString();
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700646 mIsSingleBuffered = source.readInt() != 0;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700647 setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700648 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700649 }
650
651 @Override
652 public void writeToParcel(Parcel dest, int flags) {
653 if (dest == null) {
654 throw new IllegalArgumentException("dest must not be null");
655 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700656 synchronized (mLock) {
Eino-Ville Talvalaf005f5e2016-08-29 17:51:23 -0700657 // NOTE: This must be kept synchronized with the native parceling code
658 // in frameworks/native/libs/Surface.cpp
Mathias Agopian7c116b52013-03-18 20:27:02 -0700659 dest.writeString(mName);
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700660 dest.writeInt(mIsSingleBuffered ? 1 : 0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700661 nativeWriteToParcel(mNativeObject, dest);
662 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700663 if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
664 release();
665 }
666 }
667
668 @Override
669 public String toString() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700670 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700671 return "Surface(name=" + mName + ")/@0x" +
672 Integer.toHexString(System.identityHashCode(this));
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700673 }
674 }
675
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000676 private void setNativeObjectLocked(long ptr) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700677 if (mNativeObject != ptr) {
678 if (mNativeObject == 0 && ptr != 0) {
679 mCloseGuard.open("release");
680 } else if (mNativeObject != 0 && ptr == 0) {
681 mCloseGuard.close();
682 }
683 mNativeObject = ptr;
684 mGenerationId += 1;
John Reckbb2d0cc2014-10-21 10:09:36 -0700685 if (mHwuiContext != null) {
686 mHwuiContext.updateSurface();
687 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700688 }
689 }
690
691 private void checkNotReleasedLocked() {
692 if (mNativeObject == 0) {
693 throw new IllegalStateException("Surface has already been released.");
694 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700695 }
696
Mathias Agopianc14bacf2012-04-23 18:23:08 -0700697 /**
Dan Stoza5795d642014-06-20 13:01:36 -0700698 * Allocate buffers ahead of time to avoid allocation delays during rendering
699 * @hide
700 */
701 public void allocateBuffers() {
702 synchronized (mLock) {
703 checkNotReleasedLocked();
704 nativeAllocateBuffers(mNativeObject);
705 }
706 }
707
708 /**
Robert Carrcd9a18c2015-12-16 18:16:21 -0800709 * Set the scaling mode to be used for this surfaces buffers
710 * @hide
711 */
712 void setScalingMode(@ScalingMode int scalingMode) {
713 synchronized (mLock) {
714 checkNotReleasedLocked();
715 int err = nativeSetScalingMode(mNativeObject, scalingMode);
716 if (err != 0) {
717 throw new IllegalArgumentException("Invalid scaling mode: " + scalingMode);
718 }
719 }
720 }
721
Robert Carr387838b2016-09-07 14:12:44 -0700722 void forceScopedDisconnect() {
723 synchronized (mLock) {
724 checkNotReleasedLocked();
725 int err = nativeForceScopedDisconnect(mNativeObject);
726 if (err != 0) {
727 throw new RuntimeException("Failed to disconnect Surface instance (bad object?)");
728 }
729 }
730 }
731
Robert Carrcd9a18c2015-12-16 18:16:21 -0800732 /**
Peiyong Linccc06b62019-06-25 17:31:09 -0700733 * Transfer ownership of buffer with a color space and present it on the Surface.
734 * The supported color spaces are SRGB and Display P3, other color spaces will be
735 * treated as SRGB.
736 * @hide
737 */
738 public void attachAndQueueBufferWithColorSpace(GraphicBuffer buffer, ColorSpace colorSpace) {
739 synchronized (mLock) {
740 checkNotReleasedLocked();
741 if (colorSpace == null) {
742 colorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
743 }
744 int err = nativeAttachAndQueueBufferWithColorSpace(mNativeObject, buffer,
745 colorSpace.getId());
746 if (err != 0) {
747 throw new RuntimeException(
748 "Failed to attach and queue buffer to Surface (bad object?), "
749 + "native error: " + err);
750 }
751 }
752 }
753
754 /**
755 * Deprecated, use attachAndQueueBufferWithColorSpace instead.
Robert Carra35e5de2017-03-03 17:04:54 -0800756 * Transfer ownership of buffer and present it on the Surface.
Peiyong Linccc06b62019-06-25 17:31:09 -0700757 * The color space of the buffer is treated as SRGB.
Robert Carra35e5de2017-03-03 17:04:54 -0800758 * @hide
759 */
760 public void attachAndQueueBuffer(GraphicBuffer buffer) {
Peiyong Linccc06b62019-06-25 17:31:09 -0700761 attachAndQueueBufferWithColorSpace(buffer, ColorSpace.get(ColorSpace.Named.SRGB));
Robert Carra35e5de2017-03-03 17:04:54 -0800762 }
763
764 /**
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700765 * Returns whether or not this Surface is backed by a single-buffered SurfaceTexture
766 * @hide
767 */
768 public boolean isSingleBuffered() {
769 return mIsSingleBuffered;
770 }
771
772 /**
Romain Guy0bbf0b42017-07-20 08:57:07 -0700773 * <p>The shared buffer mode allows both the application and the surface compositor
774 * (SurfaceFlinger) to concurrently access this surface's buffer. While the
775 * application is still required to issue a present request
776 * (see {@link #unlockCanvasAndPost(Canvas)}) to the compositor when an update is required,
777 * the compositor may trigger an update at any time. Since the surface's buffer is shared
778 * between the application and the compositor, updates triggered by the compositor may
779 * cause visible tearing.</p>
780 *
781 * <p>The shared buffer mode can be used with
782 * {@link #setAutoRefreshEnabled(boolean) auto-refresh} to avoid the overhead of
783 * issuing present requests.</p>
784 *
785 * <p>If the application uses the shared buffer mode to reduce latency, it is
786 * recommended to use software rendering (see {@link #lockCanvas(Rect)} to ensure
787 * the graphics workloads are not affected by other applications and/or the system
788 * using the GPU. When using software rendering, the application should update the
789 * smallest possible region of the surface required.</p>
790 *
791 * <p class="note">The shared buffer mode might not be supported by the underlying
792 * hardware. Enabling shared buffer mode on hardware that does not support it will
793 * not yield an error but the application will not benefit from lower latency (and
794 * tearing will not be visible).</p>
795 *
796 * <p class="note">Depending on how many and what kind of surfaces are visible, the
797 * surface compositor may need to copy the shared buffer before it is displayed. When
798 * this happens, the latency benefits of shared buffer mode will be reduced.</p>
799 *
800 * @param enabled True to enable the shared buffer mode on this surface, false otherwise
801 *
802 * @see #isSharedBufferModeEnabled()
803 * @see #setAutoRefreshEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700804 *
805 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700806 */
807 public void setSharedBufferModeEnabled(boolean enabled) {
808 if (mIsSharedBufferModeEnabled != enabled) {
809 int error = nativeSetSharedBufferModeEnabled(mNativeObject, enabled);
810 if (error != 0) {
811 throw new RuntimeException(
812 "Failed to set shared buffer mode on Surface (bad object?)");
813 } else {
814 mIsSharedBufferModeEnabled = enabled;
815 }
816 }
817 }
818
819 /**
820 * @return True if shared buffer mode is enabled on this surface, false otherwise
821 *
822 * @see #setSharedBufferModeEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700823 *
824 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700825 */
826 public boolean isSharedBufferModeEnabled() {
827 return mIsSharedBufferModeEnabled;
828 }
829
830 /**
831 * <p>When auto-refresh is enabled, the surface compositor (SurfaceFlinger)
832 * automatically updates the display on a regular refresh cycle. The application
833 * can continue to issue present requests but it is not required. Enabling
834 * auto-refresh may result in visible tearing.</p>
835 *
836 * <p>Auto-refresh has no effect if the {@link #setSharedBufferModeEnabled(boolean)
837 * shared buffer mode} is not enabled.</p>
838 *
839 * <p>Because auto-refresh will trigger continuous updates of the display, it is
840 * recommended to turn it on only when necessary. For example, in a drawing/painting
841 * application auto-refresh should be enabled on finger/pen down and disabled on
842 * finger/pen up.</p>
843 *
844 * @param enabled True to enable auto-refresh on this surface, false otherwise
845 *
846 * @see #isAutoRefreshEnabled()
847 * @see #setSharedBufferModeEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700848 *
849 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700850 */
851 public void setAutoRefreshEnabled(boolean enabled) {
852 if (mIsAutoRefreshEnabled != enabled) {
853 int error = nativeSetAutoRefreshEnabled(mNativeObject, enabled);
854 if (error != 0) {
855 throw new RuntimeException("Failed to set auto refresh on Surface (bad object?)");
856 } else {
857 mIsAutoRefreshEnabled = enabled;
858 }
859 }
860 }
861
862 /**
863 * @return True if auto-refresh is enabled on this surface, false otherwise
Romain Guy010f0822017-08-16 09:43:07 -0700864 *
865 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700866 */
867 public boolean isAutoRefreshEnabled() {
868 return mIsAutoRefreshEnabled;
869 }
870
871 /**
Steven Thomas6cf051e2020-01-14 11:37:21 -0800872 * Sets the intended frame rate for this surface.
873 *
874 * On devices that are capable of running the display at different refresh rates, the
875 * system may choose a display refresh rate to better match this surface's frame
876 * rate. Usage of this API won't introduce frame rate throttling, or affect other
877 * aspects of the application's frame production pipeline. However, because the system
878 * may change the display refresh rate, calls to this function may result in changes
879 * to Choreographer callback timings, and changes to the time interval at which the
880 * system releases buffers back to the application.
881 *
882 * Note that this only has an effect for surfaces presented on the display. If this
883 * surface is consumed by something other than the system compositor, e.g. a media
884 * codec, this call has no effect.
885 *
Steven Thomasadd6be12020-01-23 16:35:32 -0800886 * @param frameRate The intended frame rate of this surface, in frames per second. 0
887 * is a special value that indicates the app will accept the system's choice for the
888 * display frame rate, which is the default behavior if this function isn't
889 * called. The frameRate param does *not* need to be a valid refresh rate for this
890 * device's display - e.g., it's fine to pass 30fps to a device that can only run the
891 * display at 60fps.
Steven Thomasdd7bf2f2020-01-31 18:50:02 -0800892 *
893 * @param compatibility The frame rate compatibility of this surface. The
894 * compatibility value may influence the system's choice of display frame rate. See
895 * the FRAME_RATE_COMPATIBILITY_* values for more info.
896 *
897 * @throws IllegalArgumentException If frameRate or compatibility are invalid.
Steven Thomas6cf051e2020-01-14 11:37:21 -0800898 */
Steven Thomasdd7bf2f2020-01-31 18:50:02 -0800899 public void setFrameRate(
900 @FloatRange(from = 0.0) float frameRate, @FrameRateCompatibility int compatibility) {
901 synchronized (mLock) {
902 checkNotReleasedLocked();
903 int error = nativeSetFrameRate(mNativeObject, frameRate, compatibility);
904 if (error == -EINVAL) {
905 throw new IllegalArgumentException("Invalid argument to Surface.setFrameRate()");
906 } else if (error != 0) {
907 throw new RuntimeException("Failed to set frame rate on Surface");
908 }
Steven Thomas6cf051e2020-01-14 11:37:21 -0800909 }
910 }
911
912 /**
Igor Murashkina86ab6402013-08-30 12:58:36 -0700913 * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or
914 * when a SurfaceTexture could not successfully be allocated.
Jeff Brown64a55af2012-08-26 02:47:39 -0700915 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700916 @SuppressWarnings("serial")
917 public static class OutOfResourcesException extends RuntimeException {
Jeff Brown64a55af2012-08-26 02:47:39 -0700918 public OutOfResourcesException() {
919 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700920 public OutOfResourcesException(String name) {
921 super(name);
922 }
923 }
924
925 /**
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700926 * Returns a human readable representation of a rotation.
927 *
928 * @param rotation The rotation.
929 * @return The rotation symbolic name.
Svetoslav Ganov545252f2012-12-10 18:29:24 -0800930 *
931 * @hide
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700932 */
933 public static String rotationToString(int rotation) {
934 switch (rotation) {
935 case Surface.ROTATION_0: {
936 return "ROTATION_0";
937 }
938 case Surface.ROTATION_90: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700939 return "ROTATION_90";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700940 }
941 case Surface.ROTATION_180: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700942 return "ROTATION_180";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700943 }
944 case Surface.ROTATION_270: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700945 return "ROTATION_270";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700946 }
947 default: {
Michael Wright19859762017-09-18 20:57:58 +0100948 return Integer.toString(rotation);
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700949 }
950 }
951 }
952
953 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700954 * A Canvas class that can handle the compatibility mode.
955 * This does two things differently.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700956 * <ul>
Mathias Agopianb9230662011-08-03 14:44:48 -0700957 * <li>Returns the width and height of the target metrics, rather than
958 * native. For example, the canvas returns 320x480 even if an app is running
959 * in WVGA high density.
960 * <li>Scales the matrix in setMatrix by the application scale, except if
961 * the matrix looks like obtained from getMatrix. This is a hack to handle
962 * the case that an application uses getMatrix to keep the original matrix,
963 * set matrix of its own, then set the original matrix back. There is no
964 * perfect solution that works for all cases, and there are a lot of cases
965 * that this model does not work, but we hope this works for many apps.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700966 * </ul>
967 */
Jeff Brown64a55af2012-08-26 02:47:39 -0700968 private final class CompatibleCanvas extends Canvas {
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700969 // A temp matrix to remember what an application obtained via {@link getMatrix}
970 private Matrix mOrigMatrix = null;
971
972 @Override
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700973 public void setMatrix(Matrix matrix) {
974 if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
975 // don't scale the matrix if it's not compatibility mode, or
976 // the matrix was obtained from getMatrix.
977 super.setMatrix(matrix);
978 } else {
979 Matrix m = new Matrix(mCompatibleMatrix);
980 m.preConcat(matrix);
981 super.setMatrix(m);
982 }
983 }
984
Romain Guy8b5aa482013-02-28 18:13:54 -0800985 @SuppressWarnings("deprecation")
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700986 @Override
987 public void getMatrix(Matrix m) {
988 super.getMatrix(m);
989 if (mOrigMatrix == null) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700990 mOrigMatrix = new Matrix();
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700991 }
992 mOrigMatrix.set(m);
993 }
Romain Guyd10cd572010-10-10 13:33:22 -0700994 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700995
996 private final class HwuiContext {
997 private final RenderNode mRenderNode;
Derek Sollenberger4aa30d02019-08-30 13:53:29 -0400998 private HardwareRenderer mHardwareRenderer;
John Reck32f140aa62018-10-04 15:08:24 -0700999 private RecordingCanvas mCanvas;
Peiyong Lind8b68712018-03-06 18:34:21 -08001000 private final boolean mIsWideColorGamut;
John Reckbb2d0cc2014-10-21 10:09:36 -07001001
Peiyong Lind8b68712018-03-06 18:34:21 -08001002 HwuiContext(boolean isWideColorGamut) {
John Reckbb2d0cc2014-10-21 10:09:36 -07001003 mRenderNode = RenderNode.create("HwuiCanvas", null);
1004 mRenderNode.setClipToBounds(false);
John Recka2d20b42018-10-01 12:21:55 -07001005 mRenderNode.setForceDarkAllowed(false);
Peiyong Lind8b68712018-03-06 18:34:21 -08001006 mIsWideColorGamut = isWideColorGamut;
Derek Sollenberger4aa30d02019-08-30 13:53:29 -04001007
1008 mHardwareRenderer = new HardwareRenderer();
1009 mHardwareRenderer.setContentRoot(mRenderNode);
1010 mHardwareRenderer.setSurface(Surface.this, true);
1011 mHardwareRenderer.setWideGamut(isWideColorGamut);
1012 mHardwareRenderer.setLightSourceAlpha(0.0f, 0.0f);
1013 mHardwareRenderer.setLightSourceGeometry(0.0f, 0.0f, 0.0f, 0.0f);
John Reckbb2d0cc2014-10-21 10:09:36 -07001014 }
1015
John Reckb35c9602014-11-13 16:15:08 -08001016 Canvas lockCanvas(int width, int height) {
John Reckbb2d0cc2014-10-21 10:09:36 -07001017 if (mCanvas != null) {
1018 throw new IllegalStateException("Surface was already locked!");
1019 }
John Recke57475e2019-02-20 17:39:52 -08001020 mCanvas = mRenderNode.beginRecording(width, height);
John Reckbb2d0cc2014-10-21 10:09:36 -07001021 return mCanvas;
1022 }
1023
1024 void unlockAndPost(Canvas canvas) {
1025 if (canvas != mCanvas) {
1026 throw new IllegalArgumentException("canvas object must be the same instance that "
1027 + "was previously returned by lockCanvas");
1028 }
John Recke57475e2019-02-20 17:39:52 -08001029 mRenderNode.endRecording();
John Reckbb2d0cc2014-10-21 10:09:36 -07001030 mCanvas = null;
Derek Sollenberger4aa30d02019-08-30 13:53:29 -04001031 mHardwareRenderer.createRenderRequest()
1032 .setVsyncTime(System.nanoTime())
1033 .syncAndDraw();
John Reckbb2d0cc2014-10-21 10:09:36 -07001034 }
1035
1036 void updateSurface() {
Derek Sollenberger4aa30d02019-08-30 13:53:29 -04001037 mHardwareRenderer.setSurface(Surface.this, true);
John Reckbb2d0cc2014-10-21 10:09:36 -07001038 }
1039
1040 void destroy() {
Derek Sollenberger4aa30d02019-08-30 13:53:29 -04001041 mHardwareRenderer.destroy();
John Reckbb2d0cc2014-10-21 10:09:36 -07001042 }
Peiyong Lind8b68712018-03-06 18:34:21 -08001043
1044 boolean isWideColorGamut() {
1045 return mIsWideColorGamut;
1046 }
John Reckbb2d0cc2014-10-21 10:09:36 -07001047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048}