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