• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import dalvik.system.CloseGuard;
20 
21 import android.content.res.CompatibilityInfo.Translator;
22 import android.graphics.Bitmap;
23 import android.graphics.Canvas;
24 import android.graphics.Matrix;
25 import android.graphics.Rect;
26 import android.graphics.Region;
27 import android.graphics.SurfaceTexture;
28 import android.os.IBinder;
29 import android.os.Parcelable;
30 import android.os.Parcel;
31 import android.os.SystemProperties;
32 import android.util.Log;
33 
34 /**
35  * Handle onto a raw buffer that is being managed by the screen compositor.
36  */
37 public class Surface implements Parcelable {
38     private static final String TAG = "Surface";
39 
40     private static final boolean HEADLESS = "1".equals(
41         SystemProperties.get("ro.config.headless", "0"));
42 
43     public static final Parcelable.Creator<Surface> CREATOR =
44             new Parcelable.Creator<Surface>() {
45         public Surface createFromParcel(Parcel source) {
46             try {
47                 Surface s = new Surface();
48                 s.readFromParcel(source);
49                 return s;
50             } catch (Exception e) {
51                 Log.e(TAG, "Exception creating surface from parcel", e);
52                 return null;
53             }
54         }
55 
56         public Surface[] newArray(int size) {
57             return new Surface[size];
58         }
59     };
60 
61     /**
62      * Rotation constant: 0 degree rotation (natural orientation)
63      */
64     public static final int ROTATION_0 = 0;
65 
66     /**
67      * Rotation constant: 90 degree rotation.
68      */
69     public static final int ROTATION_90 = 1;
70 
71     /**
72      * Rotation constant: 180 degree rotation.
73      */
74     public static final int ROTATION_180 = 2;
75 
76     /**
77      * Rotation constant: 270 degree rotation.
78      */
79     public static final int ROTATION_270 = 3;
80 
81     /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
82      * these are different from the logical display ids used elsewhere in the framework */
83 
84     /**
85      * Built-in physical display id: Main display.
86      * Use only with {@link #getBuiltInDisplay()}.
87      * @hide
88      */
89     public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
90 
91     /**
92      * Built-in physical display id: Attached HDMI display.
93      * Use only with {@link #getBuiltInDisplay()}.
94      * @hide
95      */
96     public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
97 
98     /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
99 
100     /**
101      * Surface creation flag: Surface is created hidden
102      * @hide */
103     public static final int HIDDEN = 0x00000004;
104 
105     /**
106      * Surface creation flag: The surface contains secure content, special
107      * measures will be taken to disallow the surface's content to be copied
108      * from another process. In particular, screenshots and VNC servers will
109      * be disabled, but other measures can take place, for instance the
110      * surface might not be hardware accelerated.
111      * @hide
112      */
113     public static final int SECURE = 0x00000080;
114 
115     /**
116      * Surface creation flag: Creates a surface where color components are interpreted
117      * as "non pre-multiplied" by their alpha channel. Of course this flag is
118      * meaningless for surfaces without an alpha channel. By default
119      * surfaces are pre-multiplied, which means that each color component is
120      * already multiplied by its alpha value. In this case the blending
121      * equation used is:
122      *
123      *    DEST = SRC + DEST * (1-SRC_ALPHA)
124      *
125      * By contrast, non pre-multiplied surfaces use the following equation:
126      *
127      *    DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
128      *
129      * pre-multiplied surfaces must always be used if transparent pixels are
130      * composited on top of each-other into the surface. A pre-multiplied
131      * surface can never lower the value of the alpha component of a given
132      * pixel.
133      *
134      * In some rare situations, a non pre-multiplied surface is preferable.
135      * @hide
136      */
137     public static final int NON_PREMULTIPLIED = 0x00000100;
138 
139     /**
140      * Surface creation flag: Indicates that the surface must be considered opaque,
141      * even if its pixel format is set to translucent. This can be useful if an
142      * application needs full RGBA 8888 support for instance but will
143      * still draw every pixel opaque.
144      * @hide
145      */
146     public static final int OPAQUE = 0x00000400;
147 
148     /**
149      * Surface creation flag: Application requires a hardware-protected path to an
150      * external display sink. If a hardware-protected path is not available,
151      * then this surface will not be displayed on the external sink.
152      * @hide
153      */
154     public static final int PROTECTED_APP = 0x00000800;
155 
156     // 0x1000 is reserved for an independent DRM protected flag in framework
157 
158     /**
159      * Surface creation flag: Creates a normal surface.
160      * This is the default.
161      * @hide
162      */
163     public static final int FX_SURFACE_NORMAL   = 0x00000000;
164 
165     /**
166      * Surface creation flag: Creates a Blur surface.
167      * Everything behind this surface is blurred by some amount.
168      * The quality and refresh speed of the blur effect is not settable or guaranteed.
169      * It is an error to lock a Blur surface, since it doesn't have a backing store.
170      * @hide
171      * @deprecated
172      */
173     @Deprecated
174     public static final int FX_SURFACE_BLUR = 0x00010000;
175 
176     /**
177      * Surface creation flag: Creates a Dim surface.
178      * Everything behind this surface is dimmed by the amount specified
179      * in {@link #setAlpha}.  It is an error to lock a Dim surface, since it
180      * doesn't have a backing store.
181      * @hide
182      */
183     public static final int FX_SURFACE_DIM = 0x00020000;
184 
185     /**
186      * @hide
187      */
188     public static final int FX_SURFACE_SCREENSHOT = 0x00030000;
189 
190     /**
191      * Mask used for FX values above.
192      * @hide
193      */
194     public static final int FX_SURFACE_MASK = 0x000F0000;
195 
196     /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
197 
198     /**
199      * Surface flag: Hide the surface.
200      * Equivalent to calling hide().
201      * @hide
202      */
203     public static final int SURFACE_HIDDEN = 0x01;
204 
205 
206     private final CloseGuard mCloseGuard = CloseGuard.get();
207     private String mName;
208 
209     // Note: These fields are accessed by native code.
210     // The mSurfaceControl will only be present for Surfaces used by the window
211     // server or system processes. When this class is parceled we defer to the
212     // mSurfaceControl to do the parceling. Otherwise we parcel the
213     // mNativeSurface.
214     private int mNativeSurface; // Surface*
215     private int mNativeSurfaceControl; // SurfaceControl*
216     private int mGenerationId; // incremented each time mNativeSurface changes
217     private final Canvas mCanvas = new CompatibleCanvas();
218     private int mCanvasSaveCount; // Canvas save count at time of lockCanvas()
219 
220     // The Translator for density compatibility mode.  This is used for scaling
221     // the canvas to perform the appropriate density transformation.
222     private Translator mCompatibilityTranslator;
223 
224     // A matrix to scale the matrix set by application. This is set to null for
225     // non compatibility mode.
226     private Matrix mCompatibleMatrix;
227 
228     private int mWidth;
229     private int mHeight;
230 
nativeCreate(SurfaceSession session, String name, int w, int h, int format, int flags)231     private native void nativeCreate(SurfaceSession session, String name,
232             int w, int h, int format, int flags)
233             throws OutOfResourcesException;
nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)234     private native void nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
235             throws OutOfResourcesException;
nativeRelease()236     private native void nativeRelease();
nativeDestroy()237     private native void nativeDestroy();
238 
nativeIsValid()239     private native boolean nativeIsValid();
nativeGetIdentity()240     private native int nativeGetIdentity();
nativeIsConsumerRunningBehind()241     private native boolean nativeIsConsumerRunningBehind();
242 
nativeLockCanvas(Rect dirty)243     private native Canvas nativeLockCanvas(Rect dirty);
nativeUnlockCanvasAndPost(Canvas canvas)244     private native void nativeUnlockCanvasAndPost(Canvas canvas);
245 
nativeScreenshot(IBinder displayToken, int width, int height, int minLayer, int maxLayer, boolean allLayers)246     private static native Bitmap nativeScreenshot(IBinder displayToken,
247             int width, int height, int minLayer, int maxLayer, boolean allLayers);
248 
nativeOpenTransaction()249     private static native void nativeOpenTransaction();
nativeCloseTransaction()250     private static native void nativeCloseTransaction();
nativeSetAnimationTransaction()251     private static native void nativeSetAnimationTransaction();
252 
nativeSetLayer(int zorder)253     private native void nativeSetLayer(int zorder);
nativeSetPosition(float x, float y)254     private native void nativeSetPosition(float x, float y);
nativeSetSize(int w, int h)255     private native void nativeSetSize(int w, int h);
nativeSetTransparentRegionHint(Region region)256     private native void nativeSetTransparentRegionHint(Region region);
nativeSetAlpha(float alpha)257     private native void nativeSetAlpha(float alpha);
nativeSetMatrix(float dsdx, float dtdx, float dsdy, float dtdy)258     private native void nativeSetMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
nativeSetFlags(int flags, int mask)259     private native void nativeSetFlags(int flags, int mask);
nativeSetWindowCrop(Rect crop)260     private native void nativeSetWindowCrop(Rect crop);
nativeSetLayerStack(int layerStack)261     private native void nativeSetLayerStack(int layerStack);
262 
nativeGetBuiltInDisplay(int physicalDisplayId)263     private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
nativeCreateDisplay(String name, boolean secure)264     private static native IBinder nativeCreateDisplay(String name, boolean secure);
nativeSetDisplaySurface( IBinder displayToken, Surface surface)265     private static native void nativeSetDisplaySurface(
266             IBinder displayToken, Surface surface);
nativeSetDisplayLayerStack( IBinder displayToken, int layerStack)267     private static native void nativeSetDisplayLayerStack(
268             IBinder displayToken, int layerStack);
nativeSetDisplayProjection( IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect)269     private static native void nativeSetDisplayProjection(
270             IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect);
nativeGetDisplayInfo( IBinder displayToken, PhysicalDisplayInfo outInfo)271     private static native boolean nativeGetDisplayInfo(
272             IBinder displayToken, PhysicalDisplayInfo outInfo);
nativeBlankDisplay(IBinder displayToken)273     private static native void nativeBlankDisplay(IBinder displayToken);
nativeUnblankDisplay(IBinder displayToken)274     private static native void nativeUnblankDisplay(IBinder displayToken);
275 
nativeCopyFrom(Surface other)276     private native void nativeCopyFrom(Surface other);
nativeTransferFrom(Surface other)277     private native void nativeTransferFrom(Surface other);
nativeReadFromParcel(Parcel source)278     private native void nativeReadFromParcel(Parcel source);
nativeWriteToParcel(Parcel dest)279     private native void nativeWriteToParcel(Parcel dest);
280 
281 
282     /**
283      * Create an empty surface, which will later be filled in by readFromParcel().
284      * @hide
285      */
Surface()286     public Surface() {
287         checkHeadless();
288 
289         mCloseGuard.open("release");
290     }
291 
292     /**
293      * Create a surface with a name.
294      *
295      * The surface creation flags specify what kind of surface to create and
296      * certain options such as whether the surface can be assumed to be opaque
297      * and whether it should be initially hidden.  Surfaces should always be
298      * created with the {@link #HIDDEN} flag set to ensure that they are not
299      * made visible prematurely before all of the surface's properties have been
300      * configured.
301      *
302      * Good practice is to first create the surface with the {@link #HIDDEN} flag
303      * specified, open a transaction, set the surface layer, layer stack, alpha,
304      * and position, call {@link #show} if appropriate, and close the transaction.
305      *
306      * @param session The surface session, must not be null.
307      * @param name The surface name, must not be null.
308      * @param w The surface initial width.
309      * @param h The surface initial height.
310      * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
311      * in the creation flags.
312      * @hide
313      */
Surface(SurfaceSession session, String name, int w, int h, int format, int flags)314     public Surface(SurfaceSession session,
315             String name, int w, int h, int format, int flags)
316             throws OutOfResourcesException {
317         if (session == null) {
318             throw new IllegalArgumentException("session must not be null");
319         }
320         if (name == null) {
321             throw new IllegalArgumentException("name must not be null");
322         }
323 
324         if ((flags & HIDDEN) == 0) {
325             Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
326                     + "to ensure that they are not made visible prematurely before "
327                     + "all of the surface's properties have been configured.  "
328                     + "Set the other properties and make the surface visible within "
329                     + "a transaction.  New surface name: " + name,
330                     new Throwable());
331         }
332 
333         checkHeadless();
334 
335         mName = name;
336         mWidth = w;
337         mHeight = h;
338         nativeCreate(session, name, w, h, format, flags);
339 
340         mCloseGuard.open("release");
341     }
342 
343     /**
344      * Create Surface from a {@link SurfaceTexture}.
345      *
346      * Images drawn to the Surface will be made available to the {@link
347      * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
348      * SurfaceTexture#updateTexImage}.
349      *
350      * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
351      * Surface.
352      */
Surface(SurfaceTexture surfaceTexture)353     public Surface(SurfaceTexture surfaceTexture) {
354         if (surfaceTexture == null) {
355             throw new IllegalArgumentException("surfaceTexture must not be null");
356         }
357 
358         checkHeadless();
359 
360         mName = surfaceTexture.toString();
361         try {
362             nativeCreateFromSurfaceTexture(surfaceTexture);
363         } catch (OutOfResourcesException ex) {
364             // We can't throw OutOfResourcesException because it would be an API change.
365             throw new RuntimeException(ex);
366         }
367 
368         mCloseGuard.open("release");
369     }
370 
371     @Override
finalize()372     protected void finalize() throws Throwable {
373         try {
374             if (mCloseGuard != null) {
375                 mCloseGuard.warnIfOpen();
376             }
377             nativeRelease();
378         } finally {
379             super.finalize();
380         }
381     }
382 
383     /**
384      * Release the local reference to the server-side surface.
385      * Always call release() when you're done with a Surface.
386      * This will make the surface invalid.
387      */
release()388     public void release() {
389         nativeRelease();
390         mCloseGuard.close();
391     }
392 
393     /**
394      * Free all server-side state associated with this surface and
395      * release this object's reference.  This method can only be
396      * called from the process that created the service.
397      * @hide
398      */
destroy()399     public void destroy() {
400         nativeDestroy();
401         mCloseGuard.close();
402     }
403 
404     /**
405      * Returns true if this object holds a valid surface.
406      *
407      * @return True if it holds a physical surface, so lockCanvas() will succeed.
408      * Otherwise returns false.
409      */
isValid()410     public boolean isValid() {
411         return nativeIsValid();
412     }
413 
414     /**
415      * Gets the generation number of this surface, incremented each time
416      * the native surface contained within this object changes.
417      *
418      * @return The current generation number.
419      * @hide
420      */
getGenerationId()421     public int getGenerationId() {
422         return mGenerationId;
423     }
424 
425     /**
426      * Returns true if the consumer of this Surface is running behind the producer.
427      *
428      * @return True if the consumer is more than one buffer ahead of the producer.
429      * @hide
430      */
isConsumerRunningBehind()431     public boolean isConsumerRunningBehind() {
432         return nativeIsConsumerRunningBehind();
433     }
434 
435     /**
436      * Gets a {@link Canvas} for drawing into this surface.
437      *
438      * After drawing into the provided {@link Canvas}, the caller should
439      * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
440      *
441      * @param dirty A rectangle that represents the dirty region that the caller wants
442      * to redraw.  This function may choose to expand the dirty rectangle if for example
443      * the surface has been resized or if the previous contents of the surface were
444      * not available.  The caller should redraw the entire dirty region as represented
445      * by the contents of the dirty rect upon return from this function.
446      * The caller may also pass <code>null</code> instead, in the case where the
447      * entire surface should be redrawn.
448      * @return A canvas for drawing into the surface.
449      */
lockCanvas(Rect dirty)450     public Canvas lockCanvas(Rect dirty)
451             throws OutOfResourcesException, IllegalArgumentException {
452         return nativeLockCanvas(dirty);
453     }
454 
455     /**
456      * Posts the new contents of the {@link Canvas} to the surface and
457      * releases the {@link Canvas}.
458      *
459      * @param canvas The canvas previously obtained from {@link #lockCanvas}.
460      */
unlockCanvasAndPost(Canvas canvas)461     public void unlockCanvasAndPost(Canvas canvas) {
462         nativeUnlockCanvasAndPost(canvas);
463     }
464 
465     /**
466      * @deprecated This API has been removed and is not supported.  Do not use.
467      */
468     @Deprecated
unlockCanvas(Canvas canvas)469     public void unlockCanvas(Canvas canvas) {
470         throw new UnsupportedOperationException();
471     }
472 
473     /**
474      * Sets the translator used to scale canvas's width/height in compatibility
475      * mode.
476      */
setCompatibilityTranslator(Translator translator)477     void setCompatibilityTranslator(Translator translator) {
478         if (translator != null) {
479             float appScale = translator.applicationScale;
480             mCompatibleMatrix = new Matrix();
481             mCompatibleMatrix.setScale(appScale, appScale);
482         }
483     }
484 
485     /**
486      * Like {@link #screenshot(int, int, int, int)} but includes all
487      * Surfaces in the screenshot.
488      *
489      * @hide
490      */
screenshot(int width, int height)491     public static Bitmap screenshot(int width, int height) {
492         // TODO: should take the display as a parameter
493         IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN);
494         return nativeScreenshot(displayToken, width, height, 0, 0, true);
495     }
496 
497     /**
498      * Copy the current screen contents into a bitmap and return it.
499      *
500      * @param width The desired width of the returned bitmap; the raw
501      * screen will be scaled down to this size.
502      * @param height The desired height of the returned bitmap; the raw
503      * screen will be scaled down to this size.
504      * @param minLayer The lowest (bottom-most Z order) surface layer to
505      * include in the screenshot.
506      * @param maxLayer The highest (top-most Z order) surface layer to
507      * include in the screenshot.
508      * @return Returns a Bitmap containing the screen contents, or null
509      * if an error occurs.
510      *
511      * @hide
512      */
screenshot(int width, int height, int minLayer, int maxLayer)513     public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) {
514         // TODO: should take the display as a parameter
515         IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN);
516         return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false);
517     }
518 
519     /*
520      * set surface parameters.
521      * needs to be inside open/closeTransaction block
522      */
523 
524     /** start a transaction @hide */
openTransaction()525     public static void openTransaction() {
526         nativeOpenTransaction();
527     }
528 
529     /** end a transaction @hide */
closeTransaction()530     public static void closeTransaction() {
531         nativeCloseTransaction();
532     }
533 
534     /** flag the transaction as an animation @hide */
setAnimationTransaction()535     public static void setAnimationTransaction() {
536         nativeSetAnimationTransaction();
537     }
538 
539     /** @hide */
setLayer(int zorder)540     public void setLayer(int zorder) {
541         nativeSetLayer(zorder);
542     }
543 
544     /** @hide */
setPosition(int x, int y)545     public void setPosition(int x, int y) {
546         nativeSetPosition(x, y);
547     }
548 
549     /** @hide */
setPosition(float x, float y)550     public void setPosition(float x, float y) {
551         nativeSetPosition(x, y);
552     }
553 
554     /** @hide */
setSize(int w, int h)555     public void setSize(int w, int h) {
556         mWidth = w;
557         mHeight = h;
558         nativeSetSize(w, h);
559     }
560 
561     /** @hide */
getWidth()562     public int getWidth() {
563         return mWidth;
564     }
565 
566     /** @hide */
getHeight()567     public int getHeight() {
568         return mHeight;
569     }
570 
571     /** @hide */
hide()572     public void hide() {
573         nativeSetFlags(SURFACE_HIDDEN, SURFACE_HIDDEN);
574     }
575 
576     /** @hide */
show()577     public void show() {
578         nativeSetFlags(0, SURFACE_HIDDEN);
579     }
580 
581     /** @hide */
setTransparentRegionHint(Region region)582     public void setTransparentRegionHint(Region region) {
583         nativeSetTransparentRegionHint(region);
584     }
585 
586     /** @hide */
setAlpha(float alpha)587     public void setAlpha(float alpha) {
588         nativeSetAlpha(alpha);
589     }
590 
591     /** @hide */
setMatrix(float dsdx, float dtdx, float dsdy, float dtdy)592     public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
593         nativeSetMatrix(dsdx, dtdx, dsdy, dtdy);
594     }
595 
596     /** @hide */
setFlags(int flags, int mask)597     public void setFlags(int flags, int mask) {
598         nativeSetFlags(flags, mask);
599     }
600 
601     /** @hide */
setWindowCrop(Rect crop)602     public void setWindowCrop(Rect crop) {
603         nativeSetWindowCrop(crop);
604     }
605 
606     /** @hide */
setLayerStack(int layerStack)607     public void setLayerStack(int layerStack) {
608         nativeSetLayerStack(layerStack);
609     }
610 
611     /** @hide */
getBuiltInDisplay(int builtInDisplayId)612     public static IBinder getBuiltInDisplay(int builtInDisplayId) {
613         return nativeGetBuiltInDisplay(builtInDisplayId);
614     }
615 
616     /** @hide */
createDisplay(String name, boolean secure)617     public static IBinder createDisplay(String name, boolean secure) {
618         if (name == null) {
619             throw new IllegalArgumentException("name must not be null");
620         }
621         return nativeCreateDisplay(name, secure);
622     }
623 
624     /** @hide */
setDisplaySurface(IBinder displayToken, Surface surface)625     public static void setDisplaySurface(IBinder displayToken, Surface surface) {
626         if (displayToken == null) {
627             throw new IllegalArgumentException("displayToken must not be null");
628         }
629         nativeSetDisplaySurface(displayToken, surface);
630     }
631 
632     /** @hide */
setDisplayLayerStack(IBinder displayToken, int layerStack)633     public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
634         if (displayToken == null) {
635             throw new IllegalArgumentException("displayToken must not be null");
636         }
637         nativeSetDisplayLayerStack(displayToken, layerStack);
638     }
639 
640     /** @hide */
setDisplayProjection(IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect)641     public static void setDisplayProjection(IBinder displayToken,
642             int orientation, Rect layerStackRect, Rect displayRect) {
643         if (displayToken == null) {
644             throw new IllegalArgumentException("displayToken must not be null");
645         }
646         if (layerStackRect == null) {
647             throw new IllegalArgumentException("layerStackRect must not be null");
648         }
649         if (displayRect == null) {
650             throw new IllegalArgumentException("displayRect must not be null");
651         }
652         nativeSetDisplayProjection(displayToken, orientation, layerStackRect, displayRect);
653     }
654 
655     /** @hide */
getDisplayInfo(IBinder displayToken, PhysicalDisplayInfo outInfo)656     public static boolean getDisplayInfo(IBinder displayToken, PhysicalDisplayInfo outInfo) {
657         if (displayToken == null) {
658             throw new IllegalArgumentException("displayToken must not be null");
659         }
660         if (outInfo == null) {
661             throw new IllegalArgumentException("outInfo must not be null");
662         }
663         return nativeGetDisplayInfo(displayToken, outInfo);
664     }
665 
666     /** @hide */
blankDisplay(IBinder displayToken)667     public static void blankDisplay(IBinder displayToken) {
668         if (displayToken == null) {
669             throw new IllegalArgumentException("displayToken must not be null");
670         }
671         nativeBlankDisplay(displayToken);
672     }
673 
674     /** @hide */
unblankDisplay(IBinder displayToken)675     public static void unblankDisplay(IBinder displayToken) {
676         if (displayToken == null) {
677             throw new IllegalArgumentException("displayToken must not be null");
678         }
679         nativeUnblankDisplay(displayToken);
680     }
681 
682     /**
683      * Copy another surface to this one.  This surface now holds a reference
684      * to the same data as the original surface, and is -not- the owner.
685      * This is for use by the window manager when returning a window surface
686      * back from a client, converting it from the representation being managed
687      * by the window manager to the representation the client uses to draw
688      * in to it.
689      * @hide
690      */
copyFrom(Surface other)691     public void copyFrom(Surface other) {
692         if (other == null) {
693             throw new IllegalArgumentException("other must not be null");
694         }
695         if (other != this) {
696             nativeCopyFrom(other);
697         }
698     }
699 
700     /**
701      * Transfer the native state from 'other' to this surface, releasing it
702      * from 'other'.  This is for use in the client side for drawing into a
703      * surface; not guaranteed to work on the window manager side.
704      * This is for use by the client to move the underlying surface from
705      * one Surface object to another, in particular in SurfaceFlinger.
706      * @hide.
707      */
transferFrom(Surface other)708     public void transferFrom(Surface other) {
709         if (other == null) {
710             throw new IllegalArgumentException("other must not be null");
711         }
712         if (other != this) {
713             nativeTransferFrom(other);
714         }
715     }
716 
717     @Override
describeContents()718     public int describeContents() {
719         return 0;
720     }
721 
readFromParcel(Parcel source)722     public void readFromParcel(Parcel source) {
723         if (source == null) {
724             throw new IllegalArgumentException("source must not be null");
725         }
726 
727         mName = source.readString();
728         nativeReadFromParcel(source);
729     }
730 
731     @Override
writeToParcel(Parcel dest, int flags)732     public void writeToParcel(Parcel dest, int flags) {
733         if (dest == null) {
734             throw new IllegalArgumentException("dest must not be null");
735         }
736 
737         dest.writeString(mName);
738         nativeWriteToParcel(dest);
739         if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
740             release();
741         }
742     }
743 
744     @Override
toString()745     public String toString() {
746         return "Surface(name=" + mName + ", identity=" + nativeGetIdentity() + ")";
747     }
748 
checkHeadless()749     private static void checkHeadless() {
750         if (HEADLESS) {
751             throw new UnsupportedOperationException("Device is headless");
752         }
753     }
754 
755     /**
756      * Exception thrown when a surface couldn't be created or resized.
757      */
758     public static class OutOfResourcesException extends Exception {
OutOfResourcesException()759         public OutOfResourcesException() {
760         }
761 
OutOfResourcesException(String name)762         public OutOfResourcesException(String name) {
763             super(name);
764         }
765     }
766 
767     /**
768      * Describes the properties of a physical display known to surface flinger.
769      * @hide
770      */
771     public static final class PhysicalDisplayInfo {
772         public int width;
773         public int height;
774         public float refreshRate;
775         public float density;
776         public float xDpi;
777         public float yDpi;
778         public boolean secure;
779 
PhysicalDisplayInfo()780         public PhysicalDisplayInfo() {
781         }
782 
PhysicalDisplayInfo(PhysicalDisplayInfo other)783         public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
784             copyFrom(other);
785         }
786 
787         @Override
equals(Object o)788         public boolean equals(Object o) {
789             return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
790         }
791 
equals(PhysicalDisplayInfo other)792         public boolean equals(PhysicalDisplayInfo other) {
793             return other != null
794                     && width == other.width
795                     && height == other.height
796                     && refreshRate == other.refreshRate
797                     && density == other.density
798                     && xDpi == other.xDpi
799                     && yDpi == other.yDpi
800                     && secure == other.secure;
801         }
802 
803         @Override
hashCode()804         public int hashCode() {
805             return 0; // don't care
806         }
807 
copyFrom(PhysicalDisplayInfo other)808         public void copyFrom(PhysicalDisplayInfo other) {
809             width = other.width;
810             height = other.height;
811             refreshRate = other.refreshRate;
812             density = other.density;
813             xDpi = other.xDpi;
814             yDpi = other.yDpi;
815             secure = other.secure;
816         }
817 
818         // For debugging purposes
819         @Override
toString()820         public String toString() {
821             return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
822                     + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
823                     + "}";
824         }
825     }
826 
827     /**
828      * A Canvas class that can handle the compatibility mode.
829      * This does two things differently.
830      * <ul>
831      * <li>Returns the width and height of the target metrics, rather than
832      * native. For example, the canvas returns 320x480 even if an app is running
833      * in WVGA high density.
834      * <li>Scales the matrix in setMatrix by the application scale, except if
835      * the matrix looks like obtained from getMatrix. This is a hack to handle
836      * the case that an application uses getMatrix to keep the original matrix,
837      * set matrix of its own, then set the original matrix back. There is no
838      * perfect solution that works for all cases, and there are a lot of cases
839      * that this model does not work, but we hope this works for many apps.
840      * </ul>
841      */
842     private final class CompatibleCanvas extends Canvas {
843         // A temp matrix to remember what an application obtained via {@link getMatrix}
844         private Matrix mOrigMatrix = null;
845 
846         @Override
getWidth()847         public int getWidth() {
848             int w = super.getWidth();
849             if (mCompatibilityTranslator != null) {
850                 w = (int)(w * mCompatibilityTranslator.applicationInvertedScale + .5f);
851             }
852             return w;
853         }
854 
855         @Override
getHeight()856         public int getHeight() {
857             int h = super.getHeight();
858             if (mCompatibilityTranslator != null) {
859                 h = (int)(h * mCompatibilityTranslator.applicationInvertedScale + .5f);
860             }
861             return h;
862         }
863 
864         @Override
setMatrix(Matrix matrix)865         public void setMatrix(Matrix matrix) {
866             if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
867                 // don't scale the matrix if it's not compatibility mode, or
868                 // the matrix was obtained from getMatrix.
869                 super.setMatrix(matrix);
870             } else {
871                 Matrix m = new Matrix(mCompatibleMatrix);
872                 m.preConcat(matrix);
873                 super.setMatrix(m);
874             }
875         }
876 
877         @Override
getMatrix(Matrix m)878         public void getMatrix(Matrix m) {
879             super.getMatrix(m);
880             if (mOrigMatrix == null) {
881                 mOrigMatrix = new Matrix();
882             }
883             mOrigMatrix.set(m);
884         }
885     }
886 }
887