PhotoUI.java revision fd2e619a2fb263315816b3579a9c6751c398132d
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18package com.android.camera;
19
20import android.hardware.Camera;
21import android.hardware.Camera.Face;
22import android.hardware.Camera.FaceDetectionListener;
23import android.hardware.Camera.Parameters;
24import android.util.Log;
25import android.view.Gravity;
26import android.view.MotionEvent;
27import android.view.SurfaceHolder;
28import android.view.View;
29import android.view.View.OnClickListener;
30import android.view.View.OnLayoutChangeListener;
31import android.view.ViewGroup;
32import android.view.ViewStub;
33import android.widget.FrameLayout;
34import android.widget.FrameLayout.LayoutParams;
35import android.widget.ImageView;
36import android.widget.Toast;
37
38import com.android.camera.CameraPreference.OnPreferenceChangedListener;
39import com.android.camera.FocusOverlayManager.FocusUI;
40import com.android.camera.ui.AbstractSettingPopup;
41import com.android.camera.ui.CountDownView;
42import com.android.camera.ui.CountDownView.OnCountDownFinishedListener;
43import com.android.camera.ui.FaceView;
44import com.android.camera.ui.FocusIndicator;
45import com.android.camera.ui.PieRenderer;
46import com.android.camera.ui.PieRenderer.PieListener;
47import com.android.camera.ui.RenderOverlay;
48import com.android.camera.ui.ZoomRenderer;
49import com.android.gallery3d.R;
50import com.android.gallery3d.common.ApiHelper;
51
52import java.util.List;
53
54public class PhotoUI implements PieListener,
55    SurfaceHolder.Callback,
56    PreviewGestures.SingleTapListener,
57    FocusUI,
58    LocationManager.Listener,
59    FaceDetectionListener,
60    PreviewGestures.SwipeListener {
61
62    private static final String TAG = "CAM_UI";
63
64    private CameraActivity mActivity;
65    private PhotoController mController;
66    private PreviewGestures mGestures;
67
68    private View mRootView;
69    private Object mSurfaceTexture;
70    private volatile SurfaceHolder mSurfaceHolder;
71
72    private AbstractSettingPopup mPopup;
73    private ShutterButton mShutterButton;
74    private CountDownView mCountDownView;
75
76    private FaceView mFaceView;
77    private RenderOverlay mRenderOverlay;
78    private View mReviewCancelButton;
79    private View mReviewDoneButton;
80    private View mReviewRetakeButton;
81
82    private View mMenuButton;
83    private View mBlocker;
84    private PhotoMenu mMenu;
85
86    // Small indicators which show the camera settings in the viewfinder.
87    private ImageView mExposureIndicator;
88    private ImageView mFlashIndicator;
89    private ImageView mSceneIndicator;
90    private ImageView mHdrIndicator;
91    // A view group that contains all the small indicators.
92    private View mOnScreenIndicators;
93
94    private PieRenderer mPieRenderer;
95    private ZoomRenderer mZoomRenderer;
96    private Toast mNotSelectableToast;
97
98    private int mZoomMax;
99    private List<Integer> mZoomRatios;
100
101    private int mPreviewWidth = 0;
102    private int mPreviewHeight = 0;
103
104    private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() {
105        @Override
106        public void onLayoutChange(View v, int left, int top, int right,
107                int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
108            int width = right - left;
109            int height = bottom - top;
110            // Full-screen screennail
111            int w = width;
112            int h = height;
113            if (Util.getDisplayRotation(mActivity) % 180 != 0) {
114                w = height;
115                h = width;
116            }
117            if (mPreviewWidth != w || mPreviewHeight != h) {
118                mPreviewWidth = w;
119                mPreviewHeight = h;
120                mController.onScreenSizeChanged(width, height, w, h);
121            }
122        }
123    };
124
125    public PhotoUI(CameraActivity activity, PhotoController controller, View parent) {
126        mActivity = activity;
127        mController = controller;
128        mRootView = parent;
129
130        mActivity.getLayoutInflater().inflate(R.layout.photo_module,
131                (ViewGroup) mRootView, true);
132        mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay);
133
134        initIndicators();
135        mCountDownView = (CountDownView) (mRootView.findViewById(R.id.count_down_to_capture));
136        mCountDownView.setCountDownFinishedListener((OnCountDownFinishedListener) mController);
137
138        if (ApiHelper.HAS_FACE_DETECTION) {
139            ViewStub faceViewStub = (ViewStub) mRootView
140                    .findViewById(R.id.face_view_stub);
141            if (faceViewStub != null) {
142                faceViewStub.inflate();
143                mFaceView = (FaceView) mRootView.findViewById(R.id.face_view);
144            }
145        }
146
147    }
148
149    public View getRootView() {
150        return mRootView;
151    }
152
153    private void initIndicators() {
154        mOnScreenIndicators = mActivity.findViewById(R.id.on_screen_indicators);
155        mExposureIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_exposure_indicator);
156        mFlashIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_flash_indicator);
157        mSceneIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_scenemode_indicator);
158        mHdrIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_hdr_indicator);
159    }
160
161    public void onCameraOpened(PreferenceGroup prefGroup, ComboPreferences prefs,
162            Camera.Parameters params, OnPreferenceChangedListener listener) {
163        if (mPieRenderer == null) {
164            mPieRenderer = new PieRenderer(mActivity);
165            mPieRenderer.setPieListener(this);
166            mRenderOverlay.addRenderer(mPieRenderer);
167        }
168        if (mMenu == null) {
169            mMenu = new PhotoMenu(mActivity, this, mPieRenderer);
170            mMenu.setListener(listener);
171        }
172        mMenu.initialize(prefGroup);
173
174        if (mZoomRenderer == null) {
175            mZoomRenderer = new ZoomRenderer(mActivity);
176            mRenderOverlay.addRenderer(mZoomRenderer);
177        }
178        if (mGestures == null) {
179            // this will handle gesture disambiguation and dispatching
180            mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer,
181                    this);
182        }
183        mGestures.reset();
184        mGestures.setRenderOverlay(mRenderOverlay);
185        mGestures.addTouchReceiver(mMenuButton);
186        mGestures.addUnclickableArea(mBlocker);
187        // make sure to add touch targets for image capture
188        if (mController.isImageCaptureIntent()) {
189            if (mReviewCancelButton != null) {
190                mGestures.addTouchReceiver(mReviewCancelButton);
191            }
192            if (mReviewDoneButton != null) {
193                mGestures.addTouchReceiver(mReviewDoneButton);
194            }
195        }
196        mRenderOverlay.requestLayout();
197
198        initializeZoom(params);
199        updateOnScreenIndicators(params, prefs);
200    }
201
202    private void openMenu() {
203        if (mPieRenderer != null) {
204            // If autofocus is not finished, cancel autofocus so that the
205            // subsequent touch can be handled by PreviewGestures
206            if (mController.getCameraState() == PhotoController.FOCUSING) {
207                    mController.cancelAutoFocus();
208            }
209            mPieRenderer.showInCenter();
210        }
211    }
212
213    public void initializeControlByIntent() {
214        mBlocker = mActivity.findViewById(R.id.blocker);
215        mMenuButton = mActivity.findViewById(R.id.menu);
216        mMenuButton.setOnClickListener(new OnClickListener() {
217            @Override
218            public void onClick(View v) {
219                openMenu();
220            }
221        });
222        if (mController.isImageCaptureIntent()) {
223            mActivity.hideSwitcher();
224            ViewGroup cameraControls = (ViewGroup) mActivity.findViewById(R.id.camera_controls);
225            mActivity.getLayoutInflater().inflate(R.layout.review_module_control, cameraControls);
226
227            mReviewDoneButton = mActivity.findViewById(R.id.btn_done);
228            mReviewCancelButton = mActivity.findViewById(R.id.btn_cancel);
229            mReviewRetakeButton = mActivity.findViewById(R.id.btn_retake);
230            mReviewCancelButton.setVisibility(View.VISIBLE);
231
232            mReviewDoneButton.setOnClickListener(new OnClickListener() {
233                @Override
234                public void onClick(View v) {
235                    mController.onCaptureDone();
236                }
237            });
238            mReviewCancelButton.setOnClickListener(new OnClickListener() {
239                @Override
240                public void onClick(View v) {
241                    mController.onCaptureCancelled();
242                }
243            });
244
245            mReviewRetakeButton.setOnClickListener(new OnClickListener() {
246                @Override
247                public void onClick(View v) {
248                    mController.onCaptureRetake();
249                }
250            });
251        }
252    }
253
254    // called from onResume but only the first time
255    public  void initializeFirstTime() {
256        // Initialize shutter button.
257        mShutterButton = mActivity.getShutterButton();
258        mShutterButton.setImageResource(R.drawable.btn_new_shutter);
259        mShutterButton.setOnShutterButtonListener(mController);
260        mShutterButton.setVisibility(View.VISIBLE);
261        mRootView.addOnLayoutChangeListener(mLayoutListener);
262    }
263
264    // called from onResume every other time
265    public void initializeSecondTime(Camera.Parameters params) {
266        initializeZoom(params);
267        if (mController.isImageCaptureIntent()) {
268            hidePostCaptureAlert();
269        }
270        if (mMenu != null) {
271            mMenu.reloadPreferences();
272        }
273        mRootView.addOnLayoutChangeListener(mLayoutListener);
274    }
275
276    public void initializeZoom(Camera.Parameters params) {
277        if ((params == null) || !params.isZoomSupported()
278                || (mZoomRenderer == null)) return;
279        mZoomMax = params.getMaxZoom();
280        mZoomRatios = params.getZoomRatios();
281        // Currently we use immediate zoom for fast zooming to get better UX and
282        // there is no plan to take advantage of the smooth zoom.
283        if (mZoomRenderer != null) {
284            mZoomRenderer.setZoomMax(mZoomMax);
285            mZoomRenderer.setZoom(params.getZoom());
286            mZoomRenderer.setZoomValue(mZoomRatios.get(params.getZoom()));
287            mZoomRenderer.setOnZoomChangeListener(new ZoomChangeListener());
288        }
289    }
290
291    public void enableGestures(boolean enable) {
292        if (mGestures != null) {
293            mGestures.setEnabled(enable);
294        }
295    }
296
297    public void showGpsOnScreenIndicator(boolean hasSignal) { }
298
299    public void hideGpsOnScreenIndicator() { }
300
301    public void overrideSettings(final String ... keyvalues) {
302        mMenu.overrideSettings(keyvalues);
303    }
304
305    public void updateOnScreenIndicators(Camera.Parameters params,
306            ComboPreferences prefs) {
307        if (params == null) return;
308        updateSceneOnScreenIndicator(params.getSceneMode());
309        updateExposureOnScreenIndicator(params,
310                CameraSettings.readExposure(prefs));
311        updateFlashOnScreenIndicator(params.getFlashMode());
312        updateHdrOnScreenIndicator(params.getSceneMode());
313    }
314
315    private void updateExposureOnScreenIndicator(Camera.Parameters params, int value) {
316        if (mExposureIndicator == null) {
317            return;
318        }
319        int id = 0;
320        float step = params.getExposureCompensationStep();
321        value = (int) Math.round(value * step);
322        switch(value) {
323        case -3:
324            id = R.drawable.ic_indicator_ev_n3;
325            break;
326        case -2:
327            id = R.drawable.ic_indicator_ev_n2;
328            break;
329        case -1:
330            id = R.drawable.ic_indicator_ev_n1;
331            break;
332        case 0:
333            id = R.drawable.ic_indicator_ev_0;
334            break;
335        case 1:
336            id = R.drawable.ic_indicator_ev_p1;
337            break;
338        case 2:
339            id = R.drawable.ic_indicator_ev_p2;
340            break;
341        case 3:
342            id = R.drawable.ic_indicator_ev_p3;
343            break;
344        }
345        mExposureIndicator.setImageResource(id);
346    }
347
348    private void updateFlashOnScreenIndicator(String value) {
349        if (mFlashIndicator == null) {
350            return;
351        }
352        if (value == null || Parameters.FLASH_MODE_OFF.equals(value)) {
353            mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off);
354        } else {
355            if (Parameters.FLASH_MODE_AUTO.equals(value)) {
356                mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_auto);
357            } else if (Parameters.FLASH_MODE_ON.equals(value)) {
358                mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_on);
359            } else {
360                mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off);
361            }
362        }
363    }
364
365    private void updateSceneOnScreenIndicator(String value) {
366        if (mSceneIndicator == null) {
367            return;
368        }
369        if ((value == null) || Parameters.SCENE_MODE_AUTO.equals(value)
370                || Parameters.SCENE_MODE_HDR.equals(value)) {
371            mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_off);
372        } else {
373            mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_on);
374        }
375    }
376
377    private void updateHdrOnScreenIndicator(String value) {
378        if (mHdrIndicator == null) {
379            return;
380        }
381        if ((value != null) && Parameters.SCENE_MODE_HDR.equals(value)) {
382            mHdrIndicator.setImageResource(R.drawable.ic_indicator_hdr_on);
383        } else {
384            mHdrIndicator.setImageResource(R.drawable.ic_indicator_hdr_off);
385        }
386    }
387
388    public void setCameraState(int state) {
389    }
390
391    public boolean dispatchTouchEvent(MotionEvent m) {
392        if (mGestures != null && mRenderOverlay != null) {
393            return mGestures.dispatchTouch(m);
394        }
395        return false;
396    }
397
398    public boolean onBackPressed() {
399        if (mPieRenderer != null && mPieRenderer.showsItems()) {
400            mPieRenderer.hide();
401            return true;
402        }
403        // In image capture mode, back button should:
404        // 1) if there is any popup, dismiss them, 2) otherwise, get out of
405        // image capture
406        if (mController.isImageCaptureIntent()) {
407            if (!removeTopLevelPopup()) {
408                // no popup to dismiss, cancel image capture
409                mController.onCaptureCancelled();
410            }
411            return true;
412        } else if (!mController.isCameraIdle()) {
413            // ignore backs while we're taking a picture
414            return true;
415        } else {
416            return removeTopLevelPopup();
417        }
418    }
419
420    public void onFullScreenChanged(boolean full) {
421        if (mFaceView != null) {
422            mFaceView.setBlockDraw(!full);
423        }
424        if (mPopup != null) {
425            dismissPopup(false, full);
426        }
427        if (mGestures != null) {
428            mGestures.setEnabled(full);
429        }
430        if (mRenderOverlay != null) {
431            // this can not happen in capture mode
432            mRenderOverlay.setVisibility(full ? View.VISIBLE : View.GONE);
433        }
434        if (mPieRenderer != null) {
435            mPieRenderer.setBlockFocus(!full);
436        }
437        setShowMenu(full);
438        if (mBlocker != null) {
439            mBlocker.setVisibility(full ? View.VISIBLE : View.GONE);
440        }
441        if (!full && mCountDownView != null) mCountDownView.cancelCountDown();
442    }
443
444    public boolean removeTopLevelPopup() {
445        // Remove the top level popup or dialog box and return true if there's any
446        if (mPopup != null) {
447            dismissPopup(true);
448            return true;
449        }
450        return false;
451    }
452
453    public void showPopup(AbstractSettingPopup popup) {
454        mActivity.hideUI();
455        mBlocker.setVisibility(View.INVISIBLE);
456        setShowMenu(false);
457        mPopup = popup;
458        mPopup.setVisibility(View.VISIBLE);
459        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
460                LayoutParams.WRAP_CONTENT);
461        lp.gravity = Gravity.CENTER;
462        ((FrameLayout) mRootView).addView(mPopup, lp);
463        mGestures.addTouchReceiver(mPopup);
464    }
465
466    public void dismissPopup(boolean topPopupOnly) {
467        dismissPopup(topPopupOnly, true);
468    }
469
470    private void dismissPopup(boolean topOnly, boolean fullScreen) {
471        if (fullScreen) {
472            mActivity.showUI();
473            mBlocker.setVisibility(View.VISIBLE);
474        }
475        setShowMenu(fullScreen);
476        if (mPopup != null) {
477            mGestures.removeTouchReceiver(mPopup);
478            ((FrameLayout) mRootView).removeView(mPopup);
479            mPopup = null;
480        }
481        mMenu.popupDismissed(topOnly);
482    }
483
484    public void onShowSwitcherPopup() {
485        if (mPieRenderer != null && mPieRenderer.showsItems()) {
486            mPieRenderer.hide();
487        }
488    }
489
490    private void setShowMenu(boolean show) {
491        if (mOnScreenIndicators != null) {
492            mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE);
493        }
494        if (mMenuButton != null) {
495            mMenuButton.setVisibility(show ? View.VISIBLE : View.GONE);
496        }
497    }
498
499    public boolean collapseCameraControls() {
500        // Remove all the popups/dialog boxes
501        boolean ret = false;
502        if (mPopup != null) {
503            dismissPopup(false);
504            ret = true;
505        }
506        return ret;
507    }
508
509    protected void showPostCaptureAlert() {
510        mOnScreenIndicators.setVisibility(View.GONE);
511        mMenuButton.setVisibility(View.GONE);
512        Util.fadeIn(mReviewDoneButton);
513        mShutterButton.setVisibility(View.INVISIBLE);
514        Util.fadeIn(mReviewRetakeButton);
515    }
516
517    protected void hidePostCaptureAlert() {
518        mOnScreenIndicators.setVisibility(View.VISIBLE);
519        mMenuButton.setVisibility(View.VISIBLE);
520        Util.fadeOut(mReviewDoneButton);
521        mShutterButton.setVisibility(View.VISIBLE);
522        Util.fadeOut(mReviewRetakeButton);
523    }
524
525    public void setDisplayOrientation(int orientation) {
526        if (mFaceView != null) {
527            mFaceView.setDisplayOrientation(orientation);
528        }
529    }
530
531    // shutter button handling
532
533    public boolean isShutterPressed() {
534        return mShutterButton.isPressed();
535    }
536
537    // focus handling
538
539
540    private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener {
541        @Override
542        public void onZoomValueChanged(int index) {
543            int newZoom = mController.onZoomChanged(index);
544            if (mZoomRenderer != null) {
545                mZoomRenderer.setZoomValue(mZoomRatios.get(newZoom));
546            }
547        }
548
549        @Override
550        public void onZoomStart() {
551            if (mPieRenderer != null) {
552                mPieRenderer.setBlockFocus(true);
553            }
554        }
555
556        @Override
557        public void onZoomEnd() {
558            if (mPieRenderer != null) {
559                mPieRenderer.setBlockFocus(false);
560            }
561        }
562    }
563
564    @Override
565    public void onPieOpened(int centerX, int centerY) {
566        mActivity.cancelActivityTouchHandling();
567        mActivity.setSwipingEnabled(false);
568        if (mFaceView != null) {
569            mFaceView.setBlockDraw(true);
570        }
571    }
572
573    @Override
574    public void onPieClosed() {
575        mActivity.setSwipingEnabled(true);
576        if (mFaceView != null) {
577            mFaceView.setBlockDraw(false);
578        }
579    }
580
581    // Surface Listener
582
583    @Override
584    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
585        Log.v(TAG, "surfaceChanged:" + holder + " width=" + width + ". height="
586                + height);
587    }
588
589    @Override
590    public void surfaceCreated(SurfaceHolder holder) {
591        Log.v(TAG, "surfaceCreated: " + holder);
592        mSurfaceHolder = holder;
593        mController.onSurfaceCreated(holder);
594    }
595
596    @Override
597    public void surfaceDestroyed(SurfaceHolder holder) {
598        Log.v(TAG, "surfaceDestroyed: " + holder);
599        mSurfaceHolder = null;
600        mController.stopPreview();
601    }
602
603    public Object getSurfaceTexture() {
604        return mSurfaceTexture;
605    }
606
607    public void setSurfaceTexture(Object st) {
608        mSurfaceTexture = st;
609    }
610
611    public SurfaceHolder getSurfaceHolder() {
612        return mSurfaceHolder;
613    }
614
615    public boolean isCountingDown() {
616        return mCountDownView.isCountingDown();
617    }
618
619    public void cancelCountDown() {
620        mCountDownView.cancelCountDown();
621    }
622
623    public void startCountDown(int sec, boolean playSound) {
624        mCountDownView.startCountDown(sec, playSound);
625    }
626
627    public void showPreferencesToast() {
628        if (mNotSelectableToast == null) {
629            String str = mActivity.getResources().getString(R.string.not_selectable_in_scene_mode);
630            mNotSelectableToast = Toast.makeText(mActivity, str, Toast.LENGTH_SHORT);
631        }
632        mNotSelectableToast.show();
633    }
634
635    public void onPause() {
636        mCountDownView.cancelCountDown();
637        // Close the camera now because other activities may need to use it.
638        mSurfaceTexture = null;
639
640        // Clear UI.
641        collapseCameraControls();
642        if (mFaceView != null) mFaceView.clear();
643
644
645        mRootView.removeOnLayoutChangeListener(mLayoutListener);
646        mPreviewWidth = 0;
647        mPreviewHeight = 0;
648    }
649
650    public void enableShutter(boolean enabled) {
651        if (mShutterButton != null) {
652            mShutterButton.setEnabled(enabled);
653        }
654    }
655
656    public void pressShutterButton() {
657        if (mShutterButton.isInTouchMode()) {
658            mShutterButton.requestFocusFromTouch();
659        } else {
660            mShutterButton.requestFocus();
661        }
662        mShutterButton.setPressed(true);
663    }
664
665    // forward from preview gestures to controller
666    @Override
667    public void onSingleTapUp(View view, int x, int y) {
668        mController.onSingleTapUp(view, x, y);
669    }
670
671    // focus UI implementation
672
673    private FocusIndicator getFocusIndicator() {
674        return (mFaceView != null && mFaceView.faceExists()) ? mFaceView : mPieRenderer;
675    }
676
677    @Override
678    public boolean hasFaces() {
679        return (mFaceView != null && mFaceView.faceExists());
680    }
681
682    public void clearFaces() {
683        if (mFaceView != null) mFaceView.clear();
684    }
685
686    @Override
687    public void clearFocus() {
688        FocusIndicator indicator = getFocusIndicator();
689        if (indicator != null) indicator.clear();
690    }
691
692    @Override
693    public void setFocusPosition(int x, int y) {
694        mPieRenderer.setFocus(x, y);
695    }
696
697    @Override
698    public void onFocusStarted() {
699        getFocusIndicator().showStart();
700    }
701
702    @Override
703    public void onFocusSucceeded(boolean timeout) {
704        getFocusIndicator().showSuccess(timeout);
705    }
706
707    @Override
708    public void onFocusFailed(boolean timeout) {
709        getFocusIndicator().showFail(timeout);
710    }
711
712    @Override
713    public void pauseFaceDetection() {
714        if (mFaceView != null) mFaceView.pause();
715    }
716
717    @Override
718    public void resumeFaceDetection() {
719        if (mFaceView != null) mFaceView.resume();
720    }
721
722    public void onStartFaceDetection(int orientation, boolean mirror) {
723        mFaceView.clear();
724        mFaceView.setVisibility(View.VISIBLE);
725        mFaceView.setDisplayOrientation(orientation);
726        mFaceView.setMirror(mirror);
727        mFaceView.resume();
728    }
729
730    @Override
731    public void onFaceDetection(Face[] faces, android.hardware.Camera camera) {
732        mFaceView.setFaces(faces);
733    }
734
735    @Override
736    public void onSwipe(int direction) {
737        if (direction == PreviewGestures.DIR_UP) {
738            openMenu();
739        }
740    }
741
742}
743