blob: ef50fdc5eb4f9903b61bdb62da2851fb36598535 [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;
22import android.graphics.Matrix;
23import android.graphics.Rect;
Jeff Brown0b722fe2012-08-24 22:40:14 -070024import android.graphics.SurfaceTexture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.os.Parcel;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080026import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.util.Log;
Tor Norbyed9273d62013-05-30 15:59:53 -070028
29import java.lang.annotation.Retention;
30import java.lang.annotation.RetentionPolicy;
31
Mathias Agopian3866f0d2013-02-11 22:08:48 -080032import dalvik.system.CloseGuard;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033
34/**
Glenn Kasten334031c2010-11-09 21:54:38 -080035 * Handle onto a raw buffer that is being managed by the screen compositor.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036 */
37public class Surface implements Parcelable {
Jeff Brown64a55af2012-08-26 02:47:39 -070038 private static final String TAG = "Surface";
Mathias Agopianb9230662011-08-03 14:44:48 -070039
Ashok Bhat36bef0b2014-01-20 20:08:01 +000040 private static native long nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
Mathias Agopian29479eb2013-02-14 14:36:04 -080041 throws OutOfResourcesException;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000042 private static native long nativeCreateFromSurfaceControl(long surfaceControlNativeObject);
Mathias Agopian52800612013-02-14 17:11:20 -080043
Ashok Bhat36bef0b2014-01-20 20:08:01 +000044 private static native long nativeLockCanvas(long nativeObject, Canvas canvas, Rect dirty)
Jeff Brownfc0ebd72013-04-30 16:33:00 -070045 throws OutOfResourcesException;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000046 private static native void nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas);
Mathias Agopian29479eb2013-02-14 14:36:04 -080047
Ashok Bhat36bef0b2014-01-20 20:08:01 +000048 private static native void nativeRelease(long nativeObject);
49 private static native boolean nativeIsValid(long nativeObject);
50 private static native boolean nativeIsConsumerRunningBehind(long nativeObject);
51 private static native long nativeReadFromParcel(long nativeObject, Parcel source);
52 private static native void nativeWriteToParcel(long nativeObject, Parcel dest);
Mathias Agopian29479eb2013-02-14 14:36:04 -080053
Dan Stoza5795d642014-06-20 13:01:36 -070054 private static native void nativeAllocateBuffers(long nativeObject);
55
John Reckb35c9602014-11-13 16:15:08 -080056 private static native int nativeGetWidth(long nativeObject);
57 private static native int nativeGetHeight(long nativeObject);
58
Rob Carr64e516f2015-10-29 00:20:45 +000059 private static native long nativeGetNextFrameNumber(long nativeObject);
Robert Carrcd9a18c2015-12-16 18:16:21 -080060 private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
Rob Carr64e516f2015-10-29 00:20:45 +000061
Jeff Brown64a55af2012-08-26 02:47:39 -070062 public static final Parcelable.Creator<Surface> CREATOR =
63 new Parcelable.Creator<Surface>() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -070064 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -070065 public Surface createFromParcel(Parcel source) {
66 try {
67 Surface s = new Surface();
68 s.readFromParcel(source);
69 return s;
70 } catch (Exception e) {
71 Log.e(TAG, "Exception creating surface from parcel", e);
72 return null;
73 }
Kevin Hesterb85c9332012-03-08 17:06:56 -080074 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -070075
76 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -070077 public Surface[] newArray(int size) {
78 return new Surface[size];
79 }
80 };
Kevin Hesterb85c9332012-03-08 17:06:56 -080081
Jeff Brown64a55af2012-08-26 02:47:39 -070082 private final CloseGuard mCloseGuard = CloseGuard.get();
Jeff Brownfc0ebd72013-04-30 16:33:00 -070083
84 // Guarded state.
85 final Object mLock = new Object(); // protects the native state
Jeff Brown64a55af2012-08-26 02:47:39 -070086 private String mName;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000087 long mNativeObject; // package scope only for SurfaceControl access
88 private long mLockedObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -070089 private int mGenerationId; // incremented each time mNativeObject changes
Jeff Brown64a55af2012-08-26 02:47:39 -070090 private final Canvas mCanvas = new CompatibleCanvas();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091
Mitsuru Oshima240f8a72009-07-22 20:39:14 -070092 // A matrix to scale the matrix set by application. This is set to null for
93 // non compatibility mode.
94 private Matrix mCompatibleMatrix;
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -070095
John Reckbb2d0cc2014-10-21 10:09:36 -070096 private HwuiContext mHwuiContext;
97
Tor Norbyed9273d62013-05-30 15:59:53 -070098 /** @hide */
Robert Carrcd9a18c2015-12-16 18:16:21 -080099 @Retention(RetentionPolicy.SOURCE)
100 @IntDef({SCALING_MODE_FREEZE, SCALING_MODE_SCALE_TO_WINDOW,
101 SCALING_MODE_SCALE_CROP, SCALING_MODE_NO_SCALE_CROP})
102 public @interface ScalingMode {}
103 // From system/window.h
104 /** @hide */
105 static final int SCALING_MODE_FREEZE = 0;
106 /** @hide */
107 static final int SCALING_MODE_SCALE_TO_WINDOW = 1;
108 /** @hide */
109 static final int SCALING_MODE_SCALE_CROP = 2;
110 /** @hide */
111 static final int SCALING_MODE_NO_SCALE_CROP = 3;
112
113 /** @hide */
Tor Norbyed9273d62013-05-30 15:59:53 -0700114 @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
115 @Retention(RetentionPolicy.SOURCE)
116 public @interface Rotation {}
117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 /**
Mathias Agopian29479eb2013-02-14 14:36:04 -0800119 * Rotation constant: 0 degree rotation (natural orientation)
120 */
121 public static final int ROTATION_0 = 0;
122
123 /**
124 * Rotation constant: 90 degree rotation.
125 */
126 public static final int ROTATION_90 = 1;
127
128 /**
129 * Rotation constant: 180 degree rotation.
130 */
131 public static final int ROTATION_180 = 2;
132
133 /**
134 * Rotation constant: 270 degree rotation.
135 */
136 public static final int ROTATION_270 = 3;
137
Mathias Agopian29479eb2013-02-14 14:36:04 -0800138 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700139 * Create an empty surface, which will later be filled in by readFromParcel().
Mathias Agopianb9230662011-08-03 14:44:48 -0700140 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 */
142 public Surface() {
Jeff Brown64a55af2012-08-26 02:47:39 -0700143 }
144
145 /**
146 * Create Surface from a {@link SurfaceTexture}.
147 *
148 * Images drawn to the Surface will be made available to the {@link
149 * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
150 * SurfaceTexture#updateTexImage}.
151 *
152 * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
153 * Surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700154 * @throws OutOfResourcesException if the surface could not be created.
Jeff Brown64a55af2012-08-26 02:47:39 -0700155 */
156 public Surface(SurfaceTexture surfaceTexture) {
157 if (surfaceTexture == null) {
158 throw new IllegalArgumentException("surfaceTexture must not be null");
159 }
160
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700161 synchronized (mLock) {
162 mName = surfaceTexture.toString();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700163 setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
Jeff Brown64a55af2012-08-26 02:47:39 -0700164 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700165 }
166
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700167 /* called from android_view_Surface_createFromIGraphicBufferProducer() */
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000168 private Surface(long nativeObject) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700169 synchronized (mLock) {
170 setNativeObjectLocked(nativeObject);
171 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800172 }
173
Jeff Brown64a55af2012-08-26 02:47:39 -0700174 @Override
175 protected void finalize() throws Throwable {
176 try {
177 if (mCloseGuard != null) {
178 mCloseGuard.warnIfOpen();
179 }
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700180 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700181 } finally {
182 super.finalize();
183 }
184 }
185
186 /**
187 * Release the local reference to the server-side surface.
188 * Always call release() when you're done with a Surface.
189 * This will make the surface invalid.
190 */
191 public void release() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700192 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700193 if (mNativeObject != 0) {
194 nativeRelease(mNativeObject);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700195 setNativeObjectLocked(0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700196 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700197 if (mHwuiContext != null) {
198 mHwuiContext.destroy();
199 mHwuiContext = null;
200 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800201 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700202 }
203
204 /**
205 * Free all server-side state associated with this surface and
206 * release this object's reference. This method can only be
207 * called from the process that created the service.
208 * @hide
209 */
210 public void destroy() {
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700211 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700212 }
213
214 /**
215 * Returns true if this object holds a valid surface.
216 *
217 * @return True if it holds a physical surface, so lockCanvas() will succeed.
218 * Otherwise returns false.
219 */
220 public boolean isValid() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700221 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700222 if (mNativeObject == 0) return false;
223 return nativeIsValid(mNativeObject);
224 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700225 }
226
227 /**
228 * Gets the generation number of this surface, incremented each time
229 * the native surface contained within this object changes.
230 *
231 * @return The current generation number.
232 * @hide
233 */
234 public int getGenerationId() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700235 synchronized (mLock) {
236 return mGenerationId;
237 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700238 }
239
240 /**
Rob Carr64e516f2015-10-29 00:20:45 +0000241 * Returns the next frame number which will be dequeued for rendering.
242 * Intended for use with SurfaceFlinger's deferred transactions API.
243 *
244 * @hide
245 */
246 public long getNextFrameNumber() {
247 synchronized (mLock) {
248 return nativeGetNextFrameNumber(mNativeObject);
249 }
250 }
251
252 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700253 * Returns true if the consumer of this Surface is running behind the producer.
254 *
255 * @return True if the consumer is more than one buffer ahead of the producer.
256 * @hide
257 */
258 public boolean isConsumerRunningBehind() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700259 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700260 checkNotReleasedLocked();
261 return nativeIsConsumerRunningBehind(mNativeObject);
262 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700263 }
264
265 /**
266 * Gets a {@link Canvas} for drawing into this surface.
267 *
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700268 * After drawing into the provided {@link Canvas}, the caller must
Jeff Brown64a55af2012-08-26 02:47:39 -0700269 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
270 *
Mathias Agopian30d7ab92013-02-14 15:38:40 -0800271 * @param inOutDirty A rectangle that represents the dirty region that the caller wants
Jeff Brown64a55af2012-08-26 02:47:39 -0700272 * to redraw. This function may choose to expand the dirty rectangle if for example
273 * the surface has been resized or if the previous contents of the surface were
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700274 * not available. The caller must redraw the entire dirty region as represented
275 * by the contents of the inOutDirty rectangle upon return from this function.
Jeff Brown64a55af2012-08-26 02:47:39 -0700276 * The caller may also pass <code>null</code> instead, in the case where the
277 * entire surface should be redrawn.
278 * @return A canvas for drawing into the surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700279 *
280 * @throws IllegalArgumentException If the inOutDirty rectangle is not valid.
281 * @throws OutOfResourcesException If the canvas cannot be locked.
Jeff Brown64a55af2012-08-26 02:47:39 -0700282 */
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800283 public Canvas lockCanvas(Rect inOutDirty)
Igor Murashkina86ab6402013-08-30 12:58:36 -0700284 throws Surface.OutOfResourcesException, IllegalArgumentException {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700285 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700286 checkNotReleasedLocked();
Andy McFaddened55c8d2013-08-20 10:05:51 -0700287 if (mLockedObject != 0) {
288 // Ideally, nativeLockCanvas() would throw in this situation and prevent the
289 // double-lock, but that won't happen if mNativeObject was updated. We can't
290 // abandon the old mLockedObject because it might still be in use, so instead
291 // we just refuse to re-lock the Surface.
Jesse Halld7e55962014-10-13 11:01:15 -0700292 throw new IllegalArgumentException("Surface was already locked");
Andy McFaddened55c8d2013-08-20 10:05:51 -0700293 }
294 mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700295 return mCanvas;
Mathias Agopian7c116b52013-03-18 20:27:02 -0700296 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700297 }
298
299 /**
300 * Posts the new contents of the {@link Canvas} to the surface and
301 * releases the {@link Canvas}.
302 *
303 * @param canvas The canvas previously obtained from {@link #lockCanvas}.
304 */
305 public void unlockCanvasAndPost(Canvas canvas) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700306 synchronized (mLock) {
307 checkNotReleasedLocked();
308
309 if (mHwuiContext != null) {
310 mHwuiContext.unlockAndPost(canvas);
311 } else {
312 unlockSwCanvasAndPost(canvas);
313 }
314 }
315 }
316
317 private void unlockSwCanvasAndPost(Canvas canvas) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700318 if (canvas != mCanvas) {
319 throw new IllegalArgumentException("canvas object must be the same instance that "
320 + "was previously returned by lockCanvas");
321 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700322 if (mNativeObject != mLockedObject) {
323 Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
324 Long.toHexString(mNativeObject) + ") != mLockedObject (0x" +
325 Long.toHexString(mLockedObject) +")");
326 }
327 if (mLockedObject == 0) {
328 throw new IllegalStateException("Surface was not locked");
329 }
330 try {
331 nativeUnlockCanvasAndPost(mLockedObject, canvas);
332 } finally {
333 nativeRelease(mLockedObject);
334 mLockedObject = 0;
335 }
336 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700337
John Reckbb2d0cc2014-10-21 10:09:36 -0700338 /**
339 * Gets a {@link Canvas} for drawing into this surface.
340 *
341 * After drawing into the provided {@link Canvas}, the caller must
342 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
343 *
344 * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated
345 * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
346 * unsupported drawing operations</a> for a list of what is and isn't
John Reck43a53282014-10-23 13:56:03 -0700347 * supported in a hardware-accelerated canvas. It is also required to
348 * fully cover the surface every time {@link #lockHardwareCanvas()} is
349 * called as the buffer is not preserved between frames. Partial updates
350 * are not supported.
John Reckbb2d0cc2014-10-21 10:09:36 -0700351 *
352 * @return A canvas for drawing into the surface.
353 *
354 * @throws IllegalStateException If the canvas cannot be locked.
355 */
356 public Canvas lockHardwareCanvas() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700357 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700358 checkNotReleasedLocked();
John Reckbb2d0cc2014-10-21 10:09:36 -0700359 if (mHwuiContext == null) {
360 mHwuiContext = new HwuiContext();
Andy McFaddened55c8d2013-08-20 10:05:51 -0700361 }
John Reckb35c9602014-11-13 16:15:08 -0800362 return mHwuiContext.lockCanvas(
363 nativeGetWidth(mNativeObject),
364 nativeGetHeight(mNativeObject));
Mathias Agopian7c116b52013-03-18 20:27:02 -0700365 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700366 }
367
Andy McFaddened55c8d2013-08-20 10:05:51 -0700368 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700369 * @deprecated This API has been removed and is not supported. Do not use.
370 */
371 @Deprecated
372 public void unlockCanvas(Canvas canvas) {
373 throw new UnsupportedOperationException();
374 }
375
376 /**
377 * Sets the translator used to scale canvas's width/height in compatibility
378 * mode.
379 */
380 void setCompatibilityTranslator(Translator translator) {
381 if (translator != null) {
382 float appScale = translator.applicationScale;
383 mCompatibleMatrix = new Matrix();
384 mCompatibleMatrix.setScale(appScale, appScale);
385 }
386 }
387
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700388 /**
Mathias Agopianb9230662011-08-03 14:44:48 -0700389 * Copy another surface to this one. This surface now holds a reference
390 * to the same data as the original surface, and is -not- the owner.
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800391 * This is for use by the window manager when returning a window surface
392 * back from a client, converting it from the representation being managed
393 * by the window manager to the representation the client uses to draw
394 * in to it.
Mathias Agopianb9230662011-08-03 14:44:48 -0700395 * @hide
396 */
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800397 public void copyFrom(SurfaceControl other) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700398 if (other == null) {
399 throw new IllegalArgumentException("other must not be null");
400 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700401
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000402 long surfaceControlPtr = other.mNativeObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700403 if (surfaceControlPtr == 0) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800404 throw new NullPointerException(
405 "SurfaceControl native object is null. Are you using a released SurfaceControl?");
Jeff Brown64a55af2012-08-26 02:47:39 -0700406 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000407 long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700408
409 synchronized (mLock) {
410 if (mNativeObject != 0) {
411 nativeRelease(mNativeObject);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700412 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700413 setNativeObjectLocked(newNativeObject);
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700414 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700415 }
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800416
417 /**
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700418 * This is intended to be used by {@link SurfaceView#updateWindow} only.
Mathias Agopian7c116b52013-03-18 20:27:02 -0700419 * @param other access is not thread safe
420 * @hide
421 * @deprecated
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800422 */
Mathias Agopian7c116b52013-03-18 20:27:02 -0700423 @Deprecated
Jeff Brown64a55af2012-08-26 02:47:39 -0700424 public void transferFrom(Surface other) {
425 if (other == null) {
426 throw new IllegalArgumentException("other must not be null");
427 }
428 if (other != this) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000429 final long newPtr;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700430 synchronized (other.mLock) {
431 newPtr = other.mNativeObject;
432 other.setNativeObjectLocked(0);
433 }
434
435 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700436 if (mNativeObject != 0) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700437 nativeRelease(mNativeObject);
438 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700439 setNativeObjectLocked(newPtr);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800440 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700441 }
Mathias Agopianb9230662011-08-03 14:44:48 -0700442 }
443
Jeff Brown64a55af2012-08-26 02:47:39 -0700444 @Override
445 public int describeContents() {
446 return 0;
447 }
448
449 public void readFromParcel(Parcel source) {
450 if (source == null) {
451 throw new IllegalArgumentException("source must not be null");
452 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700453
454 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700455 // nativeReadFromParcel() will either return mNativeObject, or
456 // create a new native Surface and return it after reducing
457 // the reference count on mNativeObject. Either way, it is
458 // not necessary to call nativeRelease() here.
Mathias Agopian7c116b52013-03-18 20:27:02 -0700459 mName = source.readString();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700460 setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700461 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700462 }
463
464 @Override
465 public void writeToParcel(Parcel dest, int flags) {
466 if (dest == null) {
467 throw new IllegalArgumentException("dest must not be null");
468 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700469 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700470 dest.writeString(mName);
471 nativeWriteToParcel(mNativeObject, dest);
472 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700473 if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
474 release();
475 }
476 }
477
478 @Override
479 public String toString() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700480 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700481 return "Surface(name=" + mName + ")/@0x" +
482 Integer.toHexString(System.identityHashCode(this));
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700483 }
484 }
485
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000486 private void setNativeObjectLocked(long ptr) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700487 if (mNativeObject != ptr) {
488 if (mNativeObject == 0 && ptr != 0) {
489 mCloseGuard.open("release");
490 } else if (mNativeObject != 0 && ptr == 0) {
491 mCloseGuard.close();
492 }
493 mNativeObject = ptr;
494 mGenerationId += 1;
John Reckbb2d0cc2014-10-21 10:09:36 -0700495 if (mHwuiContext != null) {
496 mHwuiContext.updateSurface();
497 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700498 }
499 }
500
501 private void checkNotReleasedLocked() {
502 if (mNativeObject == 0) {
503 throw new IllegalStateException("Surface has already been released.");
504 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700505 }
506
Mathias Agopianc14bacf2012-04-23 18:23:08 -0700507 /**
Dan Stoza5795d642014-06-20 13:01:36 -0700508 * Allocate buffers ahead of time to avoid allocation delays during rendering
509 * @hide
510 */
511 public void allocateBuffers() {
512 synchronized (mLock) {
513 checkNotReleasedLocked();
514 nativeAllocateBuffers(mNativeObject);
515 }
516 }
517
518 /**
Robert Carrcd9a18c2015-12-16 18:16:21 -0800519 * Set the scaling mode to be used for this surfaces buffers
520 * @hide
521 */
522 void setScalingMode(@ScalingMode int scalingMode) {
523 synchronized (mLock) {
524 checkNotReleasedLocked();
525 int err = nativeSetScalingMode(mNativeObject, scalingMode);
526 if (err != 0) {
527 throw new IllegalArgumentException("Invalid scaling mode: " + scalingMode);
528 }
529 }
530 }
531
532 /**
Igor Murashkina86ab6402013-08-30 12:58:36 -0700533 * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or
534 * when a SurfaceTexture could not successfully be allocated.
Jeff Brown64a55af2012-08-26 02:47:39 -0700535 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700536 @SuppressWarnings("serial")
537 public static class OutOfResourcesException extends RuntimeException {
Jeff Brown64a55af2012-08-26 02:47:39 -0700538 public OutOfResourcesException() {
539 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700540 public OutOfResourcesException(String name) {
541 super(name);
542 }
543 }
544
545 /**
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700546 * Returns a human readable representation of a rotation.
547 *
548 * @param rotation The rotation.
549 * @return The rotation symbolic name.
Svetoslav Ganov545252f2012-12-10 18:29:24 -0800550 *
551 * @hide
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700552 */
553 public static String rotationToString(int rotation) {
554 switch (rotation) {
555 case Surface.ROTATION_0: {
556 return "ROTATION_0";
557 }
558 case Surface.ROTATION_90: {
559 return "ROATATION_90";
560 }
561 case Surface.ROTATION_180: {
562 return "ROATATION_180";
563 }
564 case Surface.ROTATION_270: {
565 return "ROATATION_270";
566 }
567 default: {
568 throw new IllegalArgumentException("Invalid rotation: " + rotation);
569 }
570 }
571 }
572
573 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700574 * A Canvas class that can handle the compatibility mode.
575 * This does two things differently.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700576 * <ul>
Mathias Agopianb9230662011-08-03 14:44:48 -0700577 * <li>Returns the width and height of the target metrics, rather than
578 * native. For example, the canvas returns 320x480 even if an app is running
579 * in WVGA high density.
580 * <li>Scales the matrix in setMatrix by the application scale, except if
581 * the matrix looks like obtained from getMatrix. This is a hack to handle
582 * the case that an application uses getMatrix to keep the original matrix,
583 * set matrix of its own, then set the original matrix back. There is no
584 * perfect solution that works for all cases, and there are a lot of cases
585 * that this model does not work, but we hope this works for many apps.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700586 * </ul>
587 */
Jeff Brown64a55af2012-08-26 02:47:39 -0700588 private final class CompatibleCanvas extends Canvas {
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700589 // A temp matrix to remember what an application obtained via {@link getMatrix}
590 private Matrix mOrigMatrix = null;
591
592 @Override
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700593 public void setMatrix(Matrix matrix) {
594 if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
595 // don't scale the matrix if it's not compatibility mode, or
596 // the matrix was obtained from getMatrix.
597 super.setMatrix(matrix);
598 } else {
599 Matrix m = new Matrix(mCompatibleMatrix);
600 m.preConcat(matrix);
601 super.setMatrix(m);
602 }
603 }
604
Romain Guy8b5aa482013-02-28 18:13:54 -0800605 @SuppressWarnings("deprecation")
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700606 @Override
607 public void getMatrix(Matrix m) {
608 super.getMatrix(m);
609 if (mOrigMatrix == null) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700610 mOrigMatrix = new Matrix();
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700611 }
612 mOrigMatrix.set(m);
613 }
Romain Guyd10cd572010-10-10 13:33:22 -0700614 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700615
616 private final class HwuiContext {
617 private final RenderNode mRenderNode;
618 private long mHwuiRenderer;
Chris Craikf6829a02015-03-10 10:28:59 -0700619 private DisplayListCanvas mCanvas;
John Reckbb2d0cc2014-10-21 10:09:36 -0700620
621 HwuiContext() {
622 mRenderNode = RenderNode.create("HwuiCanvas", null);
623 mRenderNode.setClipToBounds(false);
624 mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject);
625 }
626
John Reckb35c9602014-11-13 16:15:08 -0800627 Canvas lockCanvas(int width, int height) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700628 if (mCanvas != null) {
629 throw new IllegalStateException("Surface was already locked!");
630 }
John Reckb35c9602014-11-13 16:15:08 -0800631 mCanvas = mRenderNode.start(width, height);
John Reckbb2d0cc2014-10-21 10:09:36 -0700632 return mCanvas;
633 }
634
635 void unlockAndPost(Canvas canvas) {
636 if (canvas != mCanvas) {
637 throw new IllegalArgumentException("canvas object must be the same instance that "
638 + "was previously returned by lockCanvas");
639 }
640 mRenderNode.end(mCanvas);
641 mCanvas = null;
642 nHwuiDraw(mHwuiRenderer);
643 }
644
645 void updateSurface() {
646 nHwuiSetSurface(mHwuiRenderer, mNativeObject);
647 }
648
649 void destroy() {
650 if (mHwuiRenderer != 0) {
651 nHwuiDestroy(mHwuiRenderer);
652 mHwuiRenderer = 0;
653 }
654 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700655 }
656
657 private static native long nHwuiCreate(long rootNode, long surface);
658 private static native void nHwuiSetSurface(long renderer, long surface);
659 private static native void nHwuiDraw(long renderer);
660 private static native void nHwuiDestroy(long renderer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661}