TextureView.java revision 2af3524beb75150d347accc925022daa53b4a789
1/*
2 * Copyright (C) 2011 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 android.content.Context;
20import android.graphics.Bitmap;
21import android.graphics.Canvas;
22import android.graphics.Matrix;
23import android.graphics.Paint;
24import android.graphics.Rect;
25import android.graphics.SurfaceTexture;
26import android.util.AttributeSet;
27import android.util.Log;
28
29/**
30 * <p>A TextureView can be used to display a content stream. Such a content
31 * stream can for instance be a video or an OpenGL scene. The content stream
32 * can come from the application's process as well as a remote process.</p>
33 *
34 * <p>TextureView can only be used in a hardware accelerated window. When
35 * rendered in software, TextureView will draw nothing.</p>
36 *
37 * <p>Unlike {@link SurfaceView}, TextureView does not create a separate
38 * window but behaves as a regular View. This key difference allows a
39 * TextureView to be moved, transformed, animated, etc. For instance, you
40 * can make a TextureView semi-translucent by calling
41 * <code>myView.setAlpha(0.5f)</code>.</p>
42 *
43 * <p>Using a TextureView is simple: all you need to do is get its
44 * {@link SurfaceTexture}. The {@link SurfaceTexture} can then be used to
45 * render content. The following example demonstrates how to render the
46 * camera preview into a TextureView:</p>
47 *
48 * <pre>
49 *  public class LiveCameraActivity extends Activity implements TextureView.SurfaceTextureListener {
50 *      private Camera mCamera;
51 *      private TextureView mTextureView;
52 *
53 *      protected void onCreate(Bundle savedInstanceState) {
54 *          super.onCreate(savedInstanceState);
55 *
56 *          mTextureView = new TextureView(this);
57 *          mTextureView.setSurfaceTextureListener(this);
58 *
59 *          setContentView(mTextureView);
60 *      }
61 *
62 *      public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
63 *          mCamera = Camera.open();
64 *
65 *          try {
66 *              mCamera.setPreviewTexture(surface);
67 *              mCamera.startPreview();
68 *          } catch (IOException ioe) {
69 *              // Something bad happened
70 *          }
71 *      }
72 *
73 *      public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
74 *          // Ignored, Camera does all the work for us
75 *      }
76 *
77 *      public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
78 *          mCamera.stopPreview();
79 *          mCamera.release();
80 *          return true;
81 *      }
82 *
83 *      public void onSurfaceTextureUpdated(SurfaceTexture surface) {
84 *          // Invoked every time there's a new Camera preview frame
85 *      }
86 *  }
87 * </pre>
88 *
89 * <p>A TextureView's SurfaceTexture can be obtained either by invoking
90 * {@link #getSurfaceTexture()} or by using a {@link SurfaceTextureListener}.
91 * It is important to know that a SurfaceTexture is available only after the
92 * TextureView is attached to a window (and {@link #onAttachedToWindow()} has
93 * been invoked.) It is therefore highly recommended you use a listener to
94 * be notified when the SurfaceTexture becomes available.</p>
95 *
96 * <p>It is important to note that only one producer can use the TextureView.
97 * For instance, if you use a TextureView to display the camera preview, you
98 * cannot use {@link #lockCanvas()} to draw onto the TextureView at the same
99 * time.</p>
100 *
101 * @see SurfaceView
102 * @see SurfaceTexture
103 */
104public class TextureView extends View {
105    private static final String LOG_TAG = "TextureView";
106
107    private HardwareLayer mLayer;
108    private SurfaceTexture mSurface;
109    private SurfaceTextureListener mListener;
110
111    private boolean mOpaque = true;
112
113    private final Matrix mMatrix = new Matrix();
114    private boolean mMatrixChanged;
115
116    private final Object[] mLock = new Object[0];
117    private boolean mUpdateLayer;
118    private boolean mUpdateSurface;
119
120    private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
121
122    private Canvas mCanvas;
123    private int mSaveCount;
124
125    private final Object[] mNativeWindowLock = new Object[0];
126    // Used from native code, do not write!
127    @SuppressWarnings({"UnusedDeclaration"})
128    private int mNativeWindow;
129
130    /**
131     * Creates a new TextureView.
132     *
133     * @param context The context to associate this view with.
134     */
135    public TextureView(Context context) {
136        super(context);
137        init();
138    }
139
140    /**
141     * Creates a new TextureView.
142     *
143     * @param context The context to associate this view with.
144     * @param attrs The attributes of the XML tag that is inflating the view.
145     */
146    @SuppressWarnings({"UnusedDeclaration"})
147    public TextureView(Context context, AttributeSet attrs) {
148        super(context, attrs);
149        init();
150    }
151
152    /**
153     * Creates a new TextureView.
154     *
155     * @param context The context to associate this view with.
156     * @param attrs The attributes of the XML tag that is inflating the view.
157     * @param defStyle The default style to apply to this view. If 0, no style
158     *        will be applied (beyond what is included in the theme). This may
159     *        either be an attribute resource, whose value will be retrieved
160     *        from the current theme, or an explicit style resource.
161     */
162    @SuppressWarnings({"UnusedDeclaration"})
163    public TextureView(Context context, AttributeSet attrs, int defStyle) {
164        super(context, attrs, defStyle);
165        init();
166    }
167
168    private void init() {
169        mLayerPaint = new Paint();
170    }
171
172    /**
173     * {@inheritDoc}
174     */
175    @Override
176    public boolean isOpaque() {
177        return mOpaque;
178    }
179
180    /**
181     * Indicates whether the content of this TextureView is opaque. The
182     * content is assumed to be opaque by default.
183     *
184     * @param opaque True if the content of this TextureView is opaque,
185     *               false otherwise
186     */
187    public void setOpaque(boolean opaque) {
188        if (opaque != mOpaque) {
189            mOpaque = opaque;
190            updateLayer();
191        }
192    }
193
194    @Override
195    protected void onAttachedToWindow() {
196        super.onAttachedToWindow();
197
198        if (!isHardwareAccelerated()) {
199            Log.w(LOG_TAG, "A TextureView or a subclass can only be "
200                    + "used with hardware acceleration enabled.");
201        }
202    }
203
204    @Override
205    protected void onDetachedFromWindow() {
206        super.onDetachedFromWindow();
207        destroySurface();
208    }
209
210    private void destroySurface() {
211        if (mLayer != null) {
212            mSurface.detachFromGLContext();
213
214            boolean shouldRelease = true;
215            if (mListener != null) {
216                shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
217            }
218
219            synchronized (mNativeWindowLock) {
220                nDestroyNativeWindow();
221            }
222
223            mLayer.destroy();
224            if (shouldRelease) mSurface.release();
225            mSurface = null;
226            mLayer = null;
227        }
228    }
229
230    /**
231     * The layer type of a TextureView is ignored since a TextureView is always
232     * considered to act as a hardware layer. The optional paint supplied to this
233     * method will however be taken into account when rendering the content of
234     * this TextureView.
235     *
236     * @param layerType The ype of layer to use with this view, must be one of
237     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
238     *        {@link #LAYER_TYPE_HARDWARE}
239     * @param paint The paint used to compose the layer. This argument is optional
240     *        and can be null. It is ignored when the layer type is
241     *        {@link #LAYER_TYPE_NONE}
242     */
243    @Override
244    public void setLayerType(int layerType, Paint paint) {
245        if (paint != mLayerPaint) {
246            mLayerPaint = paint;
247            invalidate();
248        }
249    }
250
251    /**
252     * Always returns {@link #LAYER_TYPE_HARDWARE}.
253     */
254    @Override
255    public int getLayerType() {
256        return LAYER_TYPE_HARDWARE;
257    }
258
259    @Override
260    boolean hasStaticLayer() {
261        return true;
262    }
263
264    /**
265     * Calling this method has no effect.
266     */
267    @Override
268    public void buildLayer() {
269    }
270
271    /**
272     * Subclasses of TextureView cannot do their own rendering
273     * with the {@link Canvas} object.
274     *
275     * @param canvas The Canvas to which the View is rendered.
276     */
277    @Override
278    public final void draw(Canvas canvas) {
279        applyUpdate();
280        applyTransformMatrix();
281    }
282
283    /**
284     * Subclasses of TextureView cannot do their own rendering
285     * with the {@link Canvas} object.
286     *
287     * @param canvas The Canvas to which the View is rendered.
288     */
289    @Override
290    protected final void onDraw(Canvas canvas) {
291    }
292
293    @Override
294    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
295        super.onSizeChanged(w, h, oldw, oldh);
296        if (mSurface != null) {
297            nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
298            if (mListener != null) {
299                mListener.onSurfaceTextureSizeChanged(mSurface, getWidth(), getHeight());
300            }
301        }
302    }
303
304    @Override
305    boolean destroyLayer(boolean valid) {
306        return false;
307    }
308
309    /**
310     * @hide
311     */
312    @Override
313    protected void destroyHardwareResources() {
314        super.destroyHardwareResources();
315        destroySurface();
316        invalidateParentCaches();
317        invalidate(true);
318    }
319
320    @Override
321    HardwareLayer getHardwareLayer() {
322        if (mLayer == null) {
323            if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
324                return null;
325            }
326
327            mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque);
328            if (!mUpdateSurface) {
329                // We already have a SurfaceTexture to use, and we will pass it
330                // to mLayer below.
331                mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
332            }
333            nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
334            nCreateNativeWindow(mSurface);
335
336            mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() {
337                @Override
338                public void onFrameAvailable(SurfaceTexture surfaceTexture) {
339                    // Per SurfaceTexture's documentation, the callback may be invoked
340                    // from an arbitrary thread
341                    synchronized (mLock) {
342                        mUpdateLayer = true;
343                    }
344                    postInvalidate();
345                }
346            };
347            mSurface.setOnFrameAvailableListener(mUpdateListener);
348
349            if (mListener != null) {
350                mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
351            }
352        }
353
354        if (mUpdateSurface) {
355            // Someone has requested that we use a specific SurfaceTexture, so
356            // tell mLayer about it and set the SurfaceTexture to use the
357            // current view size.
358            mUpdateSurface = false;
359            mAttachInfo.mHardwareRenderer.setSurfaceTexture(mLayer, mSurface);
360            nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
361        }
362
363        applyUpdate();
364        applyTransformMatrix();
365
366        return mLayer;
367    }
368
369    @Override
370    protected void onVisibilityChanged(View changedView, int visibility) {
371        super.onVisibilityChanged(changedView, visibility);
372
373        if (mSurface != null) {
374            // When the view becomes invisible, stop updating it, it's a waste of CPU
375            // To cancel updates, the easiest thing to do is simply to remove the
376            // updates listener
377            if (visibility == VISIBLE) {
378                mSurface.setOnFrameAvailableListener(mUpdateListener);
379                updateLayer();
380            } else {
381                mSurface.setOnFrameAvailableListener(null);
382            }
383        }
384    }
385
386    private void updateLayer() {
387        mUpdateLayer = true;
388        invalidate();
389    }
390
391    private void applyUpdate() {
392        if (mLayer == null) {
393            return;
394        }
395
396        synchronized (mLock) {
397            if (mUpdateLayer) {
398                mUpdateLayer = false;
399            } else {
400                return;
401            }
402        }
403
404        mLayer.update(getWidth(), getHeight(), mOpaque);
405
406        if (mListener != null) {
407            mListener.onSurfaceTextureUpdated(mSurface);
408        }
409    }
410
411    /**
412     * <p>Sets the transform to associate with this texture view.
413     * The specified transform applies to the underlying surface
414     * texture and does not affect the size or position of the view
415     * itself, only of its content.</p>
416     *
417     * <p>Some transforms might prevent the content from drawing
418     * all the pixels contained within this view's bounds. In such
419     * situations, make sure this texture view is not marked opaque.</p>
420     *
421     * @param transform The transform to apply to the content of
422     *        this view.
423     *
424     * @see #getTransform(android.graphics.Matrix)
425     * @see #isOpaque()
426     * @see #setOpaque(boolean)
427     */
428    public void setTransform(Matrix transform) {
429        mMatrix.set(transform);
430        mMatrixChanged = true;
431        invalidateParentIfNeeded();
432    }
433
434    /**
435     * Returns the transform associated with this texture view.
436     *
437     * @param transform The {@link Matrix} in which to copy the current
438     *        transform. Can be null.
439     *
440     * @return The specified matrix if not null or a new {@link Matrix}
441     *         instance otherwise.
442     *
443     * @see #setTransform(android.graphics.Matrix)
444     */
445    public Matrix getTransform(Matrix transform) {
446        if (transform == null) {
447            transform = new Matrix();
448        }
449
450        transform.set(mMatrix);
451
452        return transform;
453    }
454
455    private void applyTransformMatrix() {
456        if (mMatrixChanged) {
457            mLayer.setTransform(mMatrix);
458            mMatrixChanged = false;
459        }
460    }
461
462    /**
463     * <p>Returns a {@link android.graphics.Bitmap} representation of the content
464     * of the associated surface texture. If the surface texture is not available,
465     * this method returns null.</p>
466     *
467     * <p>The bitmap returned by this method uses the {@link Bitmap.Config#ARGB_8888}
468     * pixel format and its dimensions are the same as this view's.</p>
469     *
470     * <p><strong>Do not</strong> invoke this method from a drawing method
471     * ({@link #onDraw(android.graphics.Canvas)} for instance).</p>
472     *
473     * <p>If an error occurs during the copy, an empty bitmap will be returned.</p>
474     *
475     * @return A valid {@link Bitmap.Config#ARGB_8888} bitmap, or null if the surface
476     *         texture is not available or the width &lt;= 0 or the height &lt;= 0
477     *
478     * @see #isAvailable()
479     * @see #getBitmap(android.graphics.Bitmap)
480     * @see #getBitmap(int, int)
481     */
482    public Bitmap getBitmap() {
483        return getBitmap(getWidth(), getHeight());
484    }
485
486    /**
487     * <p>Returns a {@link android.graphics.Bitmap} representation of the content
488     * of the associated surface texture. If the surface texture is not available,
489     * this method returns null.</p>
490     *
491     * <p>The bitmap returned by this method uses the {@link Bitmap.Config#ARGB_8888}
492     * pixel format.</p>
493     *
494     * <p><strong>Do not</strong> invoke this method from a drawing method
495     * ({@link #onDraw(android.graphics.Canvas)} for instance).</p>
496     *
497     * <p>If an error occurs during the copy, an empty bitmap will be returned.</p>
498     *
499     * @param width The width of the bitmap to create
500     * @param height The height of the bitmap to create
501     *
502     * @return A valid {@link Bitmap.Config#ARGB_8888} bitmap, or null if the surface
503     *         texture is not available or width is &lt;= 0 or height is &lt;= 0
504     *
505     * @see #isAvailable()
506     * @see #getBitmap(android.graphics.Bitmap)
507     * @see #getBitmap()
508     */
509    public Bitmap getBitmap(int width, int height) {
510        if (isAvailable() && width > 0 && height > 0) {
511            return getBitmap(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888));
512        }
513        return null;
514    }
515
516    /**
517     * <p>Copies the content of this view's surface texture into the specified
518     * bitmap. If the surface texture is not available, the copy is not executed.
519     * The content of the surface texture will be scaled to fit exactly inside
520     * the specified bitmap.</p>
521     *
522     * <p><strong>Do not</strong> invoke this method from a drawing method
523     * ({@link #onDraw(android.graphics.Canvas)} for instance).</p>
524     *
525     * <p>If an error occurs, the bitmap is left unchanged.</p>
526     *
527     * @param bitmap The bitmap to copy the content of the surface texture into,
528     *               cannot be null, all configurations are supported
529     *
530     * @return The bitmap specified as a parameter
531     *
532     * @see #isAvailable()
533     * @see #getBitmap(int, int)
534     * @see #getBitmap()
535     *
536     * @throws IllegalStateException if the hardware rendering context cannot be
537     *         acquired to capture the bitmap
538     */
539    public Bitmap getBitmap(Bitmap bitmap) {
540        if (bitmap != null && isAvailable()) {
541            AttachInfo info = mAttachInfo;
542            if (info != null && info.mHardwareRenderer != null &&
543                    info.mHardwareRenderer.isEnabled()) {
544                if (!info.mHardwareRenderer.validate()) {
545                    throw new IllegalStateException("Could not acquire hardware rendering context");
546                }
547            }
548
549            applyUpdate();
550            applyTransformMatrix();
551
552            mLayer.copyInto(bitmap);
553        }
554        return bitmap;
555    }
556
557    /**
558     * Returns true if the {@link SurfaceTexture} associated with this
559     * TextureView is available for rendering. When this method returns
560     * true, {@link #getSurfaceTexture()} returns a valid surface texture.
561     */
562    public boolean isAvailable() {
563        return mSurface != null;
564    }
565
566    /**
567     * <p>Start editing the pixels in the surface.  The returned Canvas can be used
568     * to draw into the surface's bitmap.  A null is returned if the surface has
569     * not been created or otherwise cannot be edited. You will usually need
570     * to implement
571     * {@link SurfaceTextureListener#onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int)}
572     * to find out when the Surface is available for use.</p>
573     *
574     * <p>The content of the Surface is never preserved between unlockCanvas()
575     * and lockCanvas(), for this reason, every pixel within the Surface area
576     * must be written. The only exception to this rule is when a dirty
577     * rectangle is specified, in which case, non-dirty pixels will be
578     * preserved.</p>
579     *
580     * <p>This method can only be used if the underlying surface is not already
581     * owned by another producer. For instance, if the TextureView is being used
582     * to render the camera's preview you cannot invoke this method.</p>
583     *
584     * @return A Canvas used to draw into the surface.
585     *
586     * @see #lockCanvas(android.graphics.Rect)
587     * @see #unlockCanvasAndPost(android.graphics.Canvas)
588     */
589    public Canvas lockCanvas() {
590        return lockCanvas(null);
591    }
592
593    /**
594     * Just like {@link #lockCanvas()} but allows specification of a dirty
595     * rectangle. Every pixel within that rectangle must be written; however
596     * pixels outside the dirty rectangle will be preserved by the next call
597     * to lockCanvas().
598     *
599     * @param dirty Area of the surface that will be modified.
600
601     * @return A Canvas used to draw into the surface.
602     *
603     * @see #lockCanvas()
604     * @see #unlockCanvasAndPost(android.graphics.Canvas)
605     */
606    public Canvas lockCanvas(Rect dirty) {
607        if (!isAvailable()) return null;
608
609        if (mCanvas == null) {
610            mCanvas = new Canvas();
611        }
612
613        synchronized (mNativeWindowLock) {
614            nLockCanvas(mNativeWindow, mCanvas, dirty);
615        }
616        mSaveCount = mCanvas.save();
617
618        return mCanvas;
619    }
620
621    /**
622     * Finish editing pixels in the surface. After this call, the surface's
623     * current pixels will be shown on the screen, but its content is lost,
624     * in particular there is no guarantee that the content of the Surface
625     * will remain unchanged when lockCanvas() is called again.
626     *
627     * @param canvas The Canvas previously returned by lockCanvas()
628     *
629     * @see #lockCanvas()
630     * @see #lockCanvas(android.graphics.Rect)
631     */
632    public void unlockCanvasAndPost(Canvas canvas) {
633        if (mCanvas != null && canvas == mCanvas) {
634            canvas.restoreToCount(mSaveCount);
635            mSaveCount = 0;
636
637            synchronized (mNativeWindowLock) {
638                nUnlockCanvasAndPost(mNativeWindow, mCanvas);
639            }
640        }
641    }
642
643    /**
644     * Returns the {@link SurfaceTexture} used by this view. This method
645     * may return null if the view is not attached to a window or if the surface
646     * texture has not been initialized yet.
647     *
648     * @see #isAvailable()
649     */
650    public SurfaceTexture getSurfaceTexture() {
651        return mSurface;
652    }
653
654    /**
655     * Set the {@link SurfaceTexture} for this view to use. If a {@link
656     * SurfaceTexture} is already being used by this view, it is immediately
657     * released and not be usable any more.  The {@link
658     * SurfaceTextureListener#onSurfaceTextureDestroyed} callback is <b>not</b>
659     * called.
660     *
661     * The {@link SurfaceTexture} object must be detached from all OpenGL ES
662     * contexts prior to calling this method.
663     *
664     * @param surfaceTexture The {@link SurfaceTexture} that the view should use.
665     * @see SurfaceTexture#detachFromGLContext()
666     * @hide
667     */
668    public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
669        if (surfaceTexture == null) {
670            throw new NullPointerException("surfaceTexture must not be null");
671        }
672        if (mSurface != null) {
673            mSurface.release();
674        }
675        mSurface = surfaceTexture;
676        mUpdateSurface = true;
677        invalidateParentIfNeeded();
678    }
679
680    /**
681     * Returns the {@link SurfaceTextureListener} currently associated with this
682     * texture view.
683     *
684     * @see #setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener)
685     * @see SurfaceTextureListener
686     */
687    public SurfaceTextureListener getSurfaceTextureListener() {
688        return mListener;
689    }
690
691    /**
692     * Sets the {@link SurfaceTextureListener} used to listen to surface
693     * texture events.
694     *
695     * @see #getSurfaceTextureListener()
696     * @see SurfaceTextureListener
697     */
698    public void setSurfaceTextureListener(SurfaceTextureListener listener) {
699        mListener = listener;
700    }
701
702    /**
703     * This listener can be used to be notified when the surface texture
704     * associated with this texture view is available.
705     */
706    public static interface SurfaceTextureListener {
707        /**
708         * Invoked when a {@link TextureView}'s SurfaceTexture is ready for use.
709         *
710         * @param surface The surface returned by
711         *                {@link android.view.TextureView#getSurfaceTexture()}
712         * @param width The width of the surface
713         * @param height The height of the surface
714         */
715        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height);
716
717        /**
718         * Invoked when the {@link SurfaceTexture}'s buffers size changed.
719         *
720         * @param surface The surface returned by
721         *                {@link android.view.TextureView#getSurfaceTexture()}
722         * @param width The new width of the surface
723         * @param height The new height of the surface
724         */
725        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height);
726
727        /**
728         * Invoked when the specified {@link SurfaceTexture} is about to be destroyed.
729         * If returns true, no rendering should happen inside the surface texture after this method
730         * is invoked. If returns false, the client needs to call {@link SurfaceTexture#release()}.
731         *
732         * @param surface The surface about to be destroyed
733         */
734        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface);
735
736        /**
737         * Invoked when the specified {@link SurfaceTexture} is updated through
738         * {@link SurfaceTexture#updateTexImage()}.
739         *
740         * @param surface The surface just updated
741         */
742        public void onSurfaceTextureUpdated(SurfaceTexture surface);
743    }
744
745    private native void nCreateNativeWindow(SurfaceTexture surface);
746    private native void nDestroyNativeWindow();
747
748    private static native void nSetDefaultBufferSize(SurfaceTexture surfaceTexture,
749            int width, int height);
750
751    private static native void nLockCanvas(int nativeWindow, Canvas canvas, Rect dirty);
752    private static native void nUnlockCanvasAndPost(int nativeWindow, Canvas canvas);
753}
754