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