SurfaceControl.java revision aa763cd35f9a74a93a2fc8cee74e8455e504788e
1/*
2 * Copyright (C) 2013 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
19import static android.graphics.Matrix.MSCALE_X;
20import static android.graphics.Matrix.MSCALE_Y;
21import static android.graphics.Matrix.MSKEW_X;
22import static android.graphics.Matrix.MSKEW_Y;
23import static android.graphics.Matrix.MTRANS_X;
24import static android.graphics.Matrix.MTRANS_Y;
25import static android.view.Surface.ROTATION_270;
26import static android.view.Surface.ROTATION_90;
27import static android.view.SurfaceControlProto.HASH_CODE;
28import static android.view.SurfaceControlProto.NAME;
29
30import android.annotation.Size;
31import android.graphics.Bitmap;
32import android.graphics.GraphicBuffer;
33import android.graphics.Matrix;
34import android.graphics.PixelFormat;
35import android.graphics.Point;
36import android.graphics.Rect;
37import android.graphics.Region;
38import android.os.IBinder;
39import android.os.Parcel;
40import android.os.Parcelable;
41import android.os.Process;
42import android.os.UserHandle;
43import android.util.ArrayMap;
44import android.util.Log;
45import android.util.proto.ProtoOutputStream;
46import android.view.Surface.OutOfResourcesException;
47
48import com.android.internal.annotations.GuardedBy;
49
50import dalvik.system.CloseGuard;
51
52import libcore.util.NativeAllocationRegistry;
53
54import java.io.Closeable;
55
56/**
57 * SurfaceControl
58 *  @hide
59 */
60public class SurfaceControl implements Parcelable {
61    private static final String TAG = "SurfaceControl";
62
63    private static native long nativeCreate(SurfaceSession session, String name,
64            int w, int h, int format, int flags, long parentObject, int windowType, int ownerUid)
65            throws OutOfResourcesException;
66    private static native long nativeReadFromParcel(Parcel in);
67    private static native void nativeWriteToParcel(long nativeObject, Parcel out);
68    private static native void nativeRelease(long nativeObject);
69    private static native void nativeDestroy(long nativeObject);
70    private static native void nativeDisconnect(long nativeObject);
71
72    private static native Bitmap nativeScreenshot(IBinder displayToken,
73            Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
74            boolean allLayers, boolean useIdentityTransform, int rotation);
75    private static native GraphicBuffer nativeScreenshotToBuffer(IBinder displayToken,
76            Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
77            boolean allLayers, boolean useIdentityTransform, int rotation);
78    private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
79            Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
80            boolean allLayers, boolean useIdentityTransform);
81    private static native GraphicBuffer nativeCaptureLayers(IBinder layerHandleToken,
82            Rect sourceCrop, float frameScale);
83
84    private static native long nativeCreateTransaction();
85    private static native long nativeGetNativeTransactionFinalizer();
86    private static native void nativeApplyTransaction(long transactionObj, boolean sync);
87    private static native void nativeMergeTransaction(long transactionObj,
88            long otherTransactionObj);
89    private static native void nativeSetAnimationTransaction(long transactionObj);
90    private static native void nativeSetEarlyWakeup(long transactionObj);
91
92    private static native void nativeSetLayer(long transactionObj, long nativeObject, int zorder);
93    private static native void nativeSetRelativeLayer(long transactionObj, long nativeObject,
94            IBinder relativeTo, int zorder);
95    private static native void nativeSetPosition(long transactionObj, long nativeObject,
96            float x, float y);
97    private static native void nativeSetGeometryAppliesWithResize(long transactionObj,
98            long nativeObject);
99    private static native void nativeSetSize(long transactionObj, long nativeObject, int w, int h);
100    private static native void nativeSetTransparentRegionHint(long transactionObj,
101            long nativeObject, Region region);
102    private static native void nativeSetAlpha(long transactionObj, long nativeObject, float alpha);
103    private static native void nativeSetMatrix(long transactionObj, long nativeObject,
104            float dsdx, float dtdx,
105            float dtdy, float dsdy);
106    private static native void nativeSetColor(long transactionObj, long nativeObject, float[] color);
107    private static native void nativeSetFlags(long transactionObj, long nativeObject,
108            int flags, int mask);
109    private static native void nativeSetWindowCrop(long transactionObj, long nativeObject,
110            int l, int t, int r, int b);
111    private static native void nativeSetFinalCrop(long transactionObj, long nativeObject,
112            int l, int t, int r, int b);
113    private static native void nativeSetLayerStack(long transactionObj, long nativeObject,
114            int layerStack);
115
116    private static native boolean nativeClearContentFrameStats(long nativeObject);
117    private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
118    private static native boolean nativeClearAnimationFrameStats();
119    private static native boolean nativeGetAnimationFrameStats(WindowAnimationFrameStats outStats);
120
121    private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
122    private static native IBinder nativeCreateDisplay(String name, boolean secure);
123    private static native void nativeDestroyDisplay(IBinder displayToken);
124    private static native void nativeSetDisplaySurface(long transactionObj,
125            IBinder displayToken, long nativeSurfaceObject);
126    private static native void nativeSetDisplayLayerStack(long transactionObj,
127            IBinder displayToken, int layerStack);
128    private static native void nativeSetDisplayProjection(long transactionObj,
129            IBinder displayToken, int orientation,
130            int l, int t, int r, int b,
131            int L, int T, int R, int B);
132    private static native void nativeSetDisplaySize(long transactionObj, IBinder displayToken,
133            int width, int height);
134    private static native SurfaceControl.PhysicalDisplayInfo[] nativeGetDisplayConfigs(
135            IBinder displayToken);
136    private static native int nativeGetActiveConfig(IBinder displayToken);
137    private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
138    private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
139    private static native int nativeGetActiveColorMode(IBinder displayToken);
140    private static native boolean nativeSetActiveColorMode(IBinder displayToken,
141            int colorMode);
142    private static native void nativeSetDisplayPowerMode(
143            IBinder displayToken, int mode);
144    private static native void nativeDeferTransactionUntil(long transactionObj, long nativeObject,
145            IBinder handle, long frame);
146    private static native void nativeDeferTransactionUntilSurface(long transactionObj,
147            long nativeObject,
148            long surfaceObject, long frame);
149    private static native void nativeReparentChildren(long transactionObj, long nativeObject,
150            IBinder handle);
151    private static native void nativeReparent(long transactionObj, long nativeObject,
152            IBinder parentHandle);
153    private static native void nativeSeverChildren(long transactionObj, long nativeObject);
154    private static native void nativeSetOverrideScalingMode(long transactionObj, long nativeObject,
155            int scalingMode);
156    private static native void nativeDestroy(long transactionObj, long nativeObject);
157    private static native IBinder nativeGetHandle(long nativeObject);
158    private static native boolean nativeGetTransformToDisplayInverse(long nativeObject);
159
160    private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
161
162
163    private final CloseGuard mCloseGuard = CloseGuard.get();
164    private final String mName;
165    long mNativeObject; // package visibility only for Surface.java access
166
167    // TODO: Move this to native.
168    private final Object mSizeLock = new Object();
169    @GuardedBy("mSizeLock")
170    private int mWidth;
171    @GuardedBy("mSizeLock")
172    private int mHeight;
173
174    static Transaction sGlobalTransaction;
175    static long sTransactionNestCount = 0;
176
177    /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
178
179    /**
180     * Surface creation flag: Surface is created hidden
181     */
182    public static final int HIDDEN = 0x00000004;
183
184    /**
185     * Surface creation flag: The surface contains secure content, special
186     * measures will be taken to disallow the surface's content to be copied
187     * from another process. In particular, screenshots and VNC servers will
188     * be disabled, but other measures can take place, for instance the
189     * surface might not be hardware accelerated.
190     *
191     */
192    public static final int SECURE = 0x00000080;
193
194    /**
195     * Surface creation flag: Creates a surface where color components are interpreted
196     * as "non pre-multiplied" by their alpha channel. Of course this flag is
197     * meaningless for surfaces without an alpha channel. By default
198     * surfaces are pre-multiplied, which means that each color component is
199     * already multiplied by its alpha value. In this case the blending
200     * equation used is:
201     * <p>
202     *    <code>DEST = SRC + DEST * (1-SRC_ALPHA)</code>
203     * <p>
204     * By contrast, non pre-multiplied surfaces use the following equation:
205     * <p>
206     *    <code>DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)</code>
207     * <p>
208     * pre-multiplied surfaces must always be used if transparent pixels are
209     * composited on top of each-other into the surface. A pre-multiplied
210     * surface can never lower the value of the alpha component of a given
211     * pixel.
212     * <p>
213     * In some rare situations, a non pre-multiplied surface is preferable.
214     *
215     */
216    public static final int NON_PREMULTIPLIED = 0x00000100;
217
218    /**
219     * Surface creation flag: Indicates that the surface must be considered opaque,
220     * even if its pixel format contains an alpha channel. This can be useful if an
221     * application needs full RGBA 8888 support for instance but will
222     * still draw every pixel opaque.
223     * <p>
224     * This flag is ignored if setAlpha() is used to make the surface non-opaque.
225     * Combined effects are (assuming a buffer format with an alpha channel):
226     * <ul>
227     * <li>OPAQUE + alpha(1.0) == opaque composition
228     * <li>OPAQUE + alpha(0.x) == blended composition
229     * <li>!OPAQUE + alpha(1.0) == blended composition
230     * <li>!OPAQUE + alpha(0.x) == blended composition
231     * </ul>
232     * If the underlying buffer lacks an alpha channel, the OPAQUE flag is effectively
233     * set automatically.
234     */
235    public static final int OPAQUE = 0x00000400;
236
237    /**
238     * Surface creation flag: Application requires a hardware-protected path to an
239     * external display sink. If a hardware-protected path is not available,
240     * then this surface will not be displayed on the external sink.
241     *
242     */
243    public static final int PROTECTED_APP = 0x00000800;
244
245    // 0x1000 is reserved for an independent DRM protected flag in framework
246
247    /**
248     * Surface creation flag: Window represents a cursor glyph.
249     */
250    public static final int CURSOR_WINDOW = 0x00002000;
251
252    /**
253     * Surface creation flag: Creates a normal surface.
254     * This is the default.
255     *
256     */
257    public static final int FX_SURFACE_NORMAL   = 0x00000000;
258
259    /**
260     * Surface creation flag: Creates a Dim surface.
261     * Everything behind this surface is dimmed by the amount specified
262     * in {@link #setAlpha}.  It is an error to lock a Dim surface, since it
263     * doesn't have a backing store.
264     *
265     */
266    public static final int FX_SURFACE_DIM = 0x00020000;
267
268    /**
269     * Mask used for FX values above.
270     *
271     */
272    public static final int FX_SURFACE_MASK = 0x000F0000;
273
274    /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
275
276    /**
277     * Surface flag: Hide the surface.
278     * Equivalent to calling hide().
279     * Updates the value set during Surface creation (see {@link #HIDDEN}).
280     */
281    private static final int SURFACE_HIDDEN = 0x01;
282
283    /**
284     * Surface flag: composite without blending when possible.
285     * Updates the value set during Surface creation (see {@link #OPAQUE}).
286     */
287    private static final int SURFACE_OPAQUE = 0x02;
288
289
290    /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
291     * these are different from the logical display ids used elsewhere in the framework */
292
293    /**
294     * Built-in physical display id: Main display.
295     * Use only with {@link SurfaceControl#getBuiltInDisplay(int)}.
296     */
297    public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
298
299    /**
300     * Built-in physical display id: Attached HDMI display.
301     * Use only with {@link SurfaceControl#getBuiltInDisplay(int)}.
302     */
303    public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
304
305    /* Display power modes * /
306
307    /**
308     * Display power mode off: used while blanking the screen.
309     * Use only with {@link SurfaceControl#setDisplayPowerMode}.
310     */
311    public static final int POWER_MODE_OFF = 0;
312
313    /**
314     * Display power mode doze: used while putting the screen into low power mode.
315     * Use only with {@link SurfaceControl#setDisplayPowerMode}.
316     */
317    public static final int POWER_MODE_DOZE = 1;
318
319    /**
320     * Display power mode normal: used while unblanking the screen.
321     * Use only with {@link SurfaceControl#setDisplayPowerMode}.
322     */
323    public static final int POWER_MODE_NORMAL = 2;
324
325    /**
326     * Display power mode doze: used while putting the screen into a suspended
327     * low power mode.  Use only with {@link SurfaceControl#setDisplayPowerMode}.
328     */
329    public static final int POWER_MODE_DOZE_SUSPEND = 3;
330
331    /**
332     * Display power mode on: used while putting the screen into a suspended
333     * full power mode.  Use only with {@link SurfaceControl#setDisplayPowerMode}.
334     */
335    public static final int POWER_MODE_ON_SUSPEND = 4;
336
337    /**
338     * A value for windowType used to indicate that the window should be omitted from screenshots
339     * and display mirroring. A temporary workaround until we express such things with
340     * the hierarchy.
341     * TODO: b/64227542
342     * @hide
343     */
344    public static final int WINDOW_TYPE_DONT_SCREENSHOT = 441731;
345
346    /**
347     * Builder class for {@link SurfaceControl} objects.
348     */
349    public static class Builder {
350        private SurfaceSession mSession;
351        private int mFlags = HIDDEN;
352        private int mWidth;
353        private int mHeight;
354        private int mFormat = PixelFormat.OPAQUE;
355        private String mName;
356        private SurfaceControl mParent;
357        private int mWindowType = -1;
358        private int mOwnerUid = -1;
359
360        /**
361         * Begin building a SurfaceControl with a given {@link SurfaceSession}.
362         *
363         * @param session The {@link SurfaceSession} with which to eventually construct the surface.
364         */
365        public Builder(SurfaceSession session) {
366            mSession = session;
367        }
368
369        /**
370         * Construct a new {@link SurfaceControl} with the set parameters.
371         */
372        public SurfaceControl build() {
373            if (mWidth <= 0 || mHeight <= 0) {
374                throw new IllegalArgumentException(
375                        "width and height must be set");
376            }
377            return new SurfaceControl(mSession, mName, mWidth, mHeight, mFormat,
378                    mFlags, mParent, mWindowType, mOwnerUid);
379        }
380
381        /**
382         * Set a debugging-name for the SurfaceControl.
383         *
384         * @param name A name to identify the Surface in debugging.
385         */
386        public Builder setName(String name) {
387            mName = name;
388            return this;
389        }
390
391        /**
392         * Set the initial size of the controlled surface's buffers in pixels.
393         *
394         * @param width The buffer width in pixels.
395         * @param height The buffer height in pixels.
396         */
397        public Builder setSize(int width, int height) {
398            if (width <= 0 || height <= 0) {
399                throw new IllegalArgumentException(
400                        "width and height must be positive");
401            }
402            mWidth = width;
403            mHeight = height;
404            return this;
405        }
406
407        /**
408         * Set the pixel format of the controlled surface's buffers, using constants from
409         * {@link android.graphics.PixelFormat}.
410         */
411        public Builder setFormat(@PixelFormat.Format int format) {
412            mFormat = format;
413            return this;
414        }
415
416        /**
417         * Specify if the app requires a hardware-protected path to
418         * an external display sync. If protected content is enabled, but
419         * such a path is not available, then the controlled Surface will
420         * not be displayed.
421         *
422         * @param protectedContent Whether to require a protected sink.
423         */
424        public Builder setProtected(boolean protectedContent) {
425            if (protectedContent) {
426                mFlags |= PROTECTED_APP;
427            } else {
428                mFlags &= ~PROTECTED_APP;
429            }
430            return this;
431        }
432
433        /**
434         * Specify whether the Surface contains secure content. If true, the system
435         * will prevent the surfaces content from being copied by another process. In
436         * particular screenshots and VNC servers will be disabled. This is however
437         * not a complete prevention of readback as {@link #setProtected}.
438         */
439        public Builder setSecure(boolean secure) {
440            if (secure) {
441                mFlags |= SECURE;
442            } else {
443                mFlags &= ~SECURE;
444            }
445            return this;
446        }
447
448        /**
449         * Indicates whether the surface must be considered opaque,
450         * even if its pixel format is set to translucent. This can be useful if an
451         * application needs full RGBA 8888 support for instance but will
452         * still draw every pixel opaque.
453         * <p>
454         * This flag only determines whether opacity will be sampled from the alpha channel.
455         * Plane-alpha from calls to setAlpha() can still result in blended composition
456         * regardless of the opaque setting.
457         *
458         * Combined effects are (assuming a buffer format with an alpha channel):
459         * <ul>
460         * <li>OPAQUE + alpha(1.0) == opaque composition
461         * <li>OPAQUE + alpha(0.x) == blended composition
462         * <li>OPAQUE + alpha(0.0) == no composition
463         * <li>!OPAQUE + alpha(1.0) == blended composition
464         * <li>!OPAQUE + alpha(0.x) == blended composition
465         * <li>!OPAQUE + alpha(0.0) == no composition
466         * </ul>
467         * If the underlying buffer lacks an alpha channel, it is as if setOpaque(true)
468         * were set automatically.
469         * @param opaque Whether the Surface is OPAQUE.
470         */
471        public Builder setOpaque(boolean opaque) {
472            if (opaque) {
473                mFlags |= OPAQUE;
474            } else {
475                mFlags &= ~OPAQUE;
476            }
477            return this;
478        }
479
480        /**
481         * Set a parent surface for our new SurfaceControl.
482         *
483         * Child surfaces are constrained to the onscreen region of their parent.
484         * Furthermore they stack relatively in Z order, and inherit the transformation
485         * of the parent.
486         *
487         * @param parent The parent control.
488         */
489        public Builder setParent(SurfaceControl parent) {
490            mParent = parent;
491            return this;
492        }
493
494        /**
495         * Set surface metadata.
496         *
497         * Currently these are window-types as per {@link WindowManager.LayoutParams} and
498         * owner UIDs. Child surfaces inherit their parents
499         * metadata so only the WindowManager needs to set this on root Surfaces.
500         *
501         * @param windowType A window-type
502         * @param ownerUid UID of the window owner.
503         */
504        public Builder setMetadata(int windowType, int ownerUid) {
505            if (UserHandle.getAppId(Process.myUid()) != Process.SYSTEM_UID) {
506                throw new UnsupportedOperationException(
507                        "It only makes sense to set Surface metadata from the WindowManager");
508            }
509            mWindowType = windowType;
510            mOwnerUid = ownerUid;
511            return this;
512        }
513
514        /**
515         * Indicate whether a 'ColorLayer' is to be constructed.
516         *
517         * Color layers will not have an associated BufferQueue and will instead always render a
518         * solid color (that is, solid before plane alpha). Currently that color is black.
519         *
520         * @param isColorLayer Whether to create a color layer.
521         */
522        public Builder setColorLayer(boolean isColorLayer) {
523            if (isColorLayer) {
524                mFlags |= FX_SURFACE_DIM;
525            } else {
526                mFlags &= ~FX_SURFACE_DIM;
527            }
528            return this;
529        }
530
531        /**
532         * Set 'Surface creation flags' such as {@link HIDDEN}, {@link SECURE}.
533         *
534         * TODO: Finish conversion to individual builder methods?
535         * @param flags The combined flags
536         */
537        public Builder setFlags(int flags) {
538            mFlags = flags;
539            return this;
540        }
541    }
542
543    /**
544     * Create a surface with a name.
545     * <p>
546     * The surface creation flags specify what kind of surface to create and
547     * certain options such as whether the surface can be assumed to be opaque
548     * and whether it should be initially hidden.  Surfaces should always be
549     * created with the {@link #HIDDEN} flag set to ensure that they are not
550     * made visible prematurely before all of the surface's properties have been
551     * configured.
552     * <p>
553     * Good practice is to first create the surface with the {@link #HIDDEN} flag
554     * specified, open a transaction, set the surface layer, layer stack, alpha,
555     * and position, call {@link #show} if appropriate, and close the transaction.
556     *
557     * @param session The surface session, must not be null.
558     * @param name The surface name, must not be null.
559     * @param w The surface initial width.
560     * @param h The surface initial height.
561     * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
562     * in the creation flags.
563     * @param windowType The type of the window as specified in WindowManager.java.
564     * @param ownerUid A unique per-app ID.
565     *
566     * @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
567     */
568    private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
569            SurfaceControl parent, int windowType, int ownerUid)
570                    throws OutOfResourcesException, IllegalArgumentException {
571        if (session == null) {
572            throw new IllegalArgumentException("session must not be null");
573        }
574        if (name == null) {
575            throw new IllegalArgumentException("name must not be null");
576        }
577
578        if ((flags & SurfaceControl.HIDDEN) == 0) {
579            Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
580                    + "to ensure that they are not made visible prematurely before "
581                    + "all of the surface's properties have been configured.  "
582                    + "Set the other properties and make the surface visible within "
583                    + "a transaction.  New surface name: " + name,
584                    new Throwable());
585        }
586
587        mName = name;
588        mWidth = w;
589        mHeight = h;
590        mNativeObject = nativeCreate(session, name, w, h, format, flags,
591            parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
592        if (mNativeObject == 0) {
593            throw new OutOfResourcesException(
594                    "Couldn't allocate SurfaceControl native object");
595        }
596
597        mCloseGuard.open("release");
598    }
599
600    // This is a transfer constructor, useful for transferring a live SurfaceControl native
601    // object to another Java wrapper which could have some different behavior, e.g.
602    // event logging.
603    public SurfaceControl(SurfaceControl other) {
604        mName = other.mName;
605        mWidth = other.mWidth;
606        mHeight = other.mHeight;
607        mNativeObject = other.mNativeObject;
608        other.mCloseGuard.close();
609        other.mNativeObject = 0;
610        mCloseGuard.open("release");
611    }
612
613    private SurfaceControl(Parcel in) {
614        mName = in.readString();
615        mWidth = in.readInt();
616        mHeight = in.readInt();
617        mNativeObject = nativeReadFromParcel(in);
618        if (mNativeObject == 0) {
619            throw new IllegalArgumentException("Couldn't read SurfaceControl from parcel=" + in);
620        }
621        mCloseGuard.open("release");
622    }
623
624    @Override
625    public int describeContents() {
626        return 0;
627    }
628
629    @Override
630    public void writeToParcel(Parcel dest, int flags) {
631        dest.writeString(mName);
632        dest.writeInt(mWidth);
633        dest.writeInt(mHeight);
634        nativeWriteToParcel(mNativeObject, dest);
635    }
636
637    /**
638     * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
639     * android.view.SurfaceControlProto}.
640     *
641     * @param proto Stream to write the SurfaceControl object to.
642     * @param fieldId Field Id of the SurfaceControl as defined in the parent message.
643     * @hide
644     */
645    public void writeToProto(ProtoOutputStream proto, long fieldId) {
646        final long token = proto.start(fieldId);
647        proto.write(HASH_CODE, System.identityHashCode(this));
648        proto.write(NAME, mName);
649        proto.end(token);
650    }
651
652    public static final Creator<SurfaceControl> CREATOR
653            = new Creator<SurfaceControl>() {
654        public SurfaceControl createFromParcel(Parcel in) {
655            return new SurfaceControl(in);
656        }
657
658        public SurfaceControl[] newArray(int size) {
659            return new SurfaceControl[size];
660        }
661    };
662
663    @Override
664    protected void finalize() throws Throwable {
665        try {
666            if (mCloseGuard != null) {
667                mCloseGuard.warnIfOpen();
668            }
669            if (mNativeObject != 0) {
670                nativeRelease(mNativeObject);
671            }
672        } finally {
673            super.finalize();
674        }
675    }
676
677    /**
678     * Release the local reference to the server-side surface.
679     * Always call release() when you're done with a Surface.
680     * This will make the surface invalid.
681     */
682    public void release() {
683        if (mNativeObject != 0) {
684            nativeRelease(mNativeObject);
685            mNativeObject = 0;
686        }
687        mCloseGuard.close();
688    }
689
690    /**
691     * Free all server-side state associated with this surface and
692     * release this object's reference.  This method can only be
693     * called from the process that created the service.
694     */
695    public void destroy() {
696        if (mNativeObject != 0) {
697            nativeDestroy(mNativeObject);
698            mNativeObject = 0;
699        }
700        mCloseGuard.close();
701    }
702
703    /**
704     * Disconnect any client still connected to the surface.
705     */
706    public void disconnect() {
707        if (mNativeObject != 0) {
708            nativeDisconnect(mNativeObject);
709        }
710    }
711
712    private void checkNotReleased() {
713        if (mNativeObject == 0) throw new NullPointerException(
714                "mNativeObject is null. Have you called release() already?");
715    }
716
717    /*
718     * set surface parameters.
719     * needs to be inside open/closeTransaction block
720     */
721
722    /** start a transaction */
723    public static void openTransaction() {
724        synchronized (SurfaceControl.class) {
725            if (sGlobalTransaction == null) {
726                sGlobalTransaction = new Transaction();
727            }
728            synchronized(SurfaceControl.class) {
729                sTransactionNestCount++;
730            }
731        }
732    }
733
734    private static void closeTransaction(boolean sync) {
735        synchronized(SurfaceControl.class) {
736            if (sTransactionNestCount == 0) {
737                Log.e(TAG, "Call to SurfaceControl.closeTransaction without matching openTransaction");
738            } else if (--sTransactionNestCount > 0) {
739                return;
740            }
741            sGlobalTransaction.apply(sync);
742        }
743    }
744
745    /**
746     * Merge the supplied transaction in to the deprecated "global" transaction.
747     * This clears the supplied transaction in an identical fashion to {@link Transaction#merge}.
748     * <p>
749     * This is a utility for interop with legacy-code and will go away with the Global Transaction.
750     */
751    @Deprecated
752    public static void mergeToGlobalTransaction(Transaction t) {
753        synchronized(SurfaceControl.class) {
754            sGlobalTransaction.merge(t);
755        }
756    }
757
758    /** end a transaction */
759    public static void closeTransaction() {
760        closeTransaction(false);
761    }
762
763    public static void closeTransactionSync() {
764        closeTransaction(true);
765    }
766
767    public void deferTransactionUntil(IBinder handle, long frame) {
768        synchronized(SurfaceControl.class) {
769            sGlobalTransaction.deferTransactionUntil(this, handle, frame);
770        }
771    }
772
773    public void deferTransactionUntil(Surface barrier, long frame) {
774        synchronized(SurfaceControl.class) {
775            sGlobalTransaction.deferTransactionUntilSurface(this, barrier, frame);
776        }
777    }
778
779    public void reparentChildren(IBinder newParentHandle) {
780        synchronized(SurfaceControl.class) {
781            sGlobalTransaction.reparentChildren(this, newParentHandle);
782        }
783    }
784
785    public void reparent(IBinder newParentHandle) {
786        synchronized(SurfaceControl.class) {
787            sGlobalTransaction.reparent(this, newParentHandle);
788        }
789    }
790
791    public void detachChildren() {
792        synchronized(SurfaceControl.class) {
793            sGlobalTransaction.detachChildren(this);
794        }
795    }
796
797    public void setOverrideScalingMode(int scalingMode) {
798        checkNotReleased();
799        synchronized(SurfaceControl.class) {
800            sGlobalTransaction.setOverrideScalingMode(this, scalingMode);
801        }
802    }
803
804    public IBinder getHandle() {
805        return nativeGetHandle(mNativeObject);
806    }
807
808    public static void setAnimationTransaction() {
809        synchronized (SurfaceControl.class) {
810            sGlobalTransaction.setAnimationTransaction();
811        }
812    }
813
814    public void setLayer(int zorder) {
815        checkNotReleased();
816        synchronized(SurfaceControl.class) {
817            sGlobalTransaction.setLayer(this, zorder);
818        }
819    }
820
821    public void setRelativeLayer(SurfaceControl relativeTo, int zorder) {
822        checkNotReleased();
823        synchronized(SurfaceControl.class) {
824            sGlobalTransaction.setRelativeLayer(this, relativeTo, zorder);
825        }
826    }
827
828    public void setPosition(float x, float y) {
829        checkNotReleased();
830        synchronized(SurfaceControl.class) {
831            sGlobalTransaction.setPosition(this, x, y);
832        }
833    }
834
835    public void setGeometryAppliesWithResize() {
836        checkNotReleased();
837        synchronized(SurfaceControl.class) {
838            sGlobalTransaction.setGeometryAppliesWithResize(this);
839        }
840    }
841
842    public void setSize(int w, int h) {
843        checkNotReleased();
844        synchronized(SurfaceControl.class) {
845            sGlobalTransaction.setSize(this, w, h);
846        }
847    }
848
849    public void hide() {
850        checkNotReleased();
851        synchronized(SurfaceControl.class) {
852            sGlobalTransaction.hide(this);
853        }
854    }
855
856    public void show() {
857        checkNotReleased();
858        synchronized(SurfaceControl.class) {
859            sGlobalTransaction.show(this);
860        }
861    }
862
863    public void setTransparentRegionHint(Region region) {
864        checkNotReleased();
865        synchronized(SurfaceControl.class) {
866            sGlobalTransaction.setTransparentRegionHint(this, region);
867        }
868    }
869
870    public boolean clearContentFrameStats() {
871        checkNotReleased();
872        return nativeClearContentFrameStats(mNativeObject);
873    }
874
875    public boolean getContentFrameStats(WindowContentFrameStats outStats) {
876        checkNotReleased();
877        return nativeGetContentFrameStats(mNativeObject, outStats);
878    }
879
880    public static boolean clearAnimationFrameStats() {
881        return nativeClearAnimationFrameStats();
882    }
883
884    public static boolean getAnimationFrameStats(WindowAnimationFrameStats outStats) {
885        return nativeGetAnimationFrameStats(outStats);
886    }
887
888    public void setAlpha(float alpha) {
889        checkNotReleased();
890        synchronized(SurfaceControl.class) {
891            sGlobalTransaction.setAlpha(this, alpha);
892        }
893    }
894
895    public void setColor(@Size(3) float[] color) {
896        checkNotReleased();
897        synchronized (SurfaceControl.class) {
898            sGlobalTransaction.setColor(this, color);
899        }
900    }
901
902    public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
903        checkNotReleased();
904        synchronized(SurfaceControl.class) {
905            sGlobalTransaction.setMatrix(this, dsdx, dtdx, dtdy, dsdy);
906        }
907    }
908
909    /**
910     * Sets the transform and position of a {@link SurfaceControl} from a 3x3 transformation matrix.
911     *
912     * @param matrix The matrix to apply.
913     * @param float9 An array of 9 floats to be used to extract the values from the matrix.
914     */
915    public void setMatrix(Matrix matrix, float[] float9) {
916        checkNotReleased();
917        matrix.getValues(float9);
918        synchronized (SurfaceControl.class) {
919            sGlobalTransaction.setMatrix(this, float9[MSCALE_X], float9[MSKEW_Y],
920                    float9[MSKEW_X], float9[MSCALE_Y]);
921            sGlobalTransaction.setPosition(this, float9[MTRANS_X], float9[MTRANS_Y]);
922        }
923    }
924
925    public void setWindowCrop(Rect crop) {
926        checkNotReleased();
927        synchronized (SurfaceControl.class) {
928            sGlobalTransaction.setWindowCrop(this, crop);
929        }
930    }
931
932    public void setFinalCrop(Rect crop) {
933        checkNotReleased();
934        synchronized (SurfaceControl.class) {
935            sGlobalTransaction.setFinalCrop(this, crop);
936        }
937    }
938
939    public void setLayerStack(int layerStack) {
940        checkNotReleased();
941        synchronized(SurfaceControl.class) {
942            sGlobalTransaction.setLayerStack(this, layerStack);
943        }
944    }
945
946    public void setOpaque(boolean isOpaque) {
947        checkNotReleased();
948
949        synchronized (SurfaceControl.class) {
950            sGlobalTransaction.setOpaque(this, isOpaque);
951        }
952    }
953
954    public void setSecure(boolean isSecure) {
955        checkNotReleased();
956
957        synchronized (SurfaceControl.class) {
958            sGlobalTransaction.setSecure(this, isSecure);
959        }
960    }
961
962    public int getWidth() {
963        synchronized (mSizeLock) {
964            return mWidth;
965        }
966    }
967
968    public int getHeight() {
969        synchronized (mSizeLock) {
970            return mHeight;
971        }
972    }
973
974    @Override
975    public String toString() {
976        return "Surface(name=" + mName + ")/@0x" +
977                Integer.toHexString(System.identityHashCode(this));
978    }
979
980    /*
981     * set display parameters.
982     * needs to be inside open/closeTransaction block
983     */
984
985    /**
986     * Describes the properties of a physical display known to surface flinger.
987     */
988    public static final class PhysicalDisplayInfo {
989        public int width;
990        public int height;
991        public float refreshRate;
992        public float density;
993        public float xDpi;
994        public float yDpi;
995        public boolean secure;
996        public long appVsyncOffsetNanos;
997        public long presentationDeadlineNanos;
998
999        public PhysicalDisplayInfo() {
1000        }
1001
1002        public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
1003            copyFrom(other);
1004        }
1005
1006        @Override
1007        public boolean equals(Object o) {
1008            return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
1009        }
1010
1011        public boolean equals(PhysicalDisplayInfo other) {
1012            return other != null
1013                    && width == other.width
1014                    && height == other.height
1015                    && refreshRate == other.refreshRate
1016                    && density == other.density
1017                    && xDpi == other.xDpi
1018                    && yDpi == other.yDpi
1019                    && secure == other.secure
1020                    && appVsyncOffsetNanos == other.appVsyncOffsetNanos
1021                    && presentationDeadlineNanos == other.presentationDeadlineNanos;
1022        }
1023
1024        @Override
1025        public int hashCode() {
1026            return 0; // don't care
1027        }
1028
1029        public void copyFrom(PhysicalDisplayInfo other) {
1030            width = other.width;
1031            height = other.height;
1032            refreshRate = other.refreshRate;
1033            density = other.density;
1034            xDpi = other.xDpi;
1035            yDpi = other.yDpi;
1036            secure = other.secure;
1037            appVsyncOffsetNanos = other.appVsyncOffsetNanos;
1038            presentationDeadlineNanos = other.presentationDeadlineNanos;
1039        }
1040
1041        // For debugging purposes
1042        @Override
1043        public String toString() {
1044            return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
1045                    + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
1046                    + ", appVsyncOffset " + appVsyncOffsetNanos
1047                    + ", bufferDeadline " + presentationDeadlineNanos + "}";
1048        }
1049    }
1050
1051    public static void setDisplayPowerMode(IBinder displayToken, int mode) {
1052        if (displayToken == null) {
1053            throw new IllegalArgumentException("displayToken must not be null");
1054        }
1055        nativeSetDisplayPowerMode(displayToken, mode);
1056    }
1057
1058    public static SurfaceControl.PhysicalDisplayInfo[] getDisplayConfigs(IBinder displayToken) {
1059        if (displayToken == null) {
1060            throw new IllegalArgumentException("displayToken must not be null");
1061        }
1062        return nativeGetDisplayConfigs(displayToken);
1063    }
1064
1065    public static int getActiveConfig(IBinder displayToken) {
1066        if (displayToken == null) {
1067            throw new IllegalArgumentException("displayToken must not be null");
1068        }
1069        return nativeGetActiveConfig(displayToken);
1070    }
1071
1072    public static boolean setActiveConfig(IBinder displayToken, int id) {
1073        if (displayToken == null) {
1074            throw new IllegalArgumentException("displayToken must not be null");
1075        }
1076        return nativeSetActiveConfig(displayToken, id);
1077    }
1078
1079    public static int[] getDisplayColorModes(IBinder displayToken) {
1080        if (displayToken == null) {
1081            throw new IllegalArgumentException("displayToken must not be null");
1082        }
1083        return nativeGetDisplayColorModes(displayToken);
1084    }
1085
1086    public static int getActiveColorMode(IBinder displayToken) {
1087        if (displayToken == null) {
1088            throw new IllegalArgumentException("displayToken must not be null");
1089        }
1090        return nativeGetActiveColorMode(displayToken);
1091    }
1092
1093    public static boolean setActiveColorMode(IBinder displayToken, int colorMode) {
1094        if (displayToken == null) {
1095            throw new IllegalArgumentException("displayToken must not be null");
1096        }
1097        return nativeSetActiveColorMode(displayToken, colorMode);
1098    }
1099
1100    public static void setDisplayProjection(IBinder displayToken,
1101            int orientation, Rect layerStackRect, Rect displayRect) {
1102        synchronized (SurfaceControl.class) {
1103            sGlobalTransaction.setDisplayProjection(displayToken, orientation,
1104                    layerStackRect, displayRect);
1105        }
1106    }
1107
1108    public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
1109        synchronized (SurfaceControl.class) {
1110            sGlobalTransaction.setDisplayLayerStack(displayToken, layerStack);
1111        }
1112    }
1113
1114    public static void setDisplaySurface(IBinder displayToken, Surface surface) {
1115        synchronized (SurfaceControl.class) {
1116            sGlobalTransaction.setDisplaySurface(displayToken, surface);
1117        }
1118    }
1119
1120    public static void setDisplaySize(IBinder displayToken, int width, int height) {
1121        synchronized (SurfaceControl.class) {
1122            sGlobalTransaction.setDisplaySize(displayToken, width, height);
1123        }
1124    }
1125
1126    public static Display.HdrCapabilities getHdrCapabilities(IBinder displayToken) {
1127        if (displayToken == null) {
1128            throw new IllegalArgumentException("displayToken must not be null");
1129        }
1130        return nativeGetHdrCapabilities(displayToken);
1131    }
1132
1133    public static IBinder createDisplay(String name, boolean secure) {
1134        if (name == null) {
1135            throw new IllegalArgumentException("name must not be null");
1136        }
1137        return nativeCreateDisplay(name, secure);
1138    }
1139
1140    public static void destroyDisplay(IBinder displayToken) {
1141        if (displayToken == null) {
1142            throw new IllegalArgumentException("displayToken must not be null");
1143        }
1144        nativeDestroyDisplay(displayToken);
1145    }
1146
1147    public static IBinder getBuiltInDisplay(int builtInDisplayId) {
1148        return nativeGetBuiltInDisplay(builtInDisplayId);
1149    }
1150
1151    /**
1152     * Copy the current screen contents into the provided {@link Surface}
1153     *
1154     * @param display The display to take the screenshot of.
1155     * @param consumer The {@link Surface} to take the screenshot into.
1156     * @param width The desired width of the returned bitmap; the raw
1157     * screen will be scaled down to this size.
1158     * @param height The desired height of the returned bitmap; the raw
1159     * screen will be scaled down to this size.
1160     * @param minLayer The lowest (bottom-most Z order) surface layer to
1161     * include in the screenshot.
1162     * @param maxLayer The highest (top-most Z order) surface layer to
1163     * include in the screenshot.
1164     * @param useIdentityTransform Replace whatever transformation (rotation,
1165     * scaling, translation) the surface layers are currently using with the
1166     * identity transformation while taking the screenshot.
1167     */
1168    public static void screenshot(IBinder display, Surface consumer,
1169            int width, int height, int minLayer, int maxLayer,
1170            boolean useIdentityTransform) {
1171        screenshot(display, consumer, new Rect(), width, height, minLayer, maxLayer,
1172                false, useIdentityTransform);
1173    }
1174
1175    /**
1176     * Copy the current screen contents into the provided {@link Surface}
1177     *
1178     * @param display The display to take the screenshot of.
1179     * @param consumer The {@link Surface} to take the screenshot into.
1180     * @param width The desired width of the returned bitmap; the raw
1181     * screen will be scaled down to this size.
1182     * @param height The desired height of the returned bitmap; the raw
1183     * screen will be scaled down to this size.
1184     */
1185    public static void screenshot(IBinder display, Surface consumer,
1186            int width, int height) {
1187        screenshot(display, consumer, new Rect(), width, height, 0, 0, true, false);
1188    }
1189
1190    /**
1191     * Copy the current screen contents into the provided {@link Surface}
1192     *
1193     * @param display The display to take the screenshot of.
1194     * @param consumer The {@link Surface} to take the screenshot into.
1195     */
1196    public static void screenshot(IBinder display, Surface consumer) {
1197        screenshot(display, consumer, new Rect(), 0, 0, 0, 0, true, false);
1198    }
1199
1200    /**
1201     * Copy the current screen contents into a hardware bitmap and return it.
1202     * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap into
1203     * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
1204     *
1205     * CAVEAT: Versions of screenshot that return a {@link Bitmap} can
1206     * be extremely slow; avoid use unless absolutely necessary; prefer
1207     * the versions that use a {@link Surface} instead, such as
1208     * {@link SurfaceControl#screenshot(IBinder, Surface)}.
1209     *
1210     * @param sourceCrop The portion of the screen to capture into the Bitmap;
1211     * caller may pass in 'new Rect()' if no cropping is desired.
1212     * @param width The desired width of the returned bitmap; the raw
1213     * screen will be scaled down to this size.
1214     * @param height The desired height of the returned bitmap; the raw
1215     * screen will be scaled down to this size.
1216     * @param minLayer The lowest (bottom-most Z order) surface layer to
1217     * include in the screenshot.
1218     * @param maxLayer The highest (top-most Z order) surface layer to
1219     * include in the screenshot.
1220     * @param useIdentityTransform Replace whatever transformation (rotation,
1221     * scaling, translation) the surface layers are currently using with the
1222     * identity transformation while taking the screenshot.
1223     * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
1224     * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take
1225     * screenshots in its native portrait orientation by default, so this is
1226     * useful for returning screenshots that are independent of device
1227     * orientation.
1228     * @return Returns a hardware Bitmap containing the screen contents, or null
1229     * if an error occurs. Make sure to call Bitmap.recycle() as soon as
1230     * possible, once its content is not needed anymore.
1231     */
1232    public static Bitmap screenshot(Rect sourceCrop, int width, int height,
1233            int minLayer, int maxLayer, boolean useIdentityTransform,
1234            int rotation) {
1235        // TODO: should take the display as a parameter
1236        IBinder displayToken = SurfaceControl.getBuiltInDisplay(
1237                SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
1238        return nativeScreenshot(displayToken, sourceCrop, width, height,
1239                minLayer, maxLayer, false, useIdentityTransform, rotation);
1240    }
1241
1242    /**
1243     * Like {@link SurfaceControl#screenshot(Rect, int, int, int, int, boolean, int)}
1244     * but returns a GraphicBuffer.
1245     */
1246    public static GraphicBuffer screenshotToBuffer(Rect sourceCrop, int width, int height,
1247            int minLayer, int maxLayer, boolean useIdentityTransform,
1248            int rotation) {
1249        IBinder displayToken = SurfaceControl.getBuiltInDisplay(
1250                SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
1251        return nativeScreenshotToBuffer(displayToken, sourceCrop, width, height,
1252                minLayer, maxLayer, false, useIdentityTransform, rotation);
1253    }
1254
1255    /**
1256     * Like {@link SurfaceControl#screenshot(Rect, int, int, int, int, boolean, int)} but
1257     * includes all Surfaces in the screenshot. This will also update the orientation so it
1258     * sends the correct coordinates to SF based on the rotation value.
1259     *
1260     * @param sourceCrop The portion of the screen to capture into the Bitmap;
1261     * caller may pass in 'new Rect()' if no cropping is desired.
1262     * @param width The desired width of the returned bitmap; the raw
1263     * screen will be scaled down to this size.
1264     * @param height The desired height of the returned bitmap; the raw
1265     * screen will be scaled down to this size.
1266     * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
1267     * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take
1268     * screenshots in its native portrait orientation by default, so this is
1269     * useful for returning screenshots that are independent of device
1270     * orientation.
1271     * @return Returns a Bitmap containing the screen contents, or null
1272     * if an error occurs. Make sure to call Bitmap.recycle() as soon as
1273     * possible, once its content is not needed anymore.
1274     */
1275    public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
1276        // TODO: should take the display as a parameter
1277        IBinder displayToken = SurfaceControl.getBuiltInDisplay(
1278                SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
1279        if (rotation == ROTATION_90 || rotation == ROTATION_270) {
1280            rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
1281        }
1282
1283        SurfaceControl.rotateCropForSF(sourceCrop, rotation);
1284        return nativeScreenshot(displayToken, sourceCrop, width, height, 0, 0, true,
1285                false, rotation);
1286    }
1287
1288    private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
1289            int width, int height, int minLayer, int maxLayer, boolean allLayers,
1290            boolean useIdentityTransform) {
1291        if (display == null) {
1292            throw new IllegalArgumentException("displayToken must not be null");
1293        }
1294        if (consumer == null) {
1295            throw new IllegalArgumentException("consumer must not be null");
1296        }
1297        nativeScreenshot(display, consumer, sourceCrop, width, height,
1298                minLayer, maxLayer, allLayers, useIdentityTransform);
1299    }
1300
1301    private static void rotateCropForSF(Rect crop, int rot) {
1302        if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
1303            int tmp = crop.top;
1304            crop.top = crop.left;
1305            crop.left = tmp;
1306            tmp = crop.right;
1307            crop.right = crop.bottom;
1308            crop.bottom = tmp;
1309        }
1310    }
1311
1312    /**
1313     * Captures a layer and its children and returns a {@link GraphicBuffer} with the content.
1314     *
1315     * @param layerHandleToken The root layer to capture.
1316     * @param sourceCrop       The portion of the root surface to capture; caller may pass in 'new
1317     *                         Rect()' or null if no cropping is desired.
1318     * @param frameScale       The desired scale of the returned buffer; the raw
1319     *                         screen will be scaled up/down.
1320     *
1321     * @return Returns a GraphicBuffer that contains the layer capture.
1322     */
1323    public static GraphicBuffer captureLayers(IBinder layerHandleToken, Rect sourceCrop,
1324            float frameScale) {
1325        return nativeCaptureLayers(layerHandleToken, sourceCrop, frameScale);
1326    }
1327
1328    public static class Transaction implements Closeable {
1329        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
1330                Transaction.class.getClassLoader(),
1331                nativeGetNativeTransactionFinalizer(), 512);
1332        private long mNativeObject;
1333
1334        private final ArrayMap<SurfaceControl, Point> mResizedSurfaces = new ArrayMap<>();
1335        Runnable mFreeNativeResources;
1336
1337        public Transaction() {
1338            mNativeObject = nativeCreateTransaction();
1339            mFreeNativeResources
1340                = sRegistry.registerNativeAllocation(this, mNativeObject);
1341        }
1342
1343        /**
1344         * Apply the transaction, clearing it's state, and making it usable
1345         * as a new transaction.
1346         */
1347        public void apply() {
1348            apply(false);
1349        }
1350
1351        /**
1352         * Close the transaction, if the transaction was not already applied this will cancel the
1353         * transaction.
1354         */
1355        @Override
1356        public void close() {
1357            mFreeNativeResources.run();
1358            mNativeObject = 0;
1359        }
1360
1361        /**
1362         * Jankier version of apply. Avoid use (b/28068298).
1363         */
1364        public void apply(boolean sync) {
1365            applyResizedSurfaces();
1366            nativeApplyTransaction(mNativeObject, sync);
1367        }
1368
1369        private void applyResizedSurfaces() {
1370            for (int i = mResizedSurfaces.size() - 1; i >= 0; i--) {
1371                final Point size = mResizedSurfaces.valueAt(i);
1372                final SurfaceControl surfaceControl = mResizedSurfaces.keyAt(i);
1373                synchronized (surfaceControl.mSizeLock) {
1374                    surfaceControl.mWidth = size.x;
1375                    surfaceControl.mHeight = size.y;
1376                }
1377            }
1378            mResizedSurfaces.clear();
1379        }
1380
1381        public Transaction show(SurfaceControl sc) {
1382            sc.checkNotReleased();
1383            nativeSetFlags(mNativeObject, sc.mNativeObject, 0, SURFACE_HIDDEN);
1384            return this;
1385        }
1386
1387        public Transaction hide(SurfaceControl sc) {
1388            sc.checkNotReleased();
1389            nativeSetFlags(mNativeObject, sc.mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
1390            return this;
1391        }
1392
1393        public Transaction setPosition(SurfaceControl sc, float x, float y) {
1394            sc.checkNotReleased();
1395            nativeSetPosition(mNativeObject, sc.mNativeObject, x, y);
1396            return this;
1397        }
1398
1399        public Transaction setSize(SurfaceControl sc, int w, int h) {
1400            sc.checkNotReleased();
1401            mResizedSurfaces.put(sc, new Point(w, h));
1402            nativeSetSize(mNativeObject, sc.mNativeObject, w, h);
1403            return this;
1404        }
1405
1406        public Transaction setLayer(SurfaceControl sc, int z) {
1407            sc.checkNotReleased();
1408            nativeSetLayer(mNativeObject, sc.mNativeObject, z);
1409            return this;
1410        }
1411
1412        public Transaction setRelativeLayer(SurfaceControl sc, SurfaceControl relativeTo, int z) {
1413            sc.checkNotReleased();
1414            nativeSetRelativeLayer(mNativeObject, sc.mNativeObject,
1415                    relativeTo.getHandle(), z);
1416            return this;
1417        }
1418
1419        public Transaction setTransparentRegionHint(SurfaceControl sc, Region transparentRegion) {
1420            sc.checkNotReleased();
1421            nativeSetTransparentRegionHint(mNativeObject,
1422                    sc.mNativeObject, transparentRegion);
1423            return this;
1424        }
1425
1426        public Transaction setAlpha(SurfaceControl sc, float alpha) {
1427            sc.checkNotReleased();
1428            nativeSetAlpha(mNativeObject, sc.mNativeObject, alpha);
1429            return this;
1430        }
1431
1432        public Transaction setMatrix(SurfaceControl sc,
1433                float dsdx, float dtdx, float dtdy, float dsdy) {
1434            sc.checkNotReleased();
1435            nativeSetMatrix(mNativeObject, sc.mNativeObject,
1436                    dsdx, dtdx, dtdy, dsdy);
1437            return this;
1438        }
1439
1440        public Transaction setMatrix(SurfaceControl sc, Matrix matrix, float[] float9) {
1441            matrix.getValues(float9);
1442            setMatrix(sc, float9[MSCALE_X], float9[MSKEW_Y],
1443                    float9[MSKEW_X], float9[MSCALE_Y]);
1444            setPosition(sc, float9[MTRANS_X], float9[MTRANS_Y]);
1445            return this;
1446        }
1447
1448        public Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
1449            sc.checkNotReleased();
1450            if (crop != null) {
1451                nativeSetWindowCrop(mNativeObject, sc.mNativeObject,
1452                        crop.left, crop.top, crop.right, crop.bottom);
1453            } else {
1454                nativeSetWindowCrop(mNativeObject, sc.mNativeObject, 0, 0, 0, 0);
1455            }
1456
1457            return this;
1458        }
1459
1460        public Transaction setFinalCrop(SurfaceControl sc, Rect crop) {
1461            sc.checkNotReleased();
1462            if (crop != null) {
1463                nativeSetFinalCrop(mNativeObject, sc.mNativeObject,
1464                        crop.left, crop.top, crop.right, crop.bottom);
1465            } else {
1466                nativeSetFinalCrop(mNativeObject, sc.mNativeObject, 0, 0, 0, 0);
1467            }
1468
1469            return this;
1470        }
1471
1472        public Transaction setLayerStack(SurfaceControl sc, int layerStack) {
1473            sc.checkNotReleased();
1474            nativeSetLayerStack(mNativeObject, sc.mNativeObject, layerStack);
1475            return this;
1476        }
1477
1478        public Transaction deferTransactionUntil(SurfaceControl sc, IBinder handle,
1479                long frameNumber) {
1480            if (frameNumber < 0) {
1481                return this;
1482            }
1483            sc.checkNotReleased();
1484            nativeDeferTransactionUntil(mNativeObject, sc.mNativeObject, handle, frameNumber);
1485            return this;
1486        }
1487
1488        public Transaction deferTransactionUntilSurface(SurfaceControl sc, Surface barrierSurface,
1489                long frameNumber) {
1490            if (frameNumber < 0) {
1491                return this;
1492            }
1493            sc.checkNotReleased();
1494            nativeDeferTransactionUntilSurface(mNativeObject, sc.mNativeObject,
1495                    barrierSurface.mNativeObject, frameNumber);
1496            return this;
1497        }
1498
1499        public Transaction reparentChildren(SurfaceControl sc, IBinder newParentHandle) {
1500            sc.checkNotReleased();
1501            nativeReparentChildren(mNativeObject, sc.mNativeObject, newParentHandle);
1502            return this;
1503        }
1504
1505        /** Re-parents a specific child layer to a new parent */
1506        public Transaction reparent(SurfaceControl sc, IBinder newParentHandle) {
1507            sc.checkNotReleased();
1508            nativeReparent(mNativeObject, sc.mNativeObject,
1509                    newParentHandle);
1510            return this;
1511        }
1512
1513        public Transaction detachChildren(SurfaceControl sc) {
1514            sc.checkNotReleased();
1515            nativeSeverChildren(mNativeObject, sc.mNativeObject);
1516            return this;
1517        }
1518
1519        public Transaction setOverrideScalingMode(SurfaceControl sc, int overrideScalingMode) {
1520            sc.checkNotReleased();
1521            nativeSetOverrideScalingMode(mNativeObject, sc.mNativeObject,
1522                    overrideScalingMode);
1523            return this;
1524        }
1525
1526        /**
1527         * Sets a color for the Surface.
1528         * @param color A float array with three values to represent r, g, b in range [0..1]
1529         */
1530        public Transaction setColor(SurfaceControl sc, @Size(3) float[] color) {
1531            sc.checkNotReleased();
1532            nativeSetColor(mNativeObject, sc.mNativeObject, color);
1533            return this;
1534        }
1535
1536        /**
1537         * If the buffer size changes in this transaction, position and crop updates specified
1538         * in this transaction will not complete until a buffer of the new size
1539         * arrives. As transform matrix and size are already frozen in this fashion,
1540         * this enables totally freezing the surface until the resize has completed
1541         * (at which point the geometry influencing aspects of this transaction will then occur)
1542         */
1543        public Transaction setGeometryAppliesWithResize(SurfaceControl sc) {
1544            sc.checkNotReleased();
1545            nativeSetGeometryAppliesWithResize(mNativeObject, sc.mNativeObject);
1546            return this;
1547        }
1548
1549        /**
1550         * Sets the security of the surface.  Setting the flag is equivalent to creating the
1551         * Surface with the {@link #SECURE} flag.
1552         */
1553        public Transaction setSecure(SurfaceControl sc, boolean isSecure) {
1554            sc.checkNotReleased();
1555            if (isSecure) {
1556                nativeSetFlags(mNativeObject, sc.mNativeObject, SECURE, SECURE);
1557            } else {
1558                nativeSetFlags(mNativeObject, sc.mNativeObject, 0, SECURE);
1559            }
1560            return this;
1561        }
1562
1563        /**
1564         * Sets the opacity of the surface.  Setting the flag is equivalent to creating the
1565         * Surface with the {@link #OPAQUE} flag.
1566         */
1567        public Transaction setOpaque(SurfaceControl sc, boolean isOpaque) {
1568            sc.checkNotReleased();
1569            if (isOpaque) {
1570                nativeSetFlags(mNativeObject, sc.mNativeObject, SURFACE_OPAQUE, SURFACE_OPAQUE);
1571            } else {
1572                nativeSetFlags(mNativeObject, sc.mNativeObject, 0, SURFACE_OPAQUE);
1573            }
1574            return this;
1575        }
1576
1577        /**
1578         * Same as {@link #destroy()} except this is invoked in a transaction instead of
1579         * immediately.
1580         */
1581        public Transaction destroy(SurfaceControl sc) {
1582            sc.checkNotReleased();
1583            nativeDestroy(mNativeObject, sc.mNativeObject);
1584            return this;
1585        }
1586
1587        public Transaction setDisplaySurface(IBinder displayToken, Surface surface) {
1588            if (displayToken == null) {
1589                throw new IllegalArgumentException("displayToken must not be null");
1590            }
1591
1592            if (surface != null) {
1593                synchronized (surface.mLock) {
1594                    nativeSetDisplaySurface(mNativeObject, displayToken, surface.mNativeObject);
1595                }
1596            } else {
1597                nativeSetDisplaySurface(mNativeObject, displayToken, 0);
1598            }
1599            return this;
1600        }
1601
1602        public Transaction setDisplayLayerStack(IBinder displayToken, int layerStack) {
1603            if (displayToken == null) {
1604                throw new IllegalArgumentException("displayToken must not be null");
1605            }
1606            nativeSetDisplayLayerStack(mNativeObject, displayToken, layerStack);
1607            return this;
1608        }
1609
1610        public Transaction setDisplayProjection(IBinder displayToken,
1611                int orientation, Rect layerStackRect, Rect displayRect) {
1612            if (displayToken == null) {
1613                throw new IllegalArgumentException("displayToken must not be null");
1614            }
1615            if (layerStackRect == null) {
1616                throw new IllegalArgumentException("layerStackRect must not be null");
1617            }
1618            if (displayRect == null) {
1619                throw new IllegalArgumentException("displayRect must not be null");
1620            }
1621            nativeSetDisplayProjection(mNativeObject, displayToken, orientation,
1622                    layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom,
1623                    displayRect.left, displayRect.top, displayRect.right, displayRect.bottom);
1624            return this;
1625        }
1626
1627        public Transaction setDisplaySize(IBinder displayToken, int width, int height) {
1628            if (displayToken == null) {
1629                throw new IllegalArgumentException("displayToken must not be null");
1630            }
1631            if (width <= 0 || height <= 0) {
1632                throw new IllegalArgumentException("width and height must be positive");
1633            }
1634
1635            nativeSetDisplaySize(mNativeObject, displayToken, width, height);
1636            return this;
1637        }
1638
1639        /** flag the transaction as an animation */
1640        public Transaction setAnimationTransaction() {
1641            nativeSetAnimationTransaction(mNativeObject);
1642            return this;
1643        }
1644
1645        /**
1646         * Indicate that SurfaceFlinger should wake up earlier than usual as a result of this
1647         * transaction. This should be used when the caller thinks that the scene is complex enough
1648         * that it's likely to hit GL composition, and thus, SurfaceFlinger needs to more time in
1649         * order not to miss frame deadlines.
1650         * <p>
1651         * Corresponds to setting ISurfaceComposer::eEarlyWakeup
1652         */
1653        public Transaction setEarlyWakeup() {
1654            nativeSetEarlyWakeup(mNativeObject);
1655            return this;
1656        }
1657
1658        /**
1659         * Merge the other transaction into this transaction, clearing the
1660         * other transaction as if it had been applied.
1661         */
1662        public Transaction merge(Transaction other) {
1663            mResizedSurfaces.putAll(other.mResizedSurfaces);
1664            other.mResizedSurfaces.clear();
1665            nativeMergeTransaction(mNativeObject, other.mNativeObject);
1666            return this;
1667        }
1668    }
1669}
1670