blob: a417a4a04e2fbf05dfe42817d3b99c5df195e1bb [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
Tor Norbyed9273d62013-05-30 15:59:53 -070019import android.annotation.IntDef;
Mitsuru Oshima240f8a72009-07-22 20:39:14 -070020import android.content.res.CompatibilityInfo.Translator;
Jeff Brown0b722fe2012-08-24 22:40:14 -070021import android.graphics.Canvas;
Robert Carra35e5de2017-03-03 17:04:54 -080022import android.graphics.GraphicBuffer;
Jeff Brown0b722fe2012-08-24 22:40:14 -070023import android.graphics.Matrix;
24import android.graphics.Rect;
Jeff Brown0b722fe2012-08-24 22:40:14 -070025import android.graphics.SurfaceTexture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.os.Parcel;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080027import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.util.Log;
Tor Norbyed9273d62013-05-30 15:59:53 -070029
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070030import dalvik.system.CloseGuard;
31
Tor Norbyed9273d62013-05-30 15:59:53 -070032import java.lang.annotation.Retention;
33import java.lang.annotation.RetentionPolicy;
34
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035/**
Glenn Kasten334031c2010-11-09 21:54:38 -080036 * Handle onto a raw buffer that is being managed by the screen compositor.
Eino-Ville Talvalac4faf0c2016-09-16 13:34:52 -070037 *
38 * <p>A Surface is generally created by or from a consumer of image buffers (such as a
39 * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or
40 * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as
41 * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL},
42 * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or
43 * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw
44 * into.</p>
45 *
46 * <p><strong>Note:</strong> A Surface acts like a
47 * {@link java.lang.ref.WeakReference weak reference} to the consumer it is associated with. By
48 * itself it will not keep its parent consumer from being reclaimed.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 */
50public class Surface implements Parcelable {
Jeff Brown64a55af2012-08-26 02:47:39 -070051 private static final String TAG = "Surface";
Mathias Agopianb9230662011-08-03 14:44:48 -070052
Ashok Bhat36bef0b2014-01-20 20:08:01 +000053 private static native long nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
Mathias Agopian29479eb2013-02-14 14:36:04 -080054 throws OutOfResourcesException;
Bryce Lee02949f12017-06-16 07:20:34 -070055
Ashok Bhat36bef0b2014-01-20 20:08:01 +000056 private static native long nativeCreateFromSurfaceControl(long surfaceControlNativeObject);
Bryce Lee02949f12017-06-16 07:20:34 -070057 private static native long nativeGetFromSurfaceControl(long surfaceControlNativeObject);
Mathias Agopian52800612013-02-14 17:11:20 -080058
Ashok Bhat36bef0b2014-01-20 20:08:01 +000059 private static native long nativeLockCanvas(long nativeObject, Canvas canvas, Rect dirty)
Jeff Brownfc0ebd72013-04-30 16:33:00 -070060 throws OutOfResourcesException;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000061 private static native void nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas);
Mathias Agopian29479eb2013-02-14 14:36:04 -080062
Ashok Bhat36bef0b2014-01-20 20:08:01 +000063 private static native void nativeRelease(long nativeObject);
64 private static native boolean nativeIsValid(long nativeObject);
65 private static native boolean nativeIsConsumerRunningBehind(long nativeObject);
66 private static native long nativeReadFromParcel(long nativeObject, Parcel source);
67 private static native void nativeWriteToParcel(long nativeObject, Parcel dest);
Mathias Agopian29479eb2013-02-14 14:36:04 -080068
Dan Stoza5795d642014-06-20 13:01:36 -070069 private static native void nativeAllocateBuffers(long nativeObject);
70
John Reckb35c9602014-11-13 16:15:08 -080071 private static native int nativeGetWidth(long nativeObject);
72 private static native int nativeGetHeight(long nativeObject);
73
Rob Carr64e516f2015-10-29 00:20:45 +000074 private static native long nativeGetNextFrameNumber(long nativeObject);
Robert Carrcd9a18c2015-12-16 18:16:21 -080075 private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
Robert Carr387838b2016-09-07 14:12:44 -070076 private static native int nativeForceScopedDisconnect(long nativeObject);
Robert Carra35e5de2017-03-03 17:04:54 -080077 private static native int nativeAttachAndQueueBuffer(long nativeObject, GraphicBuffer buffer);
Rob Carr64e516f2015-10-29 00:20:45 +000078
Romain Guy0bbf0b42017-07-20 08:57:07 -070079 private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled);
80 private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
81
Jeff Brown64a55af2012-08-26 02:47:39 -070082 public static final Parcelable.Creator<Surface> CREATOR =
83 new Parcelable.Creator<Surface>() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -070084 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -070085 public Surface createFromParcel(Parcel source) {
86 try {
87 Surface s = new Surface();
88 s.readFromParcel(source);
89 return s;
90 } catch (Exception e) {
91 Log.e(TAG, "Exception creating surface from parcel", e);
92 return null;
93 }
Kevin Hesterb85c9332012-03-08 17:06:56 -080094 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -070095
96 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -070097 public Surface[] newArray(int size) {
98 return new Surface[size];
99 }
100 };
Kevin Hesterb85c9332012-03-08 17:06:56 -0800101
Jeff Brown64a55af2012-08-26 02:47:39 -0700102 private final CloseGuard mCloseGuard = CloseGuard.get();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700103
104 // Guarded state.
105 final Object mLock = new Object(); // protects the native state
Jeff Brown64a55af2012-08-26 02:47:39 -0700106 private String mName;
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000107 long mNativeObject; // package scope only for SurfaceControl access
108 private long mLockedObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700109 private int mGenerationId; // incremented each time mNativeObject changes
Jeff Brown64a55af2012-08-26 02:47:39 -0700110 private final Canvas mCanvas = new CompatibleCanvas();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700112 // A matrix to scale the matrix set by application. This is set to null for
113 // non compatibility mode.
114 private Matrix mCompatibleMatrix;
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700115
John Reckbb2d0cc2014-10-21 10:09:36 -0700116 private HwuiContext mHwuiContext;
117
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700118 private boolean mIsSingleBuffered;
Romain Guy0bbf0b42017-07-20 08:57:07 -0700119 private boolean mIsSharedBufferModeEnabled;
120 private boolean mIsAutoRefreshEnabled;
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700121
Tor Norbyed9273d62013-05-30 15:59:53 -0700122 /** @hide */
Robert Carrcd9a18c2015-12-16 18:16:21 -0800123 @Retention(RetentionPolicy.SOURCE)
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700124 @IntDef(prefix = { "SCALING_MODE_" }, value = {
125 SCALING_MODE_FREEZE,
126 SCALING_MODE_SCALE_TO_WINDOW,
127 SCALING_MODE_SCALE_CROP,
128 SCALING_MODE_NO_SCALE_CROP
129 })
Robert Carrcd9a18c2015-12-16 18:16:21 -0800130 public @interface ScalingMode {}
131 // From system/window.h
132 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700133 public static final int SCALING_MODE_FREEZE = 0;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800134 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700135 public static final int SCALING_MODE_SCALE_TO_WINDOW = 1;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800136 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700137 public static final int SCALING_MODE_SCALE_CROP = 2;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800138 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700139 public static final int SCALING_MODE_NO_SCALE_CROP = 3;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800140
141 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700142 @IntDef(prefix = { "ROTATION_" }, value = {
143 ROTATION_0,
144 ROTATION_90,
145 ROTATION_180,
146 ROTATION_270
147 })
Tor Norbyed9273d62013-05-30 15:59:53 -0700148 @Retention(RetentionPolicy.SOURCE)
149 public @interface Rotation {}
150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 /**
Mathias Agopian29479eb2013-02-14 14:36:04 -0800152 * Rotation constant: 0 degree rotation (natural orientation)
153 */
154 public static final int ROTATION_0 = 0;
155
156 /**
157 * Rotation constant: 90 degree rotation.
158 */
159 public static final int ROTATION_90 = 1;
160
161 /**
162 * Rotation constant: 180 degree rotation.
163 */
164 public static final int ROTATION_180 = 2;
165
166 /**
167 * Rotation constant: 270 degree rotation.
168 */
169 public static final int ROTATION_270 = 3;
170
Mathias Agopian29479eb2013-02-14 14:36:04 -0800171 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700172 * Create an empty surface, which will later be filled in by readFromParcel().
Mathias Agopianb9230662011-08-03 14:44:48 -0700173 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 */
175 public Surface() {
Jeff Brown64a55af2012-08-26 02:47:39 -0700176 }
177
178 /**
179 * Create Surface from a {@link SurfaceTexture}.
180 *
181 * Images drawn to the Surface will be made available to the {@link
182 * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
183 * SurfaceTexture#updateTexImage}.
184 *
185 * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
186 * Surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700187 * @throws OutOfResourcesException if the surface could not be created.
Jeff Brown64a55af2012-08-26 02:47:39 -0700188 */
189 public Surface(SurfaceTexture surfaceTexture) {
190 if (surfaceTexture == null) {
191 throw new IllegalArgumentException("surfaceTexture must not be null");
192 }
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700193 mIsSingleBuffered = surfaceTexture.isSingleBuffered();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700194 synchronized (mLock) {
195 mName = surfaceTexture.toString();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700196 setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
Jeff Brown64a55af2012-08-26 02:47:39 -0700197 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700198 }
199
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700200 /* called from android_view_Surface_createFromIGraphicBufferProducer() */
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000201 private Surface(long nativeObject) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700202 synchronized (mLock) {
203 setNativeObjectLocked(nativeObject);
204 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800205 }
206
Jeff Brown64a55af2012-08-26 02:47:39 -0700207 @Override
208 protected void finalize() throws Throwable {
209 try {
210 if (mCloseGuard != null) {
211 mCloseGuard.warnIfOpen();
212 }
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700213 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700214 } finally {
215 super.finalize();
216 }
217 }
218
219 /**
220 * Release the local reference to the server-side surface.
221 * Always call release() when you're done with a Surface.
222 * This will make the surface invalid.
223 */
224 public void release() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700225 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700226 if (mNativeObject != 0) {
227 nativeRelease(mNativeObject);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700228 setNativeObjectLocked(0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700229 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700230 if (mHwuiContext != null) {
231 mHwuiContext.destroy();
232 mHwuiContext = null;
233 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800234 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700235 }
236
237 /**
238 * Free all server-side state associated with this surface and
239 * release this object's reference. This method can only be
240 * called from the process that created the service.
241 * @hide
242 */
243 public void destroy() {
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700244 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700245 }
246
247 /**
248 * Returns true if this object holds a valid surface.
249 *
250 * @return True if it holds a physical surface, so lockCanvas() will succeed.
251 * Otherwise returns false.
252 */
253 public boolean isValid() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700254 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700255 if (mNativeObject == 0) return false;
256 return nativeIsValid(mNativeObject);
257 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700258 }
259
260 /**
261 * Gets the generation number of this surface, incremented each time
262 * the native surface contained within this object changes.
263 *
264 * @return The current generation number.
265 * @hide
266 */
267 public int getGenerationId() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700268 synchronized (mLock) {
269 return mGenerationId;
270 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700271 }
272
273 /**
Rob Carr64e516f2015-10-29 00:20:45 +0000274 * Returns the next frame number which will be dequeued for rendering.
275 * Intended for use with SurfaceFlinger's deferred transactions API.
276 *
277 * @hide
278 */
279 public long getNextFrameNumber() {
280 synchronized (mLock) {
281 return nativeGetNextFrameNumber(mNativeObject);
282 }
283 }
284
285 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700286 * Returns true if the consumer of this Surface is running behind the producer.
287 *
288 * @return True if the consumer is more than one buffer ahead of the producer.
289 * @hide
290 */
291 public boolean isConsumerRunningBehind() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700292 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700293 checkNotReleasedLocked();
294 return nativeIsConsumerRunningBehind(mNativeObject);
295 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700296 }
297
298 /**
299 * Gets a {@link Canvas} for drawing into this surface.
300 *
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700301 * After drawing into the provided {@link Canvas}, the caller must
Jeff Brown64a55af2012-08-26 02:47:39 -0700302 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
303 *
Mathias Agopian30d7ab92013-02-14 15:38:40 -0800304 * @param inOutDirty A rectangle that represents the dirty region that the caller wants
Jeff Brown64a55af2012-08-26 02:47:39 -0700305 * to redraw. This function may choose to expand the dirty rectangle if for example
306 * the surface has been resized or if the previous contents of the surface were
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700307 * not available. The caller must redraw the entire dirty region as represented
308 * by the contents of the inOutDirty rectangle upon return from this function.
Jeff Brown64a55af2012-08-26 02:47:39 -0700309 * The caller may also pass <code>null</code> instead, in the case where the
310 * entire surface should be redrawn.
311 * @return A canvas for drawing into the surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700312 *
313 * @throws IllegalArgumentException If the inOutDirty rectangle is not valid.
314 * @throws OutOfResourcesException If the canvas cannot be locked.
Jeff Brown64a55af2012-08-26 02:47:39 -0700315 */
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800316 public Canvas lockCanvas(Rect inOutDirty)
Igor Murashkina86ab6402013-08-30 12:58:36 -0700317 throws Surface.OutOfResourcesException, IllegalArgumentException {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700318 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700319 checkNotReleasedLocked();
Andy McFaddened55c8d2013-08-20 10:05:51 -0700320 if (mLockedObject != 0) {
321 // Ideally, nativeLockCanvas() would throw in this situation and prevent the
322 // double-lock, but that won't happen if mNativeObject was updated. We can't
323 // abandon the old mLockedObject because it might still be in use, so instead
324 // we just refuse to re-lock the Surface.
Jesse Halld7e55962014-10-13 11:01:15 -0700325 throw new IllegalArgumentException("Surface was already locked");
Andy McFaddened55c8d2013-08-20 10:05:51 -0700326 }
327 mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700328 return mCanvas;
Mathias Agopian7c116b52013-03-18 20:27:02 -0700329 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700330 }
331
332 /**
333 * Posts the new contents of the {@link Canvas} to the surface and
334 * releases the {@link Canvas}.
335 *
336 * @param canvas The canvas previously obtained from {@link #lockCanvas}.
337 */
338 public void unlockCanvasAndPost(Canvas canvas) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700339 synchronized (mLock) {
340 checkNotReleasedLocked();
341
342 if (mHwuiContext != null) {
343 mHwuiContext.unlockAndPost(canvas);
344 } else {
345 unlockSwCanvasAndPost(canvas);
346 }
347 }
348 }
349
350 private void unlockSwCanvasAndPost(Canvas canvas) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700351 if (canvas != mCanvas) {
352 throw new IllegalArgumentException("canvas object must be the same instance that "
353 + "was previously returned by lockCanvas");
354 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700355 if (mNativeObject != mLockedObject) {
356 Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
357 Long.toHexString(mNativeObject) + ") != mLockedObject (0x" +
358 Long.toHexString(mLockedObject) +")");
359 }
360 if (mLockedObject == 0) {
361 throw new IllegalStateException("Surface was not locked");
362 }
363 try {
364 nativeUnlockCanvasAndPost(mLockedObject, canvas);
365 } finally {
366 nativeRelease(mLockedObject);
367 mLockedObject = 0;
368 }
369 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700370
John Reckbb2d0cc2014-10-21 10:09:36 -0700371 /**
372 * Gets a {@link Canvas} for drawing into this surface.
373 *
374 * After drawing into the provided {@link Canvas}, the caller must
375 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
376 *
377 * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated
378 * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
379 * unsupported drawing operations</a> for a list of what is and isn't
John Reck43a53282014-10-23 13:56:03 -0700380 * supported in a hardware-accelerated canvas. It is also required to
381 * fully cover the surface every time {@link #lockHardwareCanvas()} is
382 * called as the buffer is not preserved between frames. Partial updates
383 * are not supported.
John Reckbb2d0cc2014-10-21 10:09:36 -0700384 *
385 * @return A canvas for drawing into the surface.
386 *
387 * @throws IllegalStateException If the canvas cannot be locked.
388 */
389 public Canvas lockHardwareCanvas() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700390 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700391 checkNotReleasedLocked();
John Reckbb2d0cc2014-10-21 10:09:36 -0700392 if (mHwuiContext == null) {
393 mHwuiContext = new HwuiContext();
Andy McFaddened55c8d2013-08-20 10:05:51 -0700394 }
John Reckb35c9602014-11-13 16:15:08 -0800395 return mHwuiContext.lockCanvas(
396 nativeGetWidth(mNativeObject),
397 nativeGetHeight(mNativeObject));
Mathias Agopian7c116b52013-03-18 20:27:02 -0700398 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700399 }
400
Andy McFaddened55c8d2013-08-20 10:05:51 -0700401 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700402 * @deprecated This API has been removed and is not supported. Do not use.
403 */
404 @Deprecated
405 public void unlockCanvas(Canvas canvas) {
406 throw new UnsupportedOperationException();
407 }
408
409 /**
410 * Sets the translator used to scale canvas's width/height in compatibility
411 * mode.
412 */
413 void setCompatibilityTranslator(Translator translator) {
414 if (translator != null) {
415 float appScale = translator.applicationScale;
416 mCompatibleMatrix = new Matrix();
417 mCompatibleMatrix.setScale(appScale, appScale);
418 }
419 }
420
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700421 /**
Mathias Agopianb9230662011-08-03 14:44:48 -0700422 * Copy another surface to this one. This surface now holds a reference
423 * to the same data as the original surface, and is -not- the owner.
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800424 * This is for use by the window manager when returning a window surface
425 * back from a client, converting it from the representation being managed
426 * by the window manager to the representation the client uses to draw
427 * in to it.
Bryce Lee02949f12017-06-16 07:20:34 -0700428 *
429 * @param other {@link SurfaceControl} to copy from.
430 *
Mathias Agopianb9230662011-08-03 14:44:48 -0700431 * @hide
432 */
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800433 public void copyFrom(SurfaceControl other) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700434 if (other == null) {
435 throw new IllegalArgumentException("other must not be null");
436 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700437
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000438 long surfaceControlPtr = other.mNativeObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700439 if (surfaceControlPtr == 0) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800440 throw new NullPointerException(
Bryce Lee02949f12017-06-16 07:20:34 -0700441 "null SurfaceControl native object. Are you using a released SurfaceControl?");
442 }
443 long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);
444
445 synchronized (mLock) {
446 if (mNativeObject != 0) {
447 nativeRelease(mNativeObject);
448 }
449 setNativeObjectLocked(newNativeObject);
450 }
451 }
452
453 /**
454 * Gets a reference a surface created from this one. This surface now holds a reference
455 * to the same data as the original surface, and is -not- the owner.
456 * This is for use by the window manager when returning a window surface
457 * back from a client, converting it from the representation being managed
458 * by the window manager to the representation the client uses to draw
459 * in to it.
460 *
461 * @param other {@link SurfaceControl} to create surface from.
462 *
463 * @hide
464 */
465 public void createFrom(SurfaceControl other) {
466 if (other == null) {
467 throw new IllegalArgumentException("other must not be null");
468 }
469
470 long surfaceControlPtr = other.mNativeObject;
471 if (surfaceControlPtr == 0) {
472 throw new NullPointerException(
473 "null SurfaceControl native object. Are you using a released SurfaceControl?");
Jeff Brown64a55af2012-08-26 02:47:39 -0700474 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000475 long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700476
477 synchronized (mLock) {
478 if (mNativeObject != 0) {
479 nativeRelease(mNativeObject);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700480 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700481 setNativeObjectLocked(newNativeObject);
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700482 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700483 }
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800484
485 /**
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700486 * This is intended to be used by {@link SurfaceView#updateWindow} only.
Mathias Agopian7c116b52013-03-18 20:27:02 -0700487 * @param other access is not thread safe
488 * @hide
489 * @deprecated
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800490 */
Mathias Agopian7c116b52013-03-18 20:27:02 -0700491 @Deprecated
Jeff Brown64a55af2012-08-26 02:47:39 -0700492 public void transferFrom(Surface other) {
493 if (other == null) {
494 throw new IllegalArgumentException("other must not be null");
495 }
496 if (other != this) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000497 final long newPtr;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700498 synchronized (other.mLock) {
499 newPtr = other.mNativeObject;
500 other.setNativeObjectLocked(0);
501 }
502
503 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700504 if (mNativeObject != 0) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700505 nativeRelease(mNativeObject);
506 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700507 setNativeObjectLocked(newPtr);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800508 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700509 }
Mathias Agopianb9230662011-08-03 14:44:48 -0700510 }
511
Jeff Brown64a55af2012-08-26 02:47:39 -0700512 @Override
513 public int describeContents() {
514 return 0;
515 }
516
517 public void readFromParcel(Parcel source) {
518 if (source == null) {
519 throw new IllegalArgumentException("source must not be null");
520 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700521
522 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700523 // nativeReadFromParcel() will either return mNativeObject, or
524 // create a new native Surface and return it after reducing
525 // the reference count on mNativeObject. Either way, it is
526 // not necessary to call nativeRelease() here.
Eino-Ville Talvalaf005f5e2016-08-29 17:51:23 -0700527 // NOTE: This must be kept synchronized with the native parceling code
528 // in frameworks/native/libs/Surface.cpp
Mathias Agopian7c116b52013-03-18 20:27:02 -0700529 mName = source.readString();
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700530 mIsSingleBuffered = source.readInt() != 0;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700531 setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700532 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700533 }
534
535 @Override
536 public void writeToParcel(Parcel dest, int flags) {
537 if (dest == null) {
538 throw new IllegalArgumentException("dest must not be null");
539 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700540 synchronized (mLock) {
Eino-Ville Talvalaf005f5e2016-08-29 17:51:23 -0700541 // NOTE: This must be kept synchronized with the native parceling code
542 // in frameworks/native/libs/Surface.cpp
Mathias Agopian7c116b52013-03-18 20:27:02 -0700543 dest.writeString(mName);
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700544 dest.writeInt(mIsSingleBuffered ? 1 : 0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700545 nativeWriteToParcel(mNativeObject, dest);
546 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700547 if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
548 release();
549 }
550 }
551
552 @Override
553 public String toString() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700554 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700555 return "Surface(name=" + mName + ")/@0x" +
556 Integer.toHexString(System.identityHashCode(this));
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700557 }
558 }
559
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000560 private void setNativeObjectLocked(long ptr) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700561 if (mNativeObject != ptr) {
562 if (mNativeObject == 0 && ptr != 0) {
563 mCloseGuard.open("release");
564 } else if (mNativeObject != 0 && ptr == 0) {
565 mCloseGuard.close();
566 }
567 mNativeObject = ptr;
568 mGenerationId += 1;
John Reckbb2d0cc2014-10-21 10:09:36 -0700569 if (mHwuiContext != null) {
570 mHwuiContext.updateSurface();
571 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700572 }
573 }
574
575 private void checkNotReleasedLocked() {
576 if (mNativeObject == 0) {
577 throw new IllegalStateException("Surface has already been released.");
578 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700579 }
580
Mathias Agopianc14bacf2012-04-23 18:23:08 -0700581 /**
Dan Stoza5795d642014-06-20 13:01:36 -0700582 * Allocate buffers ahead of time to avoid allocation delays during rendering
583 * @hide
584 */
585 public void allocateBuffers() {
586 synchronized (mLock) {
587 checkNotReleasedLocked();
588 nativeAllocateBuffers(mNativeObject);
589 }
590 }
591
592 /**
Robert Carrcd9a18c2015-12-16 18:16:21 -0800593 * Set the scaling mode to be used for this surfaces buffers
594 * @hide
595 */
596 void setScalingMode(@ScalingMode int scalingMode) {
597 synchronized (mLock) {
598 checkNotReleasedLocked();
599 int err = nativeSetScalingMode(mNativeObject, scalingMode);
600 if (err != 0) {
601 throw new IllegalArgumentException("Invalid scaling mode: " + scalingMode);
602 }
603 }
604 }
605
Robert Carr387838b2016-09-07 14:12:44 -0700606 void forceScopedDisconnect() {
607 synchronized (mLock) {
608 checkNotReleasedLocked();
609 int err = nativeForceScopedDisconnect(mNativeObject);
610 if (err != 0) {
611 throw new RuntimeException("Failed to disconnect Surface instance (bad object?)");
612 }
613 }
614 }
615
Robert Carrcd9a18c2015-12-16 18:16:21 -0800616 /**
Robert Carra35e5de2017-03-03 17:04:54 -0800617 * Transfer ownership of buffer and present it on the Surface.
618 * @hide
619 */
620 public void attachAndQueueBuffer(GraphicBuffer buffer) {
621 synchronized (mLock) {
622 checkNotReleasedLocked();
623 int err = nativeAttachAndQueueBuffer(mNativeObject, buffer);
624 if (err != 0) {
625 throw new RuntimeException(
626 "Failed to attach and queue buffer to Surface (bad object?)");
627 }
628 }
629 }
630
631 /**
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700632 * Returns whether or not this Surface is backed by a single-buffered SurfaceTexture
633 * @hide
634 */
635 public boolean isSingleBuffered() {
636 return mIsSingleBuffered;
637 }
638
639 /**
Romain Guy0bbf0b42017-07-20 08:57:07 -0700640 * <p>The shared buffer mode allows both the application and the surface compositor
641 * (SurfaceFlinger) to concurrently access this surface's buffer. While the
642 * application is still required to issue a present request
643 * (see {@link #unlockCanvasAndPost(Canvas)}) to the compositor when an update is required,
644 * the compositor may trigger an update at any time. Since the surface's buffer is shared
645 * between the application and the compositor, updates triggered by the compositor may
646 * cause visible tearing.</p>
647 *
648 * <p>The shared buffer mode can be used with
649 * {@link #setAutoRefreshEnabled(boolean) auto-refresh} to avoid the overhead of
650 * issuing present requests.</p>
651 *
652 * <p>If the application uses the shared buffer mode to reduce latency, it is
653 * recommended to use software rendering (see {@link #lockCanvas(Rect)} to ensure
654 * the graphics workloads are not affected by other applications and/or the system
655 * using the GPU. When using software rendering, the application should update the
656 * smallest possible region of the surface required.</p>
657 *
658 * <p class="note">The shared buffer mode might not be supported by the underlying
659 * hardware. Enabling shared buffer mode on hardware that does not support it will
660 * not yield an error but the application will not benefit from lower latency (and
661 * tearing will not be visible).</p>
662 *
663 * <p class="note">Depending on how many and what kind of surfaces are visible, the
664 * surface compositor may need to copy the shared buffer before it is displayed. When
665 * this happens, the latency benefits of shared buffer mode will be reduced.</p>
666 *
667 * @param enabled True to enable the shared buffer mode on this surface, false otherwise
668 *
669 * @see #isSharedBufferModeEnabled()
670 * @see #setAutoRefreshEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700671 *
672 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700673 */
674 public void setSharedBufferModeEnabled(boolean enabled) {
675 if (mIsSharedBufferModeEnabled != enabled) {
676 int error = nativeSetSharedBufferModeEnabled(mNativeObject, enabled);
677 if (error != 0) {
678 throw new RuntimeException(
679 "Failed to set shared buffer mode on Surface (bad object?)");
680 } else {
681 mIsSharedBufferModeEnabled = enabled;
682 }
683 }
684 }
685
686 /**
687 * @return True if shared buffer mode is enabled on this surface, false otherwise
688 *
689 * @see #setSharedBufferModeEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700690 *
691 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700692 */
693 public boolean isSharedBufferModeEnabled() {
694 return mIsSharedBufferModeEnabled;
695 }
696
697 /**
698 * <p>When auto-refresh is enabled, the surface compositor (SurfaceFlinger)
699 * automatically updates the display on a regular refresh cycle. The application
700 * can continue to issue present requests but it is not required. Enabling
701 * auto-refresh may result in visible tearing.</p>
702 *
703 * <p>Auto-refresh has no effect if the {@link #setSharedBufferModeEnabled(boolean)
704 * shared buffer mode} is not enabled.</p>
705 *
706 * <p>Because auto-refresh will trigger continuous updates of the display, it is
707 * recommended to turn it on only when necessary. For example, in a drawing/painting
708 * application auto-refresh should be enabled on finger/pen down and disabled on
709 * finger/pen up.</p>
710 *
711 * @param enabled True to enable auto-refresh on this surface, false otherwise
712 *
713 * @see #isAutoRefreshEnabled()
714 * @see #setSharedBufferModeEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700715 *
716 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700717 */
718 public void setAutoRefreshEnabled(boolean enabled) {
719 if (mIsAutoRefreshEnabled != enabled) {
720 int error = nativeSetAutoRefreshEnabled(mNativeObject, enabled);
721 if (error != 0) {
722 throw new RuntimeException("Failed to set auto refresh on Surface (bad object?)");
723 } else {
724 mIsAutoRefreshEnabled = enabled;
725 }
726 }
727 }
728
729 /**
730 * @return True if auto-refresh is enabled on this surface, false otherwise
Romain Guy010f0822017-08-16 09:43:07 -0700731 *
732 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700733 */
734 public boolean isAutoRefreshEnabled() {
735 return mIsAutoRefreshEnabled;
736 }
737
738 /**
Igor Murashkina86ab6402013-08-30 12:58:36 -0700739 * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or
740 * when a SurfaceTexture could not successfully be allocated.
Jeff Brown64a55af2012-08-26 02:47:39 -0700741 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700742 @SuppressWarnings("serial")
743 public static class OutOfResourcesException extends RuntimeException {
Jeff Brown64a55af2012-08-26 02:47:39 -0700744 public OutOfResourcesException() {
745 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700746 public OutOfResourcesException(String name) {
747 super(name);
748 }
749 }
750
751 /**
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700752 * Returns a human readable representation of a rotation.
753 *
754 * @param rotation The rotation.
755 * @return The rotation symbolic name.
Svetoslav Ganov545252f2012-12-10 18:29:24 -0800756 *
757 * @hide
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700758 */
759 public static String rotationToString(int rotation) {
760 switch (rotation) {
761 case Surface.ROTATION_0: {
762 return "ROTATION_0";
763 }
764 case Surface.ROTATION_90: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700765 return "ROTATION_90";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700766 }
767 case Surface.ROTATION_180: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700768 return "ROTATION_180";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700769 }
770 case Surface.ROTATION_270: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700771 return "ROTATION_270";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700772 }
773 default: {
Michael Wright19859762017-09-18 20:57:58 +0100774 return Integer.toString(rotation);
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700775 }
776 }
777 }
778
779 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700780 * A Canvas class that can handle the compatibility mode.
781 * This does two things differently.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700782 * <ul>
Mathias Agopianb9230662011-08-03 14:44:48 -0700783 * <li>Returns the width and height of the target metrics, rather than
784 * native. For example, the canvas returns 320x480 even if an app is running
785 * in WVGA high density.
786 * <li>Scales the matrix in setMatrix by the application scale, except if
787 * the matrix looks like obtained from getMatrix. This is a hack to handle
788 * the case that an application uses getMatrix to keep the original matrix,
789 * set matrix of its own, then set the original matrix back. There is no
790 * perfect solution that works for all cases, and there are a lot of cases
791 * that this model does not work, but we hope this works for many apps.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700792 * </ul>
793 */
Jeff Brown64a55af2012-08-26 02:47:39 -0700794 private final class CompatibleCanvas extends Canvas {
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700795 // A temp matrix to remember what an application obtained via {@link getMatrix}
796 private Matrix mOrigMatrix = null;
797
798 @Override
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700799 public void setMatrix(Matrix matrix) {
800 if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
801 // don't scale the matrix if it's not compatibility mode, or
802 // the matrix was obtained from getMatrix.
803 super.setMatrix(matrix);
804 } else {
805 Matrix m = new Matrix(mCompatibleMatrix);
806 m.preConcat(matrix);
807 super.setMatrix(m);
808 }
809 }
810
Romain Guy8b5aa482013-02-28 18:13:54 -0800811 @SuppressWarnings("deprecation")
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700812 @Override
813 public void getMatrix(Matrix m) {
814 super.getMatrix(m);
815 if (mOrigMatrix == null) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700816 mOrigMatrix = new Matrix();
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700817 }
818 mOrigMatrix.set(m);
819 }
Romain Guyd10cd572010-10-10 13:33:22 -0700820 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700821
822 private final class HwuiContext {
823 private final RenderNode mRenderNode;
824 private long mHwuiRenderer;
Chris Craikf6829a02015-03-10 10:28:59 -0700825 private DisplayListCanvas mCanvas;
John Reckbb2d0cc2014-10-21 10:09:36 -0700826
827 HwuiContext() {
828 mRenderNode = RenderNode.create("HwuiCanvas", null);
829 mRenderNode.setClipToBounds(false);
830 mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject);
831 }
832
John Reckb35c9602014-11-13 16:15:08 -0800833 Canvas lockCanvas(int width, int height) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700834 if (mCanvas != null) {
835 throw new IllegalStateException("Surface was already locked!");
836 }
John Reckb35c9602014-11-13 16:15:08 -0800837 mCanvas = mRenderNode.start(width, height);
John Reckbb2d0cc2014-10-21 10:09:36 -0700838 return mCanvas;
839 }
840
841 void unlockAndPost(Canvas canvas) {
842 if (canvas != mCanvas) {
843 throw new IllegalArgumentException("canvas object must be the same instance that "
844 + "was previously returned by lockCanvas");
845 }
846 mRenderNode.end(mCanvas);
847 mCanvas = null;
848 nHwuiDraw(mHwuiRenderer);
849 }
850
851 void updateSurface() {
852 nHwuiSetSurface(mHwuiRenderer, mNativeObject);
853 }
854
855 void destroy() {
856 if (mHwuiRenderer != 0) {
857 nHwuiDestroy(mHwuiRenderer);
858 mHwuiRenderer = 0;
859 }
860 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700861 }
862
863 private static native long nHwuiCreate(long rootNode, long surface);
864 private static native void nHwuiSetSurface(long renderer, long surface);
865 private static native void nHwuiDraw(long renderer);
866 private static native void nHwuiDestroy(long renderer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867}