Home | History | Annotate | Download | only in camera
      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 
    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 
    142     public View getRootView() {
    143         return mRootView;
    144     }
    145 
    146     private void initIndicators() {
    147         mOnScreenIndicators = new OnScreenIndicators(mActivity,
    148                 mActivity.findViewById(R.id.on_screen_indicators));
    149     }
    150 
    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 
    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 
    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
    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
    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 
    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 
    289     public void enableGestures(boolean enable) {
    290         if (mGestures != null) {
    291             mGestures.setEnabled(enable);
    292         }
    293     }
    294 
    295     @Override
    296     public void showGpsOnScreenIndicator(boolean hasSignal) { }
    297 
    298     @Override
    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             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 
    323     public void setCameraState(int state) {
    324     }
    325 
    326     public boolean dispatchTouchEvent(MotionEvent m) {
    327         if (mGestures != null && mRenderOverlay != null) {
    328             return mGestures.dispatchTouch(m);
    329         }
    330         return false;
    331     }
    332 
    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 
    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 
    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 
    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 
    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 
    411     public void dismissPopup() {
    412         dismissPopup(true);
    413     }
    414 
    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 
    429     public void onShowSwitcherPopup() {
    430         if (mPieRenderer != null && mPieRenderer.showsItems()) {
    431             mPieRenderer.hide();
    432         }
    433     }
    434 
    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 
    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 
    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 
    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 
    473     public void setDisplayOrientation(int orientation) {
    474         if (mFaceView != null) {
    475             mFaceView.setDisplayOrientation(orientation);
    476         }
    477     }
    478 
    479     // shutter button handling
    480 
    481     public boolean isShutterPressed() {
    482         return mShutterButton.isPressed();
    483     }
    484 
    485     // focus handling
    486 
    487 
    488     private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener {
    489         @Override
    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
    498         public void onZoomStart() {
    499             if (mPieRenderer != null) {
    500                 mPieRenderer.setBlockFocus(true);
    501             }
    502         }
    503 
    504         @Override
    505         public void onZoomEnd() {
    506             if (mPieRenderer != null) {
    507                 mPieRenderer.setBlockFocus(false);
    508             }
    509         }
    510     }
    511 
    512     @Override
    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
    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
    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
    539     public void surfaceCreated(SurfaceHolder holder) {
    540         Log.v(TAG, "surfaceCreated: " + holder);
    541         mSurfaceHolder = holder;
    542         mController.onSurfaceCreated(holder);
    543     }
    544 
    545     @Override
    546     public void surfaceDestroyed(SurfaceHolder holder) {
    547         Log.v(TAG, "surfaceDestroyed: " + holder);
    548         mSurfaceHolder = null;
    549         mController.stopPreview();
    550     }
    551 
    552     public Object getSurfaceTexture() {
    553         return mSurfaceTexture;
    554     }
    555 
    556     public void setSurfaceTexture(Object st) {
    557         mSurfaceTexture = st;
    558     }
    559 
    560     public SurfaceHolder getSurfaceHolder() {
    561         return mSurfaceHolder;
    562     }
    563 
    564     public boolean isCountingDown() {
    565         return mCountDownView.isCountingDown();
    566     }
    567 
    568     public void cancelCountDown() {
    569         mCountDownView.cancelCountDown();
    570     }
    571 
    572     public void startCountDown(int sec, boolean playSound) {
    573         mCountDownView.startCountDown(sec, playSound);
    574     }
    575 
    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 
    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 
    599     public void enableShutter(boolean enabled) {
    600         if (mShutterButton != null) {
    601             mShutterButton.setEnabled(enabled);
    602         }
    603     }
    604 
    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
    616     public void onSingleTapUp(View view, int x, int y) {
    617         mController.onSingleTapUp(view, x, y);
    618     }
    619 
    620     // focus UI implementation
    621 
    622     private FocusIndicator getFocusIndicator() {
    623         return (mFaceView != null && mFaceView.faceExists()) ? mFaceView : mPieRenderer;
    624     }
    625 
    626     @Override
    627     public boolean hasFaces() {
    628         return (mFaceView != null && mFaceView.faceExists());
    629     }
    630 
    631     public void clearFaces() {
    632         if (mFaceView != null) mFaceView.clear();
    633     }
    634 
    635     @Override
    636     public void clearFocus() {
    637         FocusIndicator indicator = getFocusIndicator();
    638         if (indicator != null) indicator.clear();
    639     }
    640 
    641     @Override
    642     public void setFocusPosition(int x, int y) {
    643         mPieRenderer.setFocus(x, y);
    644     }
    645 
    646     @Override
    647     public void onFocusStarted() {
    648         getFocusIndicator().showStart();
    649     }
    650 
    651     @Override
    652     public void onFocusSucceeded(boolean timeout) {
    653         getFocusIndicator().showSuccess(timeout);
    654     }
    655 
    656     @Override
    657     public void onFocusFailed(boolean timeout) {
    658         getFocusIndicator().showFail(timeout);
    659     }
    660 
    661     @Override
    662     public void pauseFaceDetection() {
    663         if (mFaceView != null) mFaceView.pause();
    664     }
    665 
    666     @Override
    667     public void resumeFaceDetection() {
    668         if (mFaceView != null) mFaceView.resume();
    669     }
    670 
    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
    680     public void onFaceDetection(Face[] faces, android.hardware.Camera camera) {
    681         mFaceView.setFaces(faces);
    682     }
    683 
    684     @Override
    685     public void onSwipe(int direction) {
    686         if (direction == PreviewGestures.DIR_UP) {
    687             openMenu();
    688         }
    689     }
    690 
    691 }
    692