blob: 3770b8a31922200f1d49ca9d8744aab652fca838 [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
Jeff Brown64a55af2012-08-26 02:47:39 -070056 public static final Parcelable.Creator<Surface> CREATOR =
57 new Parcelable.Creator<Surface>() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -070058 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -070059 public Surface createFromParcel(Parcel source) {
60 try {
61 Surface s = new Surface();
62 s.readFromParcel(source);
63 return s;
64 } catch (Exception e) {
65 Log.e(TAG, "Exception creating surface from parcel", e);
66 return null;
67 }
Kevin Hesterb85c9332012-03-08 17:06:56 -080068 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -070069
70 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -070071 public Surface[] newArray(int size) {
72 return new Surface[size];
73 }
74 };
Kevin Hesterb85c9332012-03-08 17:06:56 -080075
Jeff Brown64a55af2012-08-26 02:47:39 -070076 private final CloseGuard mCloseGuard = CloseGuard.get();
Jeff Brownfc0ebd72013-04-30 16:33:00 -070077
78 // Guarded state.
79 final Object mLock = new Object(); // protects the native state
Jeff Brown64a55af2012-08-26 02:47:39 -070080 private String mName;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000081 long mNativeObject; // package scope only for SurfaceControl access
82 private long mLockedObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -070083 private int mGenerationId; // incremented each time mNativeObject changes
Jeff Brown64a55af2012-08-26 02:47:39 -070084 private final Canvas mCanvas = new CompatibleCanvas();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085
Mitsuru Oshima240f8a72009-07-22 20:39:14 -070086 // A matrix to scale the matrix set by application. This is set to null for
87 // non compatibility mode.
88 private Matrix mCompatibleMatrix;
Mitsuru Oshima38ed7d72009-07-21 14:39:34 -070089
Tor Norbyed9273d62013-05-30 15:59:53 -070090 /** @hide */
91 @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
92 @Retention(RetentionPolicy.SOURCE)
93 public @interface Rotation {}
94
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095 /**
Mathias Agopian29479eb2013-02-14 14:36:04 -080096 * Rotation constant: 0 degree rotation (natural orientation)
97 */
98 public static final int ROTATION_0 = 0;
99
100 /**
101 * Rotation constant: 90 degree rotation.
102 */
103 public static final int ROTATION_90 = 1;
104
105 /**
106 * Rotation constant: 180 degree rotation.
107 */
108 public static final int ROTATION_180 = 2;
109
110 /**
111 * Rotation constant: 270 degree rotation.
112 */
113 public static final int ROTATION_270 = 3;
114
Mathias Agopian29479eb2013-02-14 14:36:04 -0800115 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700116 * Create an empty surface, which will later be filled in by readFromParcel().
Mathias Agopianb9230662011-08-03 14:44:48 -0700117 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 */
119 public Surface() {
Jeff Brown64a55af2012-08-26 02:47:39 -0700120 }
121
122 /**
123 * Create Surface from a {@link SurfaceTexture}.
124 *
125 * Images drawn to the Surface will be made available to the {@link
126 * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
127 * SurfaceTexture#updateTexImage}.
128 *
129 * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
130 * Surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700131 * @throws OutOfResourcesException if the surface could not be created.
Jeff Brown64a55af2012-08-26 02:47:39 -0700132 */
133 public Surface(SurfaceTexture surfaceTexture) {
134 if (surfaceTexture == null) {
135 throw new IllegalArgumentException("surfaceTexture must not be null");
136 }
137
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700138 synchronized (mLock) {
139 mName = surfaceTexture.toString();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700140 setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
Jeff Brown64a55af2012-08-26 02:47:39 -0700141 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700142 }
143
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700144 /* called from android_view_Surface_createFromIGraphicBufferProducer() */
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000145 private Surface(long nativeObject) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700146 synchronized (mLock) {
147 setNativeObjectLocked(nativeObject);
148 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800149 }
150
Jeff Brown64a55af2012-08-26 02:47:39 -0700151 @Override
152 protected void finalize() throws Throwable {
153 try {
154 if (mCloseGuard != null) {
155 mCloseGuard.warnIfOpen();
156 }
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700157 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700158 } finally {
159 super.finalize();
160 }
161 }
162
163 /**
164 * Release the local reference to the server-side surface.
165 * Always call release() when you're done with a Surface.
166 * This will make the surface invalid.
167 */
168 public void release() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700169 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700170 if (mNativeObject != 0) {
171 nativeRelease(mNativeObject);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700172 setNativeObjectLocked(0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700173 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800174 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700175 }
176
177 /**
178 * Free all server-side state associated with this surface and
179 * release this object's reference. This method can only be
180 * called from the process that created the service.
181 * @hide
182 */
183 public void destroy() {
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700184 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700185 }
186
187 /**
188 * Returns true if this object holds a valid surface.
189 *
190 * @return True if it holds a physical surface, so lockCanvas() will succeed.
191 * Otherwise returns false.
192 */
193 public boolean isValid() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700194 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700195 if (mNativeObject == 0) return false;
196 return nativeIsValid(mNativeObject);
197 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700198 }
199
200 /**
201 * Gets the generation number of this surface, incremented each time
202 * the native surface contained within this object changes.
203 *
204 * @return The current generation number.
205 * @hide
206 */
207 public int getGenerationId() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700208 synchronized (mLock) {
209 return mGenerationId;
210 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700211 }
212
213 /**
214 * Returns true if the consumer of this Surface is running behind the producer.
215 *
216 * @return True if the consumer is more than one buffer ahead of the producer.
217 * @hide
218 */
219 public boolean isConsumerRunningBehind() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700220 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700221 checkNotReleasedLocked();
222 return nativeIsConsumerRunningBehind(mNativeObject);
223 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700224 }
225
226 /**
227 * Gets a {@link Canvas} for drawing into this surface.
228 *
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700229 * After drawing into the provided {@link Canvas}, the caller must
Jeff Brown64a55af2012-08-26 02:47:39 -0700230 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
231 *
Mathias Agopian30d7ab92013-02-14 15:38:40 -0800232 * @param inOutDirty A rectangle that represents the dirty region that the caller wants
Jeff Brown64a55af2012-08-26 02:47:39 -0700233 * to redraw. This function may choose to expand the dirty rectangle if for example
234 * the surface has been resized or if the previous contents of the surface were
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700235 * not available. The caller must redraw the entire dirty region as represented
236 * by the contents of the inOutDirty rectangle upon return from this function.
Jeff Brown64a55af2012-08-26 02:47:39 -0700237 * The caller may also pass <code>null</code> instead, in the case where the
238 * entire surface should be redrawn.
239 * @return A canvas for drawing into the surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700240 *
241 * @throws IllegalArgumentException If the inOutDirty rectangle is not valid.
242 * @throws OutOfResourcesException If the canvas cannot be locked.
Jeff Brown64a55af2012-08-26 02:47:39 -0700243 */
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800244 public Canvas lockCanvas(Rect inOutDirty)
Igor Murashkina86ab6402013-08-30 12:58:36 -0700245 throws Surface.OutOfResourcesException, IllegalArgumentException {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700246 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700247 checkNotReleasedLocked();
Andy McFaddened55c8d2013-08-20 10:05:51 -0700248 if (mLockedObject != 0) {
249 // Ideally, nativeLockCanvas() would throw in this situation and prevent the
250 // double-lock, but that won't happen if mNativeObject was updated. We can't
251 // abandon the old mLockedObject because it might still be in use, so instead
252 // we just refuse to re-lock the Surface.
Jesse Halld7e55962014-10-13 11:01:15 -0700253 throw new IllegalArgumentException("Surface was already locked");
Andy McFaddened55c8d2013-08-20 10:05:51 -0700254 }
255 mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700256 return mCanvas;
Mathias Agopian7c116b52013-03-18 20:27:02 -0700257 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700258 }
259
260 /**
261 * Posts the new contents of the {@link Canvas} to the surface and
262 * releases the {@link Canvas}.
263 *
264 * @param canvas The canvas previously obtained from {@link #lockCanvas}.
265 */
266 public void unlockCanvasAndPost(Canvas canvas) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700267 if (canvas != mCanvas) {
268 throw new IllegalArgumentException("canvas object must be the same instance that "
269 + "was previously returned by lockCanvas");
270 }
271
272 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700273 checkNotReleasedLocked();
Andy McFaddened55c8d2013-08-20 10:05:51 -0700274 if (mNativeObject != mLockedObject) {
275 Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000276 Long.toHexString(mNativeObject) + ") != mLockedObject (0x" +
277 Long.toHexString(mLockedObject) +")");
Andy McFaddened55c8d2013-08-20 10:05:51 -0700278 }
279 if (mLockedObject == 0) {
Igor Murashkina86ab6402013-08-30 12:58:36 -0700280 throw new IllegalStateException("Surface was not locked");
Andy McFaddened55c8d2013-08-20 10:05:51 -0700281 }
Jesse Halld7e55962014-10-13 11:01:15 -0700282 try {
283 nativeUnlockCanvasAndPost(mLockedObject, canvas);
284 } finally {
285 nativeRelease(mLockedObject);
286 mLockedObject = 0;
287 }
Mathias Agopian7c116b52013-03-18 20:27:02 -0700288 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700289 }
290
Andy McFaddened55c8d2013-08-20 10:05:51 -0700291 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700292 * @deprecated This API has been removed and is not supported. Do not use.
293 */
294 @Deprecated
295 public void unlockCanvas(Canvas canvas) {
296 throw new UnsupportedOperationException();
297 }
298
299 /**
300 * Sets the translator used to scale canvas's width/height in compatibility
301 * mode.
302 */
303 void setCompatibilityTranslator(Translator translator) {
304 if (translator != null) {
305 float appScale = translator.applicationScale;
306 mCompatibleMatrix = new Matrix();
307 mCompatibleMatrix.setScale(appScale, appScale);
308 }
309 }
310
Mitsuru Oshima38ed7d72009-07-21 14:39:34 -0700311 /**
Mathias Agopianb9230662011-08-03 14:44:48 -0700312 * Copy another surface to this one. This surface now holds a reference
313 * to the same data as the original surface, and is -not- the owner.
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800314 * This is for use by the window manager when returning a window surface
315 * back from a client, converting it from the representation being managed
316 * by the window manager to the representation the client uses to draw
317 * in to it.
Mathias Agopianb9230662011-08-03 14:44:48 -0700318 * @hide
319 */
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800320 public void copyFrom(SurfaceControl other) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700321 if (other == null) {
322 throw new IllegalArgumentException("other must not be null");
323 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700324
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000325 long surfaceControlPtr = other.mNativeObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700326 if (surfaceControlPtr == 0) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800327 throw new NullPointerException(
328 "SurfaceControl native object is null. Are you using a released SurfaceControl?");
Jeff Brown64a55af2012-08-26 02:47:39 -0700329 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000330 long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700331
332 synchronized (mLock) {
333 if (mNativeObject != 0) {
334 nativeRelease(mNativeObject);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700335 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700336 setNativeObjectLocked(newNativeObject);
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700337 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700338 }
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800339
340 /**
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700341 * This is intended to be used by {@link SurfaceView#updateWindow} only.
Mathias Agopian7c116b52013-03-18 20:27:02 -0700342 * @param other access is not thread safe
343 * @hide
344 * @deprecated
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800345 */
Mathias Agopian7c116b52013-03-18 20:27:02 -0700346 @Deprecated
Jeff Brown64a55af2012-08-26 02:47:39 -0700347 public void transferFrom(Surface other) {
348 if (other == null) {
349 throw new IllegalArgumentException("other must not be null");
350 }
351 if (other != this) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000352 final long newPtr;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700353 synchronized (other.mLock) {
354 newPtr = other.mNativeObject;
355 other.setNativeObjectLocked(0);
356 }
357
358 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700359 if (mNativeObject != 0) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700360 nativeRelease(mNativeObject);
361 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700362 setNativeObjectLocked(newPtr);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800363 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700364 }
Mathias Agopianb9230662011-08-03 14:44:48 -0700365 }
366
Jeff Brown64a55af2012-08-26 02:47:39 -0700367 @Override
368 public int describeContents() {
369 return 0;
370 }
371
372 public void readFromParcel(Parcel source) {
373 if (source == null) {
374 throw new IllegalArgumentException("source must not be null");
375 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700376
377 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700378 // nativeReadFromParcel() will either return mNativeObject, or
379 // create a new native Surface and return it after reducing
380 // the reference count on mNativeObject. Either way, it is
381 // not necessary to call nativeRelease() here.
Mathias Agopian7c116b52013-03-18 20:27:02 -0700382 mName = source.readString();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700383 setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700384 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700385 }
386
387 @Override
388 public void writeToParcel(Parcel dest, int flags) {
389 if (dest == null) {
390 throw new IllegalArgumentException("dest must not be null");
391 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700392 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700393 dest.writeString(mName);
394 nativeWriteToParcel(mNativeObject, dest);
395 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700396 if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
397 release();
398 }
399 }
400
401 @Override
402 public String toString() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700403 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700404 return "Surface(name=" + mName + ")/@0x" +
405 Integer.toHexString(System.identityHashCode(this));
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700406 }
407 }
408
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000409 private void setNativeObjectLocked(long ptr) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700410 if (mNativeObject != ptr) {
411 if (mNativeObject == 0 && ptr != 0) {
412 mCloseGuard.open("release");
413 } else if (mNativeObject != 0 && ptr == 0) {
414 mCloseGuard.close();
415 }
416 mNativeObject = ptr;
417 mGenerationId += 1;
418 }
419 }
420
421 private void checkNotReleasedLocked() {
422 if (mNativeObject == 0) {
423 throw new IllegalStateException("Surface has already been released.");
424 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700425 }
426
Mathias Agopianc14bacf2012-04-23 18:23:08 -0700427 /**
Dan Stoza5795d642014-06-20 13:01:36 -0700428 * Allocate buffers ahead of time to avoid allocation delays during rendering
429 * @hide
430 */
431 public void allocateBuffers() {
432 synchronized (mLock) {
433 checkNotReleasedLocked();
434 nativeAllocateBuffers(mNativeObject);
435 }
436 }
437
438 /**
Igor Murashkina86ab6402013-08-30 12:58:36 -0700439 * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or
440 * when a SurfaceTexture could not successfully be allocated.
Jeff Brown64a55af2012-08-26 02:47:39 -0700441 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700442 @SuppressWarnings("serial")
443 public static class OutOfResourcesException extends RuntimeException {
Jeff Brown64a55af2012-08-26 02:47:39 -0700444 public OutOfResourcesException() {
445 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700446 public OutOfResourcesException(String name) {
447 super(name);
448 }
449 }
450
451 /**
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700452 * Returns a human readable representation of a rotation.
453 *
454 * @param rotation The rotation.
455 * @return The rotation symbolic name.
Svetoslav Ganov545252f2012-12-10 18:29:24 -0800456 *
457 * @hide
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700458 */
459 public static String rotationToString(int rotation) {
460 switch (rotation) {
461 case Surface.ROTATION_0: {
462 return "ROTATION_0";
463 }
464 case Surface.ROTATION_90: {
465 return "ROATATION_90";
466 }
467 case Surface.ROTATION_180: {
468 return "ROATATION_180";
469 }
470 case Surface.ROTATION_270: {
471 return "ROATATION_270";
472 }
473 default: {
474 throw new IllegalArgumentException("Invalid rotation: " + rotation);
475 }
476 }
477 }
478
479 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700480 * A Canvas class that can handle the compatibility mode.
481 * This does two things differently.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700482 * <ul>
Mathias Agopianb9230662011-08-03 14:44:48 -0700483 * <li>Returns the width and height of the target metrics, rather than
484 * native. For example, the canvas returns 320x480 even if an app is running
485 * in WVGA high density.
486 * <li>Scales the matrix in setMatrix by the application scale, except if
487 * the matrix looks like obtained from getMatrix. This is a hack to handle
488 * the case that an application uses getMatrix to keep the original matrix,
489 * set matrix of its own, then set the original matrix back. There is no
490 * perfect solution that works for all cases, and there are a lot of cases
491 * that this model does not work, but we hope this works for many apps.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700492 * </ul>
493 */
Jeff Brown64a55af2012-08-26 02:47:39 -0700494 private final class CompatibleCanvas extends Canvas {
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700495 // A temp matrix to remember what an application obtained via {@link getMatrix}
496 private Matrix mOrigMatrix = null;
497
498 @Override
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700499 public void setMatrix(Matrix matrix) {
500 if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
501 // don't scale the matrix if it's not compatibility mode, or
502 // the matrix was obtained from getMatrix.
503 super.setMatrix(matrix);
504 } else {
505 Matrix m = new Matrix(mCompatibleMatrix);
506 m.preConcat(matrix);
507 super.setMatrix(m);
508 }
509 }
510
Romain Guy8b5aa482013-02-28 18:13:54 -0800511 @SuppressWarnings("deprecation")
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700512 @Override
513 public void getMatrix(Matrix m) {
514 super.getMatrix(m);
515 if (mOrigMatrix == null) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700516 mOrigMatrix = new Matrix();
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700517 }
518 mOrigMatrix.set(m);
519 }
Romain Guyd10cd572010-10-10 13:33:22 -0700520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521}