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