OSDN Git Service

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