VideoUI.java revision 6432cd65159731a28d9239426b0f0f4d7c44fa98
1/* 2 * Copyright (C) 2012 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 com.android.camera; 18 19import android.graphics.Bitmap; 20import android.graphics.Matrix; 21import android.graphics.SurfaceTexture; 22import android.hardware.Camera.Parameters; 23import android.os.Handler; 24import android.os.Message; 25import android.util.Log; 26import android.view.Gravity; 27import android.view.SurfaceHolder; 28import android.view.SurfaceView; 29import android.view.TextureView; 30import android.view.TextureView.SurfaceTextureListener; 31import android.view.View; 32import android.view.View.OnClickListener; 33import android.view.View.OnLayoutChangeListener; 34import android.view.ViewGroup; 35import android.widget.FrameLayout; 36import android.widget.FrameLayout.LayoutParams; 37import android.widget.ImageView; 38import android.widget.LinearLayout; 39import android.widget.TextView; 40 41import com.android.camera.CameraPreference.OnPreferenceChangedListener; 42import com.android.camera.ui.AbstractSettingPopup; 43import com.android.camera.ui.CameraControls; 44import com.android.camera.ui.CameraRootView; 45import com.android.camera.ui.CameraSwitcher; 46import com.android.camera.ui.CameraSwitcher.CameraSwitchListener; 47import com.android.camera.ui.PieRenderer; 48import com.android.camera.ui.RenderOverlay; 49import com.android.camera.ui.RotateLayout; 50import com.android.camera.ui.ZoomRenderer; 51import com.android.gallery3d.R; 52import com.android.gallery3d.common.ApiHelper; 53 54import java.util.List; 55 56public class VideoUI implements PieRenderer.PieListener, 57 PreviewGestures.SingleTapListener, 58 CameraRootView.MyDisplayListener, 59 SurfaceTextureListener, SurfaceHolder.Callback { 60 private final static String TAG = "CAM_VideoUI"; 61 private static final int UPDATE_TRANSFORM_MATRIX = 1; 62 // module fields 63 private CameraActivity mActivity; 64 private View mRootView; 65 private TextureView mTextureView; 66 // An review image having same size as preview. It is displayed when 67 // recording is stopped in capture intent. 68 private ImageView mReviewImage; 69 private View mReviewCancelButton; 70 private View mReviewDoneButton; 71 private View mReviewPlayButton; 72 private ShutterButton mShutterButton; 73 private CameraSwitcher mSwitcher; 74 private TextView mRecordingTimeView; 75 private LinearLayout mLabelsLinearLayout; 76 private View mTimeLapseLabel; 77 private RenderOverlay mRenderOverlay; 78 private PieRenderer mPieRenderer; 79 private VideoMenu mVideoMenu; 80 private CameraControls mCameraControls; 81 private AbstractSettingPopup mPopup; 82 private ZoomRenderer mZoomRenderer; 83 private PreviewGestures mGestures; 84 private View mMenuButton; 85 private View mBlocker; 86 private OnScreenIndicators mOnScreenIndicators; 87 private RotateLayout mRecordingTimeRect; 88 private final Object mLock = new Object(); 89 private SurfaceTexture mSurfaceTexture; 90 private VideoController mController; 91 private int mZoomMax; 92 private List<Integer> mZoomRatios; 93 private View mPreviewThumb; 94 95 private SurfaceView mSurfaceView = null; 96 private int mPreviewWidth = 0; 97 private int mPreviewHeight = 0; 98 private float mSurfaceTextureUncroppedWidth; 99 private float mSurfaceTextureUncroppedHeight; 100 private float mAspectRatio = 4f / 3f; 101 private Matrix mMatrix = null; 102 private final Handler mHandler = new Handler() { 103 @Override 104 public void handleMessage(Message msg) { 105 switch (msg.what) { 106 case UPDATE_TRANSFORM_MATRIX: 107 setTransformMatrix(mPreviewWidth, mPreviewHeight); 108 break; 109 default: 110 break; 111 } 112 } 113 }; 114 private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() { 115 @Override 116 public void onLayoutChange(View v, int left, int top, int right, 117 int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 118 int width = right - left; 119 int height = bottom - top; 120 // Full-screen screennail 121 int w = width; 122 int h = height; 123 if (Util.getDisplayRotation(mActivity) % 180 != 0) { 124 w = height; 125 h = width; 126 } 127 if (mPreviewWidth != width || mPreviewHeight != height) { 128 mPreviewWidth = width; 129 mPreviewHeight = height; 130 onScreenSizeChanged(width, height, w, h); 131 } 132 } 133 }; 134 135 public VideoUI(CameraActivity activity, VideoController controller, View parent) { 136 mActivity = activity; 137 mController = controller; 138 mRootView = parent; 139 mActivity.getLayoutInflater().inflate(R.layout.video_module, (ViewGroup) mRootView, true); 140 mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content); 141 mTextureView.setSurfaceTextureListener(this); 142 mRootView.addOnLayoutChangeListener(mLayoutListener); 143 ((CameraRootView) mRootView).setDisplayChangeListener(this); 144 mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button); 145 mSwitcher = (CameraSwitcher) mRootView.findViewById(R.id.camera_switcher); 146 mSwitcher.setCurrentIndex(1); 147 mSwitcher.setSwitchListener((CameraSwitchListener) mActivity); 148 initializeMiscControls(); 149 initializeControlByIntent(); 150 initializeOverlay(); 151 } 152 153 154 public void initializeSurfaceView() { 155 mSurfaceView = new SurfaceView(mActivity); 156 ((ViewGroup) mRootView).addView(mSurfaceView, 0); 157 mSurfaceView.getHolder().addCallback(this); 158 } 159 160 private void initializeControlByIntent() { 161 mBlocker = mActivity.findViewById(R.id.blocker); 162 mMenuButton = mActivity.findViewById(R.id.menu); 163 mMenuButton.setOnClickListener(new OnClickListener() { 164 @Override 165 public void onClick(View v) { 166 if (mPieRenderer != null) { 167 mPieRenderer.showInCenter(); 168 } 169 } 170 }); 171 172 mCameraControls = (CameraControls) mActivity.findViewById(R.id.camera_controls); 173 mOnScreenIndicators = new OnScreenIndicators(mActivity, 174 mActivity.findViewById(R.id.on_screen_indicators)); 175 mOnScreenIndicators.resetToDefault(); 176 if (mController.isVideoCaptureIntent()) { 177 hideSwitcher(); 178 mActivity.getLayoutInflater().inflate(R.layout.review_module_control, 179 (ViewGroup) mCameraControls); 180 // Cannot use RotateImageView for "done" and "cancel" button because 181 // the tablet layout uses RotateLayout, which cannot be cast to 182 // RotateImageView. 183 mReviewDoneButton = mActivity.findViewById(R.id.btn_done); 184 mReviewCancelButton = mActivity.findViewById(R.id.btn_cancel); 185 mReviewPlayButton = mActivity.findViewById(R.id.btn_play); 186 mReviewCancelButton.setVisibility(View.VISIBLE); 187 mReviewDoneButton.setOnClickListener(new OnClickListener() { 188 @Override 189 public void onClick(View v) { 190 mController.onReviewDoneClicked(v); 191 } 192 }); 193 mReviewCancelButton.setOnClickListener(new OnClickListener() { 194 @Override 195 public void onClick(View v) { 196 mController.onReviewCancelClicked(v); 197 } 198 }); 199 mReviewPlayButton.setOnClickListener(new OnClickListener() { 200 @Override 201 public void onClick(View v) { 202 mController.onReviewPlayClicked(v); 203 } 204 }); 205 } 206 } 207 208 public void setPreviewSize(int width, int height) { 209 if (width == 0 || height == 0) { 210 Log.w(TAG, "Preview size should not be 0."); 211 return; 212 } 213 if (width > height) { 214 mAspectRatio = (float) width / height; 215 } else { 216 mAspectRatio = (float) height / width; 217 } 218 mHandler.sendEmptyMessage(UPDATE_TRANSFORM_MATRIX); 219 } 220 221 public int getPreviewWidth() { 222 return mPreviewWidth; 223 } 224 225 public int getPreviewHeight() { 226 return mPreviewHeight; 227 } 228 229 public void onScreenSizeChanged(int width, int height, int previewWidth, int previewHeight) { 230 setTransformMatrix(width, height); 231 } 232 233 private void setTransformMatrix(int width, int height) { 234 mMatrix = mTextureView.getTransform(mMatrix); 235 int orientation = Util.getDisplayRotation(mActivity); 236 float scaleX = 1f, scaleY = 1f; 237 float scaledTextureWidth, scaledTextureHeight; 238 if (width > height) { 239 scaledTextureWidth = Math.max(width, 240 (int) (height * mAspectRatio)); 241 scaledTextureHeight = Math.max(height, 242 (int)(width / mAspectRatio)); 243 } else { 244 scaledTextureWidth = Math.max(width, 245 (int) (height / mAspectRatio)); 246 scaledTextureHeight = Math.max(height, 247 (int) (width * mAspectRatio)); 248 } 249 250 if (mSurfaceTextureUncroppedWidth != scaledTextureWidth || 251 mSurfaceTextureUncroppedHeight != scaledTextureHeight) { 252 mSurfaceTextureUncroppedWidth = scaledTextureWidth; 253 mSurfaceTextureUncroppedHeight = scaledTextureHeight; 254 } 255 scaleX = scaledTextureWidth / width; 256 scaleY = scaledTextureHeight / height; 257 mMatrix.setScale(scaleX, scaleY, (float) width / 2, (float) height / 2); 258 mTextureView.setTransform(mMatrix); 259 260 if (mSurfaceView != null && mSurfaceView.getVisibility() == View.VISIBLE) { 261 LayoutParams lp = (LayoutParams) mSurfaceView.getLayoutParams(); 262 lp.width = (int) mSurfaceTextureUncroppedWidth; 263 lp.height = (int) mSurfaceTextureUncroppedHeight; 264 lp.gravity = Gravity.CENTER; 265 mSurfaceView.requestLayout(); 266 } 267 } 268 269 public void hideUI() { 270 mCameraControls.setVisibility(View.INVISIBLE); 271 mSwitcher.closePopup(); 272 } 273 274 public void showUI() { 275 mCameraControls.setVisibility(View.VISIBLE); 276 } 277 278 public void hideSwitcher() { 279 mSwitcher.closePopup(); 280 mSwitcher.setVisibility(View.INVISIBLE); 281 } 282 283 public void showSwitcher() { 284 mSwitcher.setVisibility(View.VISIBLE); 285 } 286 287 public boolean collapseCameraControls() { 288 boolean ret = false; 289 if (mPopup != null) { 290 dismissPopup(false); 291 ret = true; 292 } 293 return ret; 294 } 295 296 public boolean removeTopLevelPopup() { 297 if (mPopup != null) { 298 dismissPopup(true); 299 return true; 300 } 301 return false; 302 } 303 304 public void enableCameraControls(boolean enable) { 305 if (mGestures != null) { 306 mGestures.setZoomOnly(!enable); 307 } 308 if (mPieRenderer != null && mPieRenderer.showsItems()) { 309 mPieRenderer.hide(); 310 } 311 } 312 313 public void overrideSettings(final String... keyvalues) { 314 mVideoMenu.overrideSettings(keyvalues); 315 } 316 317 public void setOrientationIndicator(int orientation, boolean animation) { 318 if (mGestures != null) { 319 mGestures.setOrientation(orientation); 320 } 321 // We change the orientation of the linearlayout only for phone UI 322 // because when in portrait the width is not enough. 323 if (mLabelsLinearLayout != null) { 324 if (((orientation / 90) & 1) == 0) { 325 mLabelsLinearLayout.setOrientation(LinearLayout.VERTICAL); 326 } else { 327 mLabelsLinearLayout.setOrientation(LinearLayout.HORIZONTAL); 328 } 329 } 330 mRecordingTimeRect.setOrientation(0, animation); 331 } 332 333 public SurfaceHolder getSurfaceHolder() { 334 return mSurfaceView.getHolder(); 335 } 336 337 public void hideSurfaceView() { 338 mSurfaceView.setVisibility(View.GONE); 339 mTextureView.setVisibility(View.VISIBLE); 340 setTransformMatrix(mPreviewWidth, mPreviewHeight); 341 } 342 343 public void showSurfaceView() { 344 mSurfaceView.setVisibility(View.VISIBLE); 345 mTextureView.setVisibility(View.GONE); 346 setTransformMatrix(mPreviewWidth, mPreviewHeight); 347 } 348 349 private void initializeOverlay() { 350 mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay); 351 if (mPieRenderer == null) { 352 mPieRenderer = new PieRenderer(mActivity); 353 mVideoMenu = new VideoMenu(mActivity, this, mPieRenderer); 354 mPieRenderer.setPieListener(this); 355 } 356 mRenderOverlay.addRenderer(mPieRenderer); 357 if (mZoomRenderer == null) { 358 mZoomRenderer = new ZoomRenderer(mActivity); 359 } 360 mRenderOverlay.addRenderer(mZoomRenderer); 361 if (mGestures == null) { 362 mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer); 363 mRenderOverlay.setGestures(mGestures); 364 } 365 mGestures.setRenderOverlay(mRenderOverlay); 366 367 mPreviewThumb = mActivity.findViewById(R.id.preview_thumb); 368 mPreviewThumb.setOnClickListener(new OnClickListener() { 369 @Override 370 public void onClick(View v) { 371 // TODO: Go to filmstrip view 372 } 373 }); 374 } 375 376 public void setPrefChangedListener(OnPreferenceChangedListener listener) { 377 mVideoMenu.setListener(listener); 378 } 379 380 private void initializeMiscControls() { 381 mReviewImage = (ImageView) mRootView.findViewById(R.id.review_image); 382 mShutterButton.setImageResource(R.drawable.btn_new_shutter_video); 383 mShutterButton.setOnShutterButtonListener(mController); 384 mShutterButton.setVisibility(View.VISIBLE); 385 mShutterButton.requestFocus(); 386 mShutterButton.enableTouch(true); 387 mRecordingTimeView = (TextView) mRootView.findViewById(R.id.recording_time); 388 mRecordingTimeRect = (RotateLayout) mRootView.findViewById(R.id.recording_time_rect); 389 mTimeLapseLabel = mRootView.findViewById(R.id.time_lapse_label); 390 // The R.id.labels can only be found in phone layout. 391 // That is, mLabelsLinearLayout should be null in tablet layout. 392 mLabelsLinearLayout = (LinearLayout) mRootView.findViewById(R.id.labels); 393 } 394 395 public void updateOnScreenIndicators(Parameters param, ComboPreferences prefs) { 396 mOnScreenIndicators.updateFlashOnScreenIndicator(param.getFlashMode()); 397 boolean location = RecordLocationPreference.get( 398 prefs, mActivity.getContentResolver()); 399 mOnScreenIndicators.updateLocationIndicator(location); 400 401 } 402 403 public void setAspectRatio(double ratio) { 404 // mPreviewFrameLayout.setAspectRatio(ratio); 405 } 406 407 public void showTimeLapseUI(boolean enable) { 408 if (mTimeLapseLabel != null) { 409 mTimeLapseLabel.setVisibility(enable ? View.VISIBLE : View.GONE); 410 } 411 } 412 413 private void openMenu() { 414 if (mPieRenderer != null) { 415 mPieRenderer.showInCenter(); 416 } 417 } 418 419 public void showPopup(AbstractSettingPopup popup) { 420 hideUI(); 421 mBlocker.setVisibility(View.INVISIBLE); 422 setShowMenu(false); 423 mPopup = popup; 424 mPopup.setVisibility(View.VISIBLE); 425 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, 426 LayoutParams.WRAP_CONTENT); 427 lp.gravity = Gravity.CENTER; 428 ((FrameLayout) mRootView).addView(mPopup, lp); 429 } 430 431 public void dismissPopup(boolean topLevelOnly) { 432 dismissPopup(topLevelOnly, true); 433 } 434 435 public void dismissPopup(boolean topLevelPopupOnly, boolean fullScreen) { 436 // In review mode, we do not want to bring up the camera UI 437 if (mController.isInReviewMode()) return; 438 439 if (fullScreen) { 440 showUI(); 441 mBlocker.setVisibility(View.VISIBLE); 442 } 443 setShowMenu(fullScreen); 444 if (mPopup != null) { 445 ((FrameLayout) mRootView).removeView(mPopup); 446 mPopup = null; 447 } 448 mVideoMenu.popupDismissed(topLevelPopupOnly); 449 } 450 451 public void onShowSwitcherPopup() { 452 hidePieRenderer(); 453 } 454 455 public boolean hidePieRenderer() { 456 if (mPieRenderer != null && mPieRenderer.showsItems()) { 457 mPieRenderer.hide(); 458 return true; 459 } 460 return false; 461 } 462 463 // disable preview gestures after shutter is pressed 464 public void setShutterPressed(boolean pressed) { 465 if (mGestures == null) return; 466 mGestures.setEnabled(!pressed); 467 } 468 469 public void enableShutter(boolean enable) { 470 if (mShutterButton != null) { 471 mShutterButton.setEnabled(enable); 472 } 473 } 474 475 // PieListener 476 @Override 477 public void onPieOpened(int centerX, int centerY) { 478 setSwipingEnabled(false); 479 dismissPopup(false, true); 480 } 481 482 @Override 483 public void onPieClosed() { 484 setSwipingEnabled(true); 485 } 486 487 public void setSwipingEnabled(boolean enable) { 488 mActivity.setSwipingEnabled(enable); 489 } 490 491 public void showPreviewBorder(boolean enable) { 492 // TODO: mPreviewFrameLayout.showBorder(enable); 493 } 494 495 // SingleTapListener 496 // Preview area is touched. Take a picture. 497 @Override 498 public void onSingleTapUp(View view, int x, int y) { 499 mController.onSingleTapUp(view, x, y); 500 } 501 502 public void showRecordingUI(boolean recording, boolean zoomSupported) { 503 mMenuButton.setVisibility(recording ? View.GONE : View.VISIBLE); 504 mOnScreenIndicators.setVisibility(recording ? View.GONE : View.VISIBLE); 505 if (recording) { 506 mShutterButton.setImageResource(R.drawable.btn_shutter_video_recording); 507 hideSwitcher(); 508 mRecordingTimeView.setText(""); 509 mRecordingTimeView.setVisibility(View.VISIBLE); 510 // The camera is not allowed to be accessed in older api levels during 511 // recording. It is therefore necessary to hide the zoom UI on older 512 // platforms. 513 // See the documentation of android.media.MediaRecorder.start() for 514 // further explanation. 515 if (!ApiHelper.HAS_ZOOM_WHEN_RECORDING && zoomSupported) { 516 // TODO: disable zoom UI here. 517 } 518 } else { 519 mShutterButton.setImageResource(R.drawable.btn_new_shutter_video); 520 showSwitcher(); 521 mRecordingTimeView.setVisibility(View.GONE); 522 if (!ApiHelper.HAS_ZOOM_WHEN_RECORDING && zoomSupported) { 523 // TODO: enable zoom UI here. 524 } 525 } 526 } 527 528 public void showReviewImage(Bitmap bitmap) { 529 mReviewImage.setImageBitmap(bitmap); 530 mReviewImage.setVisibility(View.VISIBLE); 531 } 532 533 public void showReviewControls() { 534 Util.fadeOut(mShutterButton); 535 Util.fadeIn(mReviewDoneButton); 536 Util.fadeIn(mReviewPlayButton); 537 mReviewImage.setVisibility(View.VISIBLE); 538 mMenuButton.setVisibility(View.GONE); 539 mOnScreenIndicators.setVisibility(View.GONE); 540 } 541 542 public void hideReviewUI() { 543 mReviewImage.setVisibility(View.GONE); 544 mShutterButton.setEnabled(true); 545 mMenuButton.setVisibility(View.VISIBLE); 546 mOnScreenIndicators.setVisibility(View.VISIBLE); 547 Util.fadeOut(mReviewDoneButton); 548 Util.fadeOut(mReviewPlayButton); 549 Util.fadeIn(mShutterButton); 550 } 551 552 private void setShowMenu(boolean show) { 553 if (mOnScreenIndicators != null) { 554 mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE); 555 } 556 if (mMenuButton != null) { 557 mMenuButton.setVisibility(show ? View.VISIBLE : View.GONE); 558 } 559 } 560 561 public void onSwitchMode(boolean toCamera) { 562 if (toCamera) { 563 showUI(); 564 } else { 565 hideUI(); 566 } 567 if (mGestures != null) { 568 mGestures.setEnabled(toCamera); 569 } 570 if (mPopup != null) { 571 dismissPopup(false, toCamera); 572 } 573 if (mRenderOverlay != null) { 574 // this can not happen in capture mode 575 mRenderOverlay.setVisibility(toCamera ? View.VISIBLE : View.GONE); 576 } 577 setShowMenu(toCamera); 578 } 579 580 public void initializePopup(PreferenceGroup pref) { 581 mVideoMenu.initialize(pref); 582 } 583 584 public void initializeZoom(Parameters param) { 585 if (param == null || !param.isZoomSupported()) { 586 mGestures.setZoomEnabled(false); 587 return; 588 } 589 mGestures.setZoomEnabled(true); 590 mZoomMax = param.getMaxZoom(); 591 mZoomRatios = param.getZoomRatios(); 592 // Currently we use immediate zoom for fast zooming to get better UX and 593 // there is no plan to take advantage of the smooth zoom. 594 mZoomRenderer.setZoomMax(mZoomMax); 595 mZoomRenderer.setZoom(param.getZoom()); 596 mZoomRenderer.setZoomValue(mZoomRatios.get(param.getZoom())); 597 mZoomRenderer.setOnZoomChangeListener(new ZoomChangeListener()); 598 } 599 600 public void clickShutter() { 601 mShutterButton.performClick(); 602 } 603 604 public void pressShutter(boolean pressed) { 605 mShutterButton.setPressed(pressed); 606 } 607 608 public View getShutterButton() { 609 return mShutterButton; 610 } 611 612 public void setRecordingTime(String text) { 613 mRecordingTimeView.setText(text); 614 } 615 616 public void setRecordingTimeTextColor(int color) { 617 mRecordingTimeView.setTextColor(color); 618 } 619 620 public boolean isVisible() { 621 return mTextureView.getVisibility() == View.VISIBLE; 622 } 623 624 public void onDisplayChanged() { 625 mCameraControls.checkLayoutFlip(); 626 mController.updateCameraOrientation(); 627 } 628 629 /** 630 * Enable or disable the preview thumbnail for click events. 631 */ 632 public void enablePreviewThumb(boolean enabled) { 633 if (enabled) { 634 mPreviewThumb.setVisibility(View.VISIBLE); 635 } else { 636 mPreviewThumb.setVisibility(View.GONE); 637 } 638 } 639 640 private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener { 641 @Override 642 public void onZoomValueChanged(int index) { 643 int newZoom = mController.onZoomChanged(index); 644 if (mZoomRenderer != null) { 645 mZoomRenderer.setZoomValue(mZoomRatios.get(newZoom)); 646 } 647 } 648 649 @Override 650 public void onZoomStart() { 651 } 652 653 @Override 654 public void onZoomEnd() { 655 } 656 } 657 658 public SurfaceTexture getSurfaceTexture() { 659 synchronized (mLock) { 660 if (mSurfaceTexture == null) { 661 try { 662 mLock.wait(); 663 } catch (InterruptedException e) { 664 Log.w(TAG, "Unexpected interruption when waiting to get surface texture"); 665 } 666 } 667 } 668 return mSurfaceTexture; 669 } 670 671 // SurfaceTexture callbacks 672 @Override 673 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 674 synchronized (mLock) { 675 mSurfaceTexture = surface; 676 mLock.notifyAll(); 677 } 678 } 679 680 @Override 681 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 682 mSurfaceTexture = null; 683 mController.stopPreview(); 684 Log.d(TAG, "surfaceTexture is destroyed"); 685 return true; 686 } 687 688 @Override 689 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 690 } 691 692 @Override 693 public void onSurfaceTextureUpdated(SurfaceTexture surface) { 694 } 695 696 // SurfaceHolder callbacks 697 @Override 698 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 699 Log.v(TAG, "Surface changed. width=" + width + ". height=" + height); 700 } 701 702 @Override 703 public void surfaceCreated(SurfaceHolder holder) { 704 Log.v(TAG, "Surface created"); 705 } 706 707 @Override 708 public void surfaceDestroyed(SurfaceHolder holder) { 709 Log.v(TAG, "Surface destroyed"); 710 mController.stopPreview(); 711 } 712} 713