PhotoModule.java revision b19c713286b7beed376ec6c4390e7272a80aa5b9
1d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb/* 2d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * Copyright (C) 2012 The Android Open Source Project 3d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * 4d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License"); 5d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * you may not use this file except in compliance with the License. 6d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * You may obtain a copy of the License at 7d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * 8d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * http://www.apache.org/licenses/LICENSE-2.0 9d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * 10d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * Unless required by applicable law or agreed to in writing, software 11d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS, 12d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * See the License for the specific language governing permissions and 14d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * limitations under the License. 15d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb */ 16d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 17d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbpackage com.android.camera; 18d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 19d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.annotation.TargetApi; 20d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.app.Activity; 21d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.content.BroadcastReceiver; 22d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.content.ContentProviderClient; 23d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.content.ContentResolver; 24d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.content.Context; 25d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.content.Intent; 26d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.content.IntentFilter; 27d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.content.SharedPreferences.Editor; 28d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.content.res.Configuration; 29d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.graphics.Bitmap; 30d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.graphics.SurfaceTexture; 31d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.hardware.Camera.CameraInfo; 32d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.hardware.Camera.Face; 33d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.hardware.Camera.FaceDetectionListener; 34d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.hardware.Camera.Parameters; 35d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.hardware.Camera.PictureCallback; 36d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.hardware.Camera.Size; 37d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.location.Location; 38d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.media.CameraProfile; 39d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.net.Uri; 40d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.os.Bundle; 41d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.os.ConditionVariable; 42d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.os.Handler; 43d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.os.Looper; 44d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.os.Message; 45d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.os.MessageQueue; 46d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.os.SystemClock; 47d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.provider.MediaStore; 48d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.util.Log; 49d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.view.KeyEvent; 50d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.view.LayoutInflater; 51d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.view.MotionEvent; 52d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.view.OrientationEventListener; 53d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.view.SurfaceHolder; 54d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.view.View; 55d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.view.ViewGroup; 56d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.view.WindowManager; 57d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.widget.ImageView; 58d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.widget.LinearLayout; 59d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.widget.TextView; 60d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport android.widget.Toast; 61d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 62d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.camera.CameraManager.CameraProxy; 63d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.camera.ui.FaceView; 64b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolbimport com.android.camera.ui.FocusRenderer; 65d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.camera.ui.PopupManager; 66d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.camera.ui.PreviewSurfaceView; 67b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolbimport com.android.camera.ui.RenderOverlay; 68d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.camera.ui.Rotatable; 69d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.camera.ui.RotateImageView; 70d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.camera.ui.RotateLayout; 71d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.camera.ui.RotateTextToast; 72d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.camera.ui.TwoStateImageView; 73d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.camera.ui.ZoomControl; 74d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport com.android.gallery3d.common.ApiHelper; 75d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 76d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport java.io.File; 77d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport java.io.FileNotFoundException; 78d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport java.io.FileOutputStream; 79d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport java.io.IOException; 80d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport java.io.OutputStream; 81d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport java.util.ArrayList; 82d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport java.util.Collections; 83d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport java.util.Formatter; 84d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbimport java.util.List; 85d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 86d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolbpublic class PhotoModule 87d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb implements CameraModule, 88b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb FocusOverlayManager.Listener, 89d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraPreference.OnPreferenceChangedListener, 90d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb LocationManager.Listener, 91d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb PreviewFrameLayout.OnSizeChangedListener, 92d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb ShutterButton.OnShutterButtonListener, 93d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb SurfaceHolder.Callback { 94d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 95d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final String TAG = "CAM_PhotoModule"; 96d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 97d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We number the request code from 1000 to avoid collision with Gallery. 98d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int REQUEST_CROP = 1000; 99d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 100d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int SETUP_PREVIEW = 1; 101d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int FIRST_TIME_INIT = 2; 102d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int CLEAR_SCREEN_DELAY = 3; 103d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int SET_CAMERA_PARAMETERS_WHEN_IDLE = 4; 104d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int CHECK_DISPLAY_ROTATION = 5; 105d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int SHOW_TAP_TO_FOCUS_TOAST = 6; 106d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int UPDATE_THUMBNAIL = 7; 107d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int SWITCH_CAMERA = 8; 108d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int SWITCH_CAMERA_START_ANIMATION = 9; 109d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int CAMERA_OPEN_DONE = 10; 110d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int START_PREVIEW_DONE = 11; 111d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int OPEN_CAMERA_FAIL = 12; 112d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int CAMERA_DISABLED = 13; 113d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 114d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // The subset of parameters we need to update in setCameraParameters(). 115d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int UPDATE_PARAM_INITIALIZE = 1; 116d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int UPDATE_PARAM_ZOOM = 2; 117d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int UPDATE_PARAM_PREFERENCE = 4; 118d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int UPDATE_PARAM_ALL = -1; 119d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 120d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // copied from Camera hierarchy 121d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private CameraActivity mActivity; 122d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private View mRootView; 123d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private CameraProxy mCameraDevice; 124d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mCameraId; 125d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Parameters mParameters; 126d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mPaused; 127d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 128d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // these are only used by Camera 129d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 130d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // The activity is going to switch to the specified camera id. This is 131d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // needed because texture copy is done in GL thread. -1 means camera is not 132d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // switching. 133d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb protected int mPendingSwitchCameraId = -1; 134d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mOpenCameraFail; 135d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mCameraDisabled; 136d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 137d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // When setCameraParametersWhenIdle() is called, we accumulate the subsets 138d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // needed to be updated in mUpdateSet. 139d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mUpdateSet; 140d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 141d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int SCREEN_DELAY = 2 * 60 * 1000; 142d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 143d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mZoomValue; // The current zoom value. 144d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mZoomMax; 145d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 146d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Parameters mInitialParams; 147d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mFocusAreaSupported; 148d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mMeteringAreaSupported; 149d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mAeLockSupported; 150d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mAwbLockSupported; 151d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mContinousFocusSupported; 152d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 153d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private MyOrientationEventListener mOrientationListener; 154d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // The degrees of the device rotated clockwise from its natural orientation. 155d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN; 156d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // The orientation compensation for icons and thumbnails. Ex: if the value 157d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // is 90, the UI components should be rotated 90 degrees counter-clockwise. 158d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mOrientationCompensation = 0; 159d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ComboPreferences mPreferences; 160d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 161d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final String sTempCropFilename = "crop-temp"; 162d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 163d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ContentProviderClient mMediaProviderClient; 164d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ShutterButton mShutterButton; 165d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mFaceDetectionStarted = false; 166d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 167d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private PreviewFrameLayout mPreviewFrameLayout; 168d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Object mSurfaceTexture; 169d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 170d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // for API level 10 171d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private PreviewSurfaceView mPreviewSurfaceView; 172d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private volatile SurfaceHolder mCameraSurfaceHolder; 173d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 174d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private RotateDialogController mRotateDialog; 175d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ModePicker mModePicker; 176d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private FaceView mFaceView; 177b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb private RenderOverlay mRenderOverlay; 178d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Rotatable mReviewCancelButton; 179d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Rotatable mReviewDoneButton; 180d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private View mReviewRetakeButton; 181d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 182d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // mCropValue and mSaveUri are used only if isImageCaptureIntent() is true. 183d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private String mCropValue; 184d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Uri mSaveUri; 185d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 186d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Small indicators which show the camera settings in the viewfinder. 187d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private TextView mExposureIndicator; 188d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ImageView mGpsIndicator; 189d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ImageView mFlashIndicator; 190d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ImageView mSceneIndicator; 191d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ImageView mWhiteBalanceIndicator; 192d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ImageView mFocusIndicator; 193d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // A view group that contains all the small indicators. 194d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Rotatable mOnScreenIndicators; 195d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 196d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We use a thread in ImageSaver to do the work of saving images and 197d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // generating thumbnails. This reduces the shot-to-shot time. 198d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ImageSaver mImageSaver; 199d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Similarly, we use a thread to generate the name of the picture and insert 200d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // it into MediaStore while picture taking is still in progress. 201d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ImageNamer mImageNamer; 202d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 203d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private SoundClips.Player mSoundPlayer; 204d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 205d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Runnable mDoSnapRunnable = new Runnable() { 206d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 207d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void run() { 208d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb onShutterButtonClick(); 209d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 210d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb }; 211d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 212d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final StringBuilder mBuilder = new StringBuilder(); 213d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final Formatter mFormatter = new Formatter(mBuilder); 214d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final Object[] mFormatterArgs = new Object[1]; 215d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 216d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb /** 217d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * An unpublished intent flag requesting to return as soon as capturing 218d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * is completed. 219d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * 220d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * TODO: consider publishing by moving into MediaStore. 221d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb */ 222d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final String EXTRA_QUICK_CAPTURE = 223d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb "android.intent.extra.quickCapture"; 224d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 225d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // The display rotation in degrees. This is only valid when mCameraState is 226d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // not PREVIEW_STOPPED. 227d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mDisplayRotation; 228d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // The value for android.hardware.Camera.setDisplayOrientation. 229d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mCameraDisplayOrientation; 230d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // The value for UI components like indicators. 231d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mDisplayOrientation; 232d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // The value for android.hardware.Camera.Parameters.setRotation. 233d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mJpegRotation; 234d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mFirstTimeInitialized; 235d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mIsImageCaptureIntent; 236d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 237d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int PREVIEW_STOPPED = 0; 238d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int IDLE = 1; // preview is active 239d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Focus is in progress. The exact focus state is in Focus.java. 240d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int FOCUSING = 2; 241d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int SNAPSHOT_IN_PROGRESS = 3; 242d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Switching between cameras. 243d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int SWITCHING_CAMERA = 4; 244d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mCameraState = PREVIEW_STOPPED; 245d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mSnapshotOnIdle = false; 246d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 247d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ContentResolver mContentResolver; 248d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mDidRegister = false; 249d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 250d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private LocationManager mLocationManager; 251d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 252d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final ShutterCallback mShutterCallback = new ShutterCallback(); 253d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final PostViewPictureCallback mPostViewPictureCallback = 254d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb new PostViewPictureCallback(); 255d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final RawPictureCallback mRawPictureCallback = 256d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb new RawPictureCallback(); 257d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final AutoFocusCallback mAutoFocusCallback = 258d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb new AutoFocusCallback(); 259d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final Object mAutoFocusMoveCallback = 260d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK 261d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb ? new AutoFocusMoveCallback() 262d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb : null; 263d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 264d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final CameraErrorCallback mErrorCallback = new CameraErrorCallback(); 265d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 266d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private long mFocusStartTime; 267d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private long mShutterCallbackTime; 268d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private long mPostViewPictureCallbackTime; 269d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private long mRawPictureCallbackTime; 270d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private long mJpegPictureCallbackTime; 271d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private long mOnResumeTime; 272d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private byte[] mJpegImageData; 273d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 274d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // These latency time are for the CameraLatency test. 275d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public long mAutoFocusTime; 276d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public long mShutterLag; 277d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public long mShutterToPictureDisplayedTime; 278d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public long mPictureDisplayedToJpegCallbackTime; 279d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public long mJpegCallbackFinishTime; 280d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public long mCaptureStartTime; 281d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 282d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // This handles everything about focus. 283b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb private FocusOverlayManager mFocusManager; 284b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb private FocusRenderer mFocusRenderer; 285b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb 286d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private String mSceneMode; 287d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Toast mNotSelectableToast; 288d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 289d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final Handler mHandler = new MainHandler(); 290d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private PreferenceGroup mPreferenceGroup; 291d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 292d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mQuickCapture; 293d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 294d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraStartUpThread mCameraStartUpThread; 295d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb ConditionVariable mStartPreviewPrerequisiteReady = new ConditionVariable(); 296d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 297d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb protected class CameraOpenThread extends Thread { 298d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 299d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void run() { 300d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 301d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice = Util.openCamera(mActivity, mCameraId); 302d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters = mCameraDevice.getParameters(); 303d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (CameraHardwareException e) { 304d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mOpenCameraFail = true; 305d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (CameraDisabledException e) { 306d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDisabled = true; 307d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 308d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 309d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 310d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 311d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // The purpose is not to block the main thread in onCreate and onResume. 312d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private class CameraStartUpThread extends Thread { 313d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private volatile boolean mCancelled; 314d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 315d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void cancel() { 316d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCancelled = true; 317d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 318d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 319d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 320d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void run() { 321d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 322d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We need to check whether the activity is paused before long 323d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // operations to ensure that onPause() can be done ASAP. 324d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCancelled) return; 325d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice = Util.openCamera(mActivity, mCameraId); 326d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters = mCameraDevice.getParameters(); 327d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Wait until all the initialization needed by startPreview are 328d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // done. 329d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mStartPreviewPrerequisiteReady.block(); 330d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 331d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeCapabilities(); 332d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFocusManager == null) initializeFocusManager(); 333d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCancelled) return; 334d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraParameters(UPDATE_PARAM_ALL); 335d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessage(CAMERA_OPEN_DONE); 336d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCancelled) return; 337d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb startPreview(); 338d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessage(START_PREVIEW_DONE); 339d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mOnResumeTime = SystemClock.uptimeMillis(); 340d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessage(CHECK_DISPLAY_ROTATION); 341d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (CameraHardwareException e) { 342d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessage(OPEN_CAMERA_FAIL); 343d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (CameraDisabledException e) { 344d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessage(CAMERA_DISABLED); 345d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 346d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 347d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 348d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 349d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb /** 350d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * This Handler is used to post message back onto the main thread of the 351d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb * application 352d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb */ 353d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private class MainHandler extends Handler { 354d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 355d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void handleMessage(Message msg) { 356d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb switch (msg.what) { 357d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case SETUP_PREVIEW: { 358d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setupPreview(); 359d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 360d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 361d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 362d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case CLEAR_SCREEN_DELAY: { 363d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getWindow().clearFlags( 364d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 365d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 366d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 367d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 368d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case FIRST_TIME_INIT: { 369d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeFirstTime(); 370d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 371d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 372d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 373d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case SET_CAMERA_PARAMETERS_WHEN_IDLE: { 374d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraParametersWhenIdle(0); 375d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 376d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 377d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 378d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case CHECK_DISPLAY_ROTATION: { 379d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set the display orientation if display rotation has changed. 380d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Sometimes this happens when the device is held upside 381d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // down and camera app is opened. Rotation animation will 382d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // take some time and the rotation value we have got may be 383d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // wrong. Framework does not have a callback for this now. 384d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (Util.getDisplayRotation(mActivity) != mDisplayRotation) { 385d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setDisplayOrientation(); 386d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 387d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (SystemClock.uptimeMillis() - mOnResumeTime < 5000) { 388d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100); 389d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 390d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 391d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 392d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 393d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case SHOW_TAP_TO_FOCUS_TOAST: { 394d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb showTapToFocusToast(); 395d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 396d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 397d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 398d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case UPDATE_THUMBNAIL: { 399d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageSaver.updateThumbnail(); 400d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 401d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 402d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 403d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case SWITCH_CAMERA: { 404d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb switchCamera(); 405d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 406d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 407d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 408d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case SWITCH_CAMERA_START_ANIMATION: { 409b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb ((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera(); 410d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 411d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 412d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 413d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case CAMERA_OPEN_DONE: { 414d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeAfterCameraOpen(); 415d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 416d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 417d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 418d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case START_PREVIEW_DONE: { 419d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraStartUpThread = null; 420d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraState(IDLE); 421d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!ApiHelper.HAS_SURFACE_TEXTURE) { 422d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // This may happen if surfaceCreated has arrived. 423d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setPreviewDisplayAsync(mCameraSurfaceHolder); 424d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 425d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb startFaceDetection(); 426d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 427d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 428d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 429d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case OPEN_CAMERA_FAIL: { 430d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraStartUpThread = null; 431d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mOpenCameraFail = true; 432d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.showErrorAndFinish(mActivity, 433d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb R.string.cannot_connect_camera); 434d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 435d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 436d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 437d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case CAMERA_DISABLED: { 438d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraStartUpThread = null; 439d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDisabled = true; 440d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.showErrorAndFinish(mActivity, 441d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb R.string.camera_disabled); 442d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 443d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 444d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 445d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 446d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 447d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 448d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 449d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void init(CameraActivity activity, View parent) { 450d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity = activity; 451d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mRootView = parent; 452d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreferences = new ComboPreferences(mActivity); 453d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal()); 454d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraId = getPreferredCameraId(mPreferences); 455d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 456d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mContentResolver = mActivity.getContentResolver(); 457d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 458d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // To reduce startup time, open the camera and start the preview in 459d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // another thread. 460d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraStartUpThread = new CameraStartUpThread(); 461d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraStartUpThread.start(); 462d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 463d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getLayoutInflater().inflate(R.layout.photo_module, (ViewGroup) mRootView); 464d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 465d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Surface texture is from camera screen nail and startPreview needs it. 466d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // This must be done before startPreview. 467d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mIsImageCaptureIntent = isImageCaptureIntent(); 468d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.reuseCameraScreenNail(!mIsImageCaptureIntent); 469d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 470d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreferences.setLocalId(mActivity, mCameraId); 471d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); 472d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // we need to reset exposure for the preview 473d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb resetExposureCompensation(); 474d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Starting the preview needs preferences, camera screen nail, and 475d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // focus area indicator. 476d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mStartPreviewPrerequisiteReady.open(); 477d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 478d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeControlByIntent(); 479d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mRotateDialog = new RotateDialogController(mActivity, R.layout.rotate_dialog); 480d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false); 481d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeMiscControls(); 482d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mLocationManager = new LocationManager(mActivity, this); 483d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initOnScreenIndicator(); 484d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Make sure all views are disabled before camera is open. 485b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb// enableCameraControls(false); 486d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 487d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 488d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void initializeAfterCameraOpen() { 489b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb mFocusRenderer = new FocusRenderer(); 490b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb mRenderOverlay.addRenderer(mFocusRenderer); 491b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb mFocusManager.setFocusRenderer(mFocusRenderer); 492b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb mRenderOverlay.requestLayout(); 493b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb 494d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // These depend on camera parameters. 495d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setPreviewFrameLayoutAspectRatio(); 496d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.setPreviewSize(mPreviewFrameLayout.getWidth(), 497d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreviewFrameLayout.getHeight()); 498b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb loadCameraPreferences(); 499d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeZoom(); 500d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateOnScreenIndicators(); 501d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb showTapToFocusToastIfNeeded(); 502d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 503d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 504d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void resetExposureCompensation() { 505d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String value = mPreferences.getString(CameraSettings.KEY_EXPOSURE, 506d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings.EXPOSURE_DEFAULT_VALUE); 507d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!CameraSettings.EXPOSURE_DEFAULT_VALUE.equals(value)) { 508d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Editor editor = mPreferences.edit(); 509d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb editor.putString(CameraSettings.KEY_EXPOSURE, "0"); 510d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb editor.apply(); 511d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 512d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 513d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 514d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void keepMediaProviderInstance() { 515d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We want to keep a reference to MediaProvider in camera's lifecycle. 516d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // TODO: Utilize mMediaProviderClient instance to replace 517d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ContentResolver calls. 518d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mMediaProviderClient == null) { 519d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mMediaProviderClient = mContentResolver 520d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb .acquireContentProviderClient(MediaStore.AUTHORITY); 521d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 522d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 523d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 524d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Snapshots can only be taken after this is called. It should be called 525d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // once only. We could have done these things in onCreate() but we want to 526d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // make preview screen appear as soon as possible. 527d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void initializeFirstTime() { 528d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFirstTimeInitialized) return; 529d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 530d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Create orientation listener. This should be done first because it 531d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // takes some time to get first orientation. 532d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mOrientationListener = new MyOrientationEventListener(mActivity); 533d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mOrientationListener.enable(); 534d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 535d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Initialize location service. 536d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb boolean recordLocation = RecordLocationPreference.get( 537d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreferences, mContentResolver); 538d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mLocationManager.recordLocation(recordLocation); 539d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 540d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb keepMediaProviderInstance(); 541d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 542d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Initialize shutter button. 543d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterButton = mActivity.getShutterButton(); 544d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterButton.setImageResource(R.drawable.btn_shutter); 545d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterButton.setOnShutterButtonListener(this); 546d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterButton.setVisibility(View.VISIBLE); 547d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 548d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageSaver = new ImageSaver(); 549d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageNamer = new ImageNamer(); 550d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 551d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFirstTimeInitialized = true; 552d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb addIdleHandler(); 553d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 554d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.updateStorageSpaceAndHint(); 555d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 556d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 557d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void showTapToFocusToastIfNeeded() { 558d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Show the tap to focus toast if this is the first start. 559d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFocusAreaSupported && 560d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreferences.getBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, true)) { 561d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Delay the toast for one second to wait for orientation. 562d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessageDelayed(SHOW_TAP_TO_FOCUS_TOAST, 1000); 563d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 564d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 565d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 566d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void addIdleHandler() { 567d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb MessageQueue queue = Looper.myQueue(); 568d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb queue.addIdleHandler(new MessageQueue.IdleHandler() { 569d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 570d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public boolean queueIdle() { 571d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Storage.ensureOSXCompatible(); 572d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return false; 573d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 574d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb }); 575d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 576d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 577d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If the activity is paused and resumed, this method will be called in 578d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // onResume. 579d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void initializeSecondTime() { 580d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Start orientation listener as soon as possible because it takes 581d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // some time to get first orientation. 582d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mOrientationListener.enable(); 583d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 584d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Start location update if needed. 585d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb boolean recordLocation = RecordLocationPreference.get( 586d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreferences, mContentResolver); 587d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mLocationManager.recordLocation(recordLocation); 588d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 589d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageSaver = new ImageSaver(); 590d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageNamer = new ImageNamer(); 591d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeZoom(); 592d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb keepMediaProviderInstance(); 593d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb hidePostCaptureAlert(); 594d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 595d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mIsImageCaptureIntent) { 596d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mModePicker != null) { 597d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mModePicker.setCurrentMode(ModePicker.MODE_CAMERA); 598d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 599d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 600d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 601d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 602d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private class ZoomChangeListener implements ZoomControl.OnZoomChangedListener { 603d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 604d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onZoomValueChanged(int index) { 605d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Not useful to change zoom value when the activity is paused. 606d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused) return; 607d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mZoomValue = index; 608d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 609d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set zoom parameters asynchronously 610d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setZoom(mZoomValue); 611d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setParametersAsync(mParameters); 612d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 613d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 614d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 615d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void initializeZoom() { 616d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mParameters.isZoomSupported()) return; 617d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mZoomMax = mParameters.getMaxZoom(); 618d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 619d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 620d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) 621d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 622d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void startFaceDetection() { 623d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!ApiHelper.HAS_FACE_DETECTION) return; 624d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFaceDetectionStarted) return; 625d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mParameters.getMaxNumDetectedFaces() > 0) { 626d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceDetectionStarted = true; 627d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.clear(); 628d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.setVisibility(View.VISIBLE); 629d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.setDisplayOrientation(mDisplayOrientation); 630d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; 631d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.setMirror(info.facing == CameraInfo.CAMERA_FACING_FRONT); 632d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.resume(); 633d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.setFaceView(mFaceView); 634d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setFaceDetectionListener(new FaceDetectionListener() { 635d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 636d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onFaceDetection(Face[] faces, android.hardware.Camera camera) { 637d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.setFaces(faces); 638d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 639d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb }); 640d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.startFaceDetection(); 641d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 642d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 643d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 644d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 645d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) 646d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 647d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void stopFaceDetection() { 648d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!ApiHelper.HAS_FACE_DETECTION) return; 649d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mFaceDetectionStarted) return; 650d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mParameters.getMaxNumDetectedFaces() > 0) { 651d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceDetectionStarted = false; 652d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setFaceDetectionListener(null); 653d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.stopFaceDetection(); 654d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFaceView != null) mFaceView.clear(); 655d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 656d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 657d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 658d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 659d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public boolean dispatchTouchEvent(MotionEvent m) { 660d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraState == SWITCHING_CAMERA) return true; 661d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return false; 662d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 663d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 664d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 665d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 666d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onReceive(Context context, Intent intent) { 667d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String action = intent.getAction(); 668d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mIsImageCaptureIntent && action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) { 669d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getLastThumbnail(); 670d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 671d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 672d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb }; 673d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 674d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void initOnScreenIndicator() { 675d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mGpsIndicator = (ImageView) mRootView.findViewById(R.id.onscreen_gps_indicator); 676d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mExposureIndicator = (TextView) mRootView.findViewById(R.id.onscreen_exposure_indicator); 677d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFlashIndicator = (ImageView) mRootView.findViewById(R.id.onscreen_flash_indicator); 678d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSceneIndicator = (ImageView) mRootView.findViewById(R.id.onscreen_scene_indicator); 679d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mWhiteBalanceIndicator = 680d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb (ImageView) mRootView.findViewById(R.id.onscreen_white_balance_indicator); 681d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusIndicator = (ImageView) mRootView.findViewById(R.id.onscreen_focus_indicator); 682d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 683d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 684d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 685d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void showGpsOnScreenIndicator(boolean hasSignal) { 686d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mGpsIndicator == null) { 687d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 688d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 689d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (hasSignal) { 690d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mGpsIndicator.setImageResource(R.drawable.ic_viewfinder_gps_on); 691d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 692d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mGpsIndicator.setImageResource(R.drawable.ic_viewfinder_gps_no_signal); 693d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 694d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mGpsIndicator.setVisibility(View.VISIBLE); 695d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 696d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 697d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 698d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void hideGpsOnScreenIndicator() { 699d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mGpsIndicator == null) { 700d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 701d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 702d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mGpsIndicator.setVisibility(View.GONE); 703d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 704d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 705d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateExposureOnScreenIndicator(int value) { 706d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mExposureIndicator == null) { 707d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 708d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 709d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (value == 0) { 710d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mExposureIndicator.setText(""); 711d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mExposureIndicator.setVisibility(View.GONE); 712d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 713d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb float step = mParameters.getExposureCompensationStep(); 714d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFormatterArgs[0] = value * step; 715d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mBuilder.delete(0, mBuilder.length()); 716d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFormatter.format("%+1.1f", mFormatterArgs); 717d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String exposure = mFormatter.toString(); 718d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mExposureIndicator.setText(exposure); 719d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mExposureIndicator.setVisibility(View.VISIBLE); 720d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 721d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 722d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 723d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateFlashOnScreenIndicator(String value) { 724d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFlashIndicator == null) { 725d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 726d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 727d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (value == null || Parameters.FLASH_MODE_OFF.equals(value)) { 728d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFlashIndicator.setVisibility(View.GONE); 729d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 730d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFlashIndicator.setVisibility(View.VISIBLE); 731d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (Parameters.FLASH_MODE_AUTO.equals(value)) { 732d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFlashIndicator.setImageResource(R.drawable.ic_indicators_landscape_flash_auto); 733d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else if (Parameters.FLASH_MODE_ON.equals(value)) { 734d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFlashIndicator.setImageResource(R.drawable.ic_indicators_landscape_flash_on); 735d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 736d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Should not happen. 737d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFlashIndicator.setVisibility(View.GONE); 738d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 739d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 740d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 741d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 742d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateSceneOnScreenIndicator(String value) { 743d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mSceneIndicator == null) { 744d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 745d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 746d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb boolean isGone = (value == null) || (Parameters.SCENE_MODE_AUTO.equals(value)); 747d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSceneIndicator.setVisibility(isGone ? View.GONE : View.VISIBLE); 748d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 749d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 750d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateWhiteBalanceOnScreenIndicator(String value) { 751d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mWhiteBalanceIndicator == null) { 752d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 753d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 754d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (value == null || Parameters.WHITE_BALANCE_AUTO.equals(value)) { 755d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mWhiteBalanceIndicator.setVisibility(View.GONE); 756d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 757d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mWhiteBalanceIndicator.setVisibility(View.VISIBLE); 758d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (Parameters.WHITE_BALANCE_FLUORESCENT.equals(value)) { 759d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mWhiteBalanceIndicator.setImageResource(R.drawable.ic_indicators_fluorescent); 760d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else if (Parameters.WHITE_BALANCE_INCANDESCENT.equals(value)) { 761d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mWhiteBalanceIndicator.setImageResource(R.drawable.ic_indicators_incandescent); 762d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else if (Parameters.WHITE_BALANCE_DAYLIGHT.equals(value)) { 763d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mWhiteBalanceIndicator.setImageResource(R.drawable.ic_indicators_sunlight); 764d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else if (Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT.equals(value)) { 765d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mWhiteBalanceIndicator.setImageResource(R.drawable.ic_indicators_cloudy); 766d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 767d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Should not happen. 768d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mWhiteBalanceIndicator.setVisibility(View.GONE); 769d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 770d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 771d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 772d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 773d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateFocusOnScreenIndicator(String value) { 774d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFocusIndicator == null) { 775d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 776d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 777d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Do not show the indicator if users cannot choose. 778d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPreferenceGroup.findPreference(CameraSettings.KEY_FOCUS_MODE) == null) { 779d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusIndicator.setVisibility(View.GONE); 780d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 781d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusIndicator.setVisibility(View.VISIBLE); 782d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (Parameters.FOCUS_MODE_INFINITY.equals(value)) { 783d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusIndicator.setImageResource(R.drawable.ic_indicators_landscape); 784d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else if (Parameters.FOCUS_MODE_MACRO.equals(value)) { 785d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusIndicator.setImageResource(R.drawable.ic_indicators_macro); 786d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 787d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Should not happen. 788d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusIndicator.setVisibility(View.GONE); 789d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 790d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 791d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 792d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 793d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateOnScreenIndicators() { 794d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateSceneOnScreenIndicator(mParameters.getSceneMode()); 795d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateExposureOnScreenIndicator(CameraSettings.readExposure(mPreferences)); 796d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateFlashOnScreenIndicator(mParameters.getFlashMode()); 797d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateWhiteBalanceOnScreenIndicator(mParameters.getWhiteBalance()); 798d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateFocusOnScreenIndicator(mParameters.getFocusMode()); 799d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 800d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 801d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final class ShutterCallback 802d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb implements android.hardware.Camera.ShutterCallback { 803d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 804d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onShutter() { 805d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterCallbackTime = System.currentTimeMillis(); 806d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterLag = mShutterCallbackTime - mCaptureStartTime; 807d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "mShutterLag = " + mShutterLag + "ms"); 808d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 809d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 810d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 811d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final class PostViewPictureCallback implements PictureCallback { 812d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 813d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onPictureTaken( 814d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb byte [] data, android.hardware.Camera camera) { 815d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPostViewPictureCallbackTime = System.currentTimeMillis(); 816d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "mShutterToPostViewCallbackTime = " 817d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb + (mPostViewPictureCallbackTime - mShutterCallbackTime) 818d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb + "ms"); 819d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 820d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 821d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 822d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final class RawPictureCallback implements PictureCallback { 823d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 824d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onPictureTaken( 825d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb byte [] rawData, android.hardware.Camera camera) { 826d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mRawPictureCallbackTime = System.currentTimeMillis(); 827d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "mShutterToRawCallbackTime = " 828d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb + (mRawPictureCallbackTime - mShutterCallbackTime) + "ms"); 829d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 830d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 831d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 832d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final class JpegPictureCallback implements PictureCallback { 833d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Location mLocation; 834d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 835d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public JpegPictureCallback(Location loc) { 836d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mLocation = loc; 837d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 838d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 839d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 840d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onPictureTaken( 841d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb final byte [] jpegData, final android.hardware.Camera camera) { 842d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused) { 843d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 844d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 845d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 846d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mJpegPictureCallbackTime = System.currentTimeMillis(); 847d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If postview callback has arrived, the captured image is displayed 848d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // in postview callback. If not, the captured image is displayed in 849d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // raw picture callback. 850d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPostViewPictureCallbackTime != 0) { 851d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterToPictureDisplayedTime = 852d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPostViewPictureCallbackTime - mShutterCallbackTime; 853d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPictureDisplayedToJpegCallbackTime = 854d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mJpegPictureCallbackTime - mPostViewPictureCallbackTime; 855d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 856d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterToPictureDisplayedTime = 857d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mRawPictureCallbackTime - mShutterCallbackTime; 858d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPictureDisplayedToJpegCallbackTime = 859d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mJpegPictureCallbackTime - mRawPictureCallbackTime; 860d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 861d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "mPictureDisplayedToJpegCallbackTime = " 862d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb + mPictureDisplayedToJpegCallbackTime + "ms"); 863d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 864d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.updateFocusUI(); // Ensure focus indicator is hidden. 865d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mIsImageCaptureIntent) { 866d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (ApiHelper.CAN_START_PREVIEW_IN_JPEG_CALLBACK) { 867d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setupPreview(); 868d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 869d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Camera HAL of some devices have a bug. Starting preview 870d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // immediately after taking a picture will fail. Wait some 871d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // time before starting the preview. 872d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessageDelayed(SETUP_PREVIEW, 300); 873d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 874d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 875d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 876d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mIsImageCaptureIntent) { 877d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Calculate the width and the height of the jpeg. 878d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Size s = mParameters.getPictureSize(); 879d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int orientation = Exif.getOrientation(jpegData); 880d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int width, height; 881d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if ((mJpegRotation + orientation) % 180 == 0) { 882d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb width = s.width; 883d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb height = s.height; 884d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 885d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb width = s.height; 886d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb height = s.width; 887d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 888d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Uri uri = mImageNamer.getUri(); 889d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.addSecureAlbumItemIfNeeded(false, uri); 890d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String title = mImageNamer.getTitle(); 891d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageSaver.addImage(jpegData, uri, title, mLocation, 892d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb width, height, mActivity.mThumbnailViewWidth, orientation); 893d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 894d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mJpegImageData = jpegData; 895d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mQuickCapture) { 896d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb showPostCaptureAlert(); 897d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 898d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb doAttach(); 899d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 900d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 901d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 902d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Check this in advance of each shot so we don't add to shutter 903d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // latency. It's true that someone else could write to the SD card in 904d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // the mean time and fill it, but that could have happened between the 905d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // shutter press and saving the JPEG too. 906d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.updateStorageSpaceAndHint(); 907d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 908d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb long now = System.currentTimeMillis(); 909d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mJpegCallbackFinishTime = now - mJpegPictureCallbackTime; 910d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "mJpegCallbackFinishTime = " 911d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb + mJpegCallbackFinishTime + "ms"); 912d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mJpegPictureCallbackTime = 0; 913d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 914d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 915d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 916d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final class AutoFocusCallback 917d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb implements android.hardware.Camera.AutoFocusCallback { 918d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 919d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onAutoFocus( 920d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb boolean focused, android.hardware.Camera camera) { 921d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused) return; 922d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 923d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mAutoFocusTime = System.currentTimeMillis() - mFocusStartTime; 924d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "mAutoFocusTime = " + mAutoFocusTime + "ms"); 925d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraState(IDLE); 926d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.onAutoFocus(focused); 927d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 928d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 929d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 930d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) 931d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private final class AutoFocusMoveCallback 932d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb implements android.hardware.Camera.AutoFocusMoveCallback { 933d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 934d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onAutoFocusMoving( 935d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb boolean moving, android.hardware.Camera camera) { 936d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.onAutoFocusMoving(moving); 937d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 938d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 939d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 940d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Each SaveRequest remembers the data needed to save an image. 941d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static class SaveRequest { 942d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb byte[] data; 943d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Uri uri; 944d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String title; 945d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Location loc; 946d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int width, height; 947d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int thumbnailWidth; 948d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int orientation; 949d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 950d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 951d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We use a queue to store the SaveRequests that have not been completed 952d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // yet. The main thread puts the request into the queue. The saver thread 953d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // gets it from the queue, does the work, and removes it from the queue. 954d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // 955d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // The main thread needs to wait for the saver thread to finish all the work 956d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // in the queue, when the activity's onPause() is called, we need to finish 957d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // all the work, so other programs (like Gallery) can see all the images. 958d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // 959d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If the queue becomes too long, adding a new request will block the main 960d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // thread until the queue length drops below the threshold (QUEUE_LIMIT). 961d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If we don't do this, we may face several problems: (1) We may OOM 962d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // because we are holding all the jpeg data in memory. (2) We may ANR 963d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // when we need to wait for saver thread finishing all the work (in 964d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // onPause() or gotoGallery()) because the time to finishing a long queue 965d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // of work may be too long. 966d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private class ImageSaver extends Thread { 967d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static final int QUEUE_LIMIT = 3; 968d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 969d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ArrayList<SaveRequest> mQueue; 970d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Thumbnail mPendingThumbnail; 971d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Object mUpdateThumbnailLock = new Object(); 972d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mStop; 973d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 974d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in main thread 975d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public ImageSaver() { 976d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mQueue = new ArrayList<SaveRequest>(); 977d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb start(); 978d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 979d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 980d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in main thread 981d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void addImage(final byte[] data, Uri uri, String title, 982d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Location loc, int width, int height, int thumbnailWidth, 983d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int orientation) { 984d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb SaveRequest r = new SaveRequest(); 985d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb r.data = data; 986d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb r.uri = uri; 987d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb r.title = title; 988d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb r.loc = (loc == null) ? null : new Location(loc); // make a copy 989d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb r.width = width; 990d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb r.height = height; 991d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb r.thumbnailWidth = thumbnailWidth; 992d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb r.orientation = orientation; 993d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb synchronized (this) { 994d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb while (mQueue.size() >= QUEUE_LIMIT) { 995d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 996d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb wait(); 997d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (InterruptedException ex) { 998d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore. 999d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1000d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1001d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mQueue.add(r); 1002d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb notifyAll(); // Tell saver thread there is new work to do. 1003d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1004d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1005d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1006d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in saver thread 1007d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1008d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void run() { 1009d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb while (true) { 1010d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb SaveRequest r; 1011d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb synchronized (this) { 1012d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mQueue.isEmpty()) { 1013d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb notifyAll(); // notify main thread in waitDone 1014d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1015d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Note that we can only stop after we saved all images 1016d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // in the queue. 1017d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mStop) break; 1018d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1019d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 1020d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb wait(); 1021d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (InterruptedException ex) { 1022d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore. 1023d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1024d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb continue; 1025d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1026d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb r = mQueue.get(0); 1027d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1028d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb storeImage(r.data, r.uri, r.title, r.loc, r.width, r.height, 1029d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb r.thumbnailWidth, r.orientation); 1030d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb synchronized (this) { 1031d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mQueue.remove(0); 1032d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb notifyAll(); // the main thread may wait in addImage 1033d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1034d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1035d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1036d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1037d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in main thread 1038d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void waitDone() { 1039d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb synchronized (this) { 1040d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb while (!mQueue.isEmpty()) { 1041d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 1042d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb wait(); 1043d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (InterruptedException ex) { 1044d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore. 1045d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1046d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1047d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1048d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateThumbnail(); 1049d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1050d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1051d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in main thread 1052d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void finish() { 1053d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb waitDone(); 1054d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb synchronized (this) { 1055d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mStop = true; 1056d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb notifyAll(); 1057d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1058d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 1059d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb join(); 1060d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (InterruptedException ex) { 1061d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore. 1062d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1063d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1064d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1065d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in main thread (because we need to update mThumbnailView in the 1066d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // main thread) 1067d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void updateThumbnail() { 1068d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Thumbnail t; 1069d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb synchronized (mUpdateThumbnailLock) { 1070d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(UPDATE_THUMBNAIL); 1071d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb t = mPendingThumbnail; 1072d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPendingThumbnail = null; 1073d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1074d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1075d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (t != null) { 1076d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.mThumbnail = t; 1077d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mActivity.mThumbnailView != null) { 1078d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.mThumbnailView.setBitmap(mActivity.mThumbnail.getBitmap()); 1079d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1080d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1081d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1082d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1083d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in saver thread 1084d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void storeImage(final byte[] data, Uri uri, String title, 1085d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Location loc, int width, int height, int thumbnailWidth, 1086d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int orientation) { 1087d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb boolean ok = Storage.updateImage(mContentResolver, uri, title, loc, 1088d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb orientation, data, width, height); 1089d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (ok) { 1090d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb boolean needThumbnail; 1091d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb synchronized (this) { 1092d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If the number of requests in the queue (include the 1093d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // current one) is greater than 1, we don't need to generate 1094d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // thumbnail for this image. Because we'll soon replace it 1095d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // with the thumbnail for some image later in the queue. 1096d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb needThumbnail = (mQueue.size() <= 1); 1097d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1098d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (needThumbnail) { 1099d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Create a thumbnail whose width is equal or bigger than 1100d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // that of the thumbnail view. 1101d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int ratio = (int) Math.ceil((double) width / thumbnailWidth); 1102d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int inSampleSize = Integer.highestOneBit(ratio); 1103d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Thumbnail t = Thumbnail.createThumbnail( 1104d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb data, orientation, inSampleSize, uri); 1105d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb synchronized (mUpdateThumbnailLock) { 1106d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We need to update the thumbnail in the main thread, 1107d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // so send a message to run updateThumbnail(). 1108d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPendingThumbnail = t; 1109d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessage(UPDATE_THUMBNAIL); 1110d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1111d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1112d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.broadcastNewPicture(mActivity, uri); 1113d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1114d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1115d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1116d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1117d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private static class ImageNamer extends Thread { 1118d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mRequestPending; 1119d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private ContentResolver mResolver; 1120d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private long mDateTaken; 1121d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int mWidth, mHeight; 1122d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean mStop; 1123d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private Uri mUri; 1124d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private String mTitle; 1125d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1126d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in main thread 1127d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public ImageNamer() { 1128d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb start(); 1129d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1130d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1131d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in main thread 1132d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public synchronized void prepareUri(ContentResolver resolver, 1133d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb long dateTaken, int width, int height, int rotation) { 1134d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (rotation % 180 != 0) { 1135d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int tmp = width; 1136d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb width = height; 1137d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb height = tmp; 1138d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1139d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mRequestPending = true; 1140d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mResolver = resolver; 1141d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mDateTaken = dateTaken; 1142d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mWidth = width; 1143d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHeight = height; 1144d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb notifyAll(); 1145d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1146d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1147d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in main thread 1148d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public synchronized Uri getUri() { 1149d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // wait until the request is done. 1150d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb while (mRequestPending) { 1151d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 1152d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb wait(); 1153d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (InterruptedException ex) { 1154d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore. 1155d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1156d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1157d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1158d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // return the uri generated 1159d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Uri uri = mUri; 1160d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mUri = null; 1161d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return uri; 1162d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1163d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1164d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in main thread, should be called after getUri(). 1165d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public synchronized String getTitle() { 1166d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return mTitle; 1167d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1168d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1169d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in namer thread 1170d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1171d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public synchronized void run() { 1172d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb while (true) { 1173d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mStop) break; 1174d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mRequestPending) { 1175d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 1176d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb wait(); 1177d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (InterruptedException ex) { 1178d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore. 1179d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1180d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb continue; 1181d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1182d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb cleanOldUri(); 1183d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb generateUri(); 1184d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mRequestPending = false; 1185d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb notifyAll(); 1186d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1187d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb cleanOldUri(); 1188d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1189d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1190d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in main thread 1191d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public synchronized void finish() { 1192d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mStop = true; 1193d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb notifyAll(); 1194d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1195d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1196d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in namer thread 1197d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void generateUri() { 1198d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mTitle = Util.createJpegName(mDateTaken); 1199d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mUri = Storage.newImage(mResolver, mTitle, mDateTaken, mWidth, mHeight); 1200d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1201d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1202d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Runs in namer thread 1203d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void cleanOldUri() { 1204d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mUri == null) return; 1205d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Storage.deleteImage(mResolver, mUri); 1206d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mUri = null; 1207d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1208d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1209d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1210d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setCameraState(int state) { 1211d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraState = state; 1212d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb switch (state) { 1213d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case PREVIEW_STOPPED: 1214d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case SNAPSHOT_IN_PROGRESS: 1215d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case FOCUSING: 1216d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case SWITCHING_CAMERA: 1217b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb// enableCameraControls(false); 1218d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 1219d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case IDLE: 1220b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb// enableCameraControls(true); 1221d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 1222d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1223d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1224d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1225d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1226d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public boolean capture() { 1227d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If we are already in the middle of taking a snapshot then ignore. 1228d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraDevice == null || mCameraState == SNAPSHOT_IN_PROGRESS 1229d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb || mCameraState == SWITCHING_CAMERA) { 1230d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return false; 1231d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1232d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCaptureStartTime = System.currentTimeMillis(); 1233d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPostViewPictureCallbackTime = 0; 1234d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mJpegImageData = null; 1235d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1236d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set rotation and gps data. 1237d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mJpegRotation = Util.getJpegRotation(mCameraId, mOrientation); 1238d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setRotation(mJpegRotation); 1239d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Location loc = mLocationManager.getCurrentLocation(); 1240d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.setGpsParameters(mParameters, loc); 1241d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setParameters(mParameters); 1242d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1243d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback, 1244d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPostViewPictureCallback, new JpegPictureCallback(loc)); 1245d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1246d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Size size = mParameters.getPictureSize(); 1247d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageNamer.prepareUri(mContentResolver, mCaptureStartTime, 1248d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb size.width, size.height, mJpegRotation); 1249d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1250d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (ApiHelper.HAS_SURFACE_TEXTURE && !mIsImageCaptureIntent) { 1251d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Start capture animation. 1252b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb ((CameraScreenNail) mActivity.mCameraScreenNail).animateCapture(getCameraRotation()); 1253d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1254d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceDetectionStarted = false; 1255d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraState(SNAPSHOT_IN_PROGRESS); 1256d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return true; 1257d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1258d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1259d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int getCameraRotation() { 1260d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return (mOrientationCompensation - mDisplayRotation + 360) % 360; 1261d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1262d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1263d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1264d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void setFocusParameters() { 1265d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraParameters(UPDATE_PARAM_PREFERENCE); 1266d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1267d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1268d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1269d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void playSound(int soundId) { 1270d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSoundPlayer.play(soundId); 1271d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1272d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1273d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private int getPreferredCameraId(ComboPreferences preferences) { 1274d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int intentCameraId = Util.getCameraFacingIntentExtras(mActivity); 1275d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (intentCameraId != -1) { 1276d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Testing purpose. Launch a specific camera through the intent 1277d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // extras. 1278d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return intentCameraId; 1279d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1280d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return CameraSettings.readPreferredCameraId(preferences); 1281d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1282d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1283d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1284d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1285d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1286d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onFullScreenChanged(boolean full) { 1287d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (ApiHelper.HAS_SURFACE_TEXTURE) return; 1288d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1289d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (full) { 1290d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreviewSurfaceView.expand(); 1291d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1292d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreviewSurfaceView.shrink(); 1293d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1294d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1295d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1296d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1297d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 1298d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "surfaceChanged:" + holder + " width=" + width + ". height=" 1299d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb + height); 1300d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1301d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1302d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1303d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void surfaceCreated(SurfaceHolder holder) { 1304d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "surfaceCreated: " + holder); 1305d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraSurfaceHolder = holder; 1306d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Do not access the camera if camera start up thread is not finished. 1307d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraDevice == null || mCameraStartUpThread != null) return; 1308d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1309d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setPreviewDisplayAsync(holder); 1310d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // This happens when onConfigurationChanged arrives, surface has been 1311d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // destroyed, and there is no onFullScreenChanged. 1312d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraState == PREVIEW_STOPPED) { 1313d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setupPreview(); 1314d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1315d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1316d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1317d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1318d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void surfaceDestroyed(SurfaceHolder holder) { 1319d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "surfaceDestroyed: " + holder); 1320d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraSurfaceHolder = null; 1321d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb stopPreview(); 1322d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1323d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1324d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateSceneModeUI() { 1325d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If scene mode is set, we cannot set flash mode, white balance, and 1326d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // focus mode, instead, we read it from driver 1327d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) { 1328b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb// overrideCameraSettings(mParameters.getFlashMode(), 1329b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb// mParameters.getWhiteBalance(), mParameters.getFocusMode()); 1330d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1331b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb// overrideCameraSettings(null, null, null); 1332d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1333d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1334d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1335d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void loadCameraPreferences() { 1336d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings settings = new CameraSettings(mActivity, mInitialParams, 1337d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraId, CameraHolder.instance().getCameraInfo()); 1338d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreferenceGroup = settings.getPreferenceGroup(R.xml.camera_preferences); 1339d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1340d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1341d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1342d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public boolean collapseCameraControls() { 1343d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return false; 1344d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1345d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1346d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private class MyOrientationEventListener 1347d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb extends OrientationEventListener { 1348d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public MyOrientationEventListener(Context context) { 1349d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb super(context); 1350d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1351d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1352d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1353d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onOrientationChanged(int orientation) { 1354d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We keep the last known orientation. So if the user first orient 1355d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // the camera then point the camera to floor or sky, we still have 1356d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // the correct orientation. 1357d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (orientation == ORIENTATION_UNKNOWN) return; 1358d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mOrientation = Util.roundOrientation(orientation, mOrientation); 1359d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // When the screen is unlocked, display rotation may change. Always 1360d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // calculate the up-to-date orientationCompensation. 1361d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int orientationCompensation = 1362d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb (mOrientation + Util.getDisplayRotation(mActivity)) % 360; 1363d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mOrientationCompensation != orientationCompensation) { 1364d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mOrientationCompensation = orientationCompensation; 1365d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setOrientationIndicator(mOrientationCompensation, true); 1366d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1367d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1368d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Show the toast after getting the first orientation changed. 1369d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mHandler.hasMessages(SHOW_TAP_TO_FOCUS_TOAST)) { 1370d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(SHOW_TAP_TO_FOCUS_TOAST); 1371d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb showTapToFocusToast(); 1372d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1373d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1374d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1375d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1376d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setOrientationIndicator(int orientation, boolean animation) { 1377d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Rotatable[] indicators = { 1378b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb mRenderOverlay, mFaceView, 1379d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mReviewDoneButton, mRotateDialog, mOnScreenIndicators}; 1380d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb for (Rotatable indicator : indicators) { 1381d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (indicator != null) indicator.setOrientation(orientation, animation); 1382d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1383d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1384d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We change the orientation of the review cancel button only for tablet 1385d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // UI because there's a label along with the X icon. For phone UI, we 1386d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // don't change the orientation because there's only a symmetrical X 1387d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // icon. 1388d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mReviewCancelButton instanceof RotateLayout) { 1389d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mReviewCancelButton.setOrientation(orientation, animation); 1390d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1391d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1392d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1393d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1394d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onStop() { 1395d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mMediaProviderClient != null) { 1396d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mMediaProviderClient.release(); 1397d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mMediaProviderClient = null; 1398d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1399d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1400d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1401d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @OnClickAttr 1402d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onThumbnailClicked(View v) { 1403d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (isCameraIdle() && mActivity.mThumbnail != null) { 1404d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mImageSaver != null) mImageSaver.waitDone(); 1405d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.gotoGallery(); 1406d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1407d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1408d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1409d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // onClick handler for R.id.btn_retake 1410d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @OnClickAttr 1411d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onReviewRetakeClicked(View v) { 1412d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused) return; 1413d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1414d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb hidePostCaptureAlert(); 1415d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setupPreview(); 1416d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1417d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1418d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // onClick handler for R.id.btn_done 1419d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @OnClickAttr 1420d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onReviewDoneClicked(View v) { 1421d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb doAttach(); 1422d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1423d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1424d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // onClick handler for R.id.btn_cancel 1425d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @OnClickAttr 1426d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onReviewCancelClicked(View v) { 1427d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb doCancel(); 1428d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1429d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1430d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void doAttach() { 1431d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused) { 1432d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 1433d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1434d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1435d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb byte[] data = mJpegImageData; 1436d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1437d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCropValue == null) { 1438d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // First handle the no crop case -- just return the value. If the 1439d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // caller specifies a "save uri" then write the data to its 1440d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // stream. Otherwise, pass back a scaled down version of the bitmap 1441d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // directly in the extras. 1442d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mSaveUri != null) { 1443d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb OutputStream outputStream = null; 1444d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 1445d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb outputStream = mContentResolver.openOutputStream(mSaveUri); 1446d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb outputStream.write(data); 1447d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb outputStream.close(); 1448d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1449d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.setResultEx(Activity.RESULT_OK); 1450d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.finish(); 1451d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (IOException ex) { 1452d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore exception 1453d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } finally { 1454d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.closeSilently(outputStream); 1455d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1456d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1457d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int orientation = Exif.getOrientation(data); 1458d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Bitmap bitmap = Util.makeBitmap(data, 50 * 1024); 1459d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb bitmap = Util.rotate(bitmap, orientation); 1460d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.setResultEx(Activity.RESULT_OK, 1461d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb new Intent("inline-data").putExtra("data", bitmap)); 1462d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.finish(); 1463d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1464d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1465d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Save the image to a temp file and invoke the cropper 1466d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Uri tempUri = null; 1467d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb FileOutputStream tempStream = null; 1468d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 1469d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb File path = mActivity.getFileStreamPath(sTempCropFilename); 1470d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb path.delete(); 1471d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb tempStream = mActivity.openFileOutput(sTempCropFilename, 0); 1472d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb tempStream.write(data); 1473d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb tempStream.close(); 1474d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb tempUri = Uri.fromFile(path); 1475d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (FileNotFoundException ex) { 1476d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.setResultEx(Activity.RESULT_CANCELED); 1477d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.finish(); 1478d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 1479d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (IOException ex) { 1480d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.setResultEx(Activity.RESULT_CANCELED); 1481d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.finish(); 1482d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 1483d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } finally { 1484d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.closeSilently(tempStream); 1485d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1486d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1487d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Bundle newExtras = new Bundle(); 1488d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCropValue.equals("circle")) { 1489d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb newExtras.putString("circleCrop", "true"); 1490d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1491d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mSaveUri != null) { 1492d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, mSaveUri); 1493d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1494d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb newExtras.putBoolean("return-data", true); 1495d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1496d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1497d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Intent cropIntent = new Intent("com.android.camera.action.CROP"); 1498d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1499d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb cropIntent.setData(tempUri); 1500d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb cropIntent.putExtras(newExtras); 1501d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1502d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.startActivityForResult(cropIntent, REQUEST_CROP); 1503d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1504d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1505d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1506d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void doCancel() { 1507d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.setResultEx(Activity.RESULT_CANCELED, new Intent()); 1508d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.finish(); 1509d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1510d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1511d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1512d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onShutterButtonFocus(boolean pressed) { 1513d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused || collapseCameraControls() 1514d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb || (mCameraState == SNAPSHOT_IN_PROGRESS) 1515d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb || (mCameraState == PREVIEW_STOPPED)) return; 1516d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1517d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Do not do focus if there is not enough storage. 1518d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (pressed && !canTakePicture()) return; 1519d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1520d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (pressed) { 1521d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.onShutterDown(); 1522d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1523d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.onShutterUp(); 1524d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1525d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1526d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1527d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1528d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onShutterButtonClick() { 1529d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused || collapseCameraControls() 1530d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb || (mCameraState == SWITCHING_CAMERA) 1531d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb || (mCameraState == PREVIEW_STOPPED)) return; 1532d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1533d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Do not take the picture if there is not enough storage. 1534d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mActivity.getStorageSpace() <= Storage.LOW_STORAGE_THRESHOLD) { 1535d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.i(TAG, "Not enough space or storage not ready. remaining=" 1536d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb + mActivity.getStorageSpace()); 1537d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 1538d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1539d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "onShutterButtonClick: mCameraState=" + mCameraState); 1540d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1541d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If the user wants to do a snapshot while the previous one is still 1542d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // in progress, remember the fact and do it after we finish the previous 1543d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // one and re-start the preview. Snapshot in progress also includes the 1544d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // state that autofocus is focusing and a picture will be taken when 1545d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // focus callback arrives. 1546d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if ((mFocusManager.isFocusingSnapOnFinish() || mCameraState == SNAPSHOT_IN_PROGRESS) 1547d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb && !mIsImageCaptureIntent) { 1548d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSnapshotOnIdle = true; 1549d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 1550d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1551d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1552d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSnapshotOnIdle = false; 1553d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.doSnap(); 1554d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1555d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1556d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1557d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void installIntentFilter() { 1558d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // install an intent filter to receive SD card related events. 1559d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb IntentFilter intentFilter = 1560d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb new IntentFilter(Intent.ACTION_MEDIA_SCANNER_FINISHED); 1561d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb intentFilter.addDataScheme("file"); 1562d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.registerReceiver(mReceiver, intentFilter); 1563d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mDidRegister = true; 1564d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1565d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1566d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1567d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public boolean updateStorageHintOnResume() { 1568d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return mFirstTimeInitialized; 1569d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1570d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1571d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1572d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void updateCameraAppView() { 1573d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1574d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1575d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1576d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onResumeBeforeSuper() { 1577d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPaused = false; 1578d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1579d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1580d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1581d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onResumeAfterSuper() { 1582d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mOpenCameraFail || mCameraDisabled) return; 1583d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1584d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mJpegPictureCallbackTime = 0; 1585d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mZoomValue = 0; 1586d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1587d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Start the preview if it is not started. 1588d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraState == PREVIEW_STOPPED && mCameraStartUpThread == null) { 1589d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb resetExposureCompensation(); 1590d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraStartUpThread = new CameraStartUpThread(); 1591d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraStartUpThread.start(); 1592d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1593d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1594d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mIsImageCaptureIntent) mActivity.getLastThumbnail(); 1595d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1596d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If first time initialization is not finished, put it in the 1597d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // message queue. 1598d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mFirstTimeInitialized) { 1599d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessage(FIRST_TIME_INIT); 1600d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1601d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeSecondTime(); 1602d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1603d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb keepScreenOnAwhile(); 1604d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1605d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Dismiss open menu if exists. 1606d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb PopupManager.getInstance(mActivity).notifyShowPopup(null); 1607d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1608d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSoundPlayer = SoundClips.getPlayer(mActivity); 1609d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1610d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1611d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb void waitCameraStartUpThread() { 1612d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 1613d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraStartUpThread != null) { 1614d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraStartUpThread.cancel(); 1615d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraStartUpThread.join(); 1616d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraStartUpThread = null; 1617d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraState(IDLE); 1618d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1619d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (InterruptedException e) { 1620d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore 1621d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1622d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1623d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1624d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1625d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onPauseBeforeSuper() { 1626d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPaused = true; 1627d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1628d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1629d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1630d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onPauseAfterSuper() { 1631d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Wait the camera start up thread to finish. 1632d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb waitCameraStartUpThread(); 1633d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1634d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb stopPreview(); 1635d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Close the camera now because other activities may need to use it. 1636d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb closeCamera(); 1637d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mSurfaceTexture != null) { 1638b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb ((CameraScreenNail) mActivity.mCameraScreenNail).releaseSurfaceTexture(); 1639d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSurfaceTexture = null; 1640d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1641d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mSoundPlayer != null) { 1642d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSoundPlayer.release(); 1643d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSoundPlayer = null; 1644d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1645d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb resetScreenOn(); 1646d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1647d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Clear UI. 1648d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb collapseCameraControls(); 1649d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFaceView != null) mFaceView.clear(); 1650d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1651d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFirstTimeInitialized) { 1652d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mOrientationListener.disable(); 1653d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mImageSaver != null) { 1654d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageSaver.finish(); 1655d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageSaver = null; 1656d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageNamer.finish(); 1657d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mImageNamer = null; 1658d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1659d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1660d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1661d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mDidRegister) { 1662d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.unregisterReceiver(mReceiver); 1663d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mDidRegister = false; 1664d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1665d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mLocationManager != null) mLocationManager.recordLocation(false); 1666d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateExposureOnScreenIndicator(0); 1667d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1668d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If we are in an image capture intent and has taken 1669d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // a picture, we just clear it in onPause. 1670d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mJpegImageData = null; 1671d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1672d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Remove the messages in the event queue. 1673d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(SETUP_PREVIEW); 1674d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(FIRST_TIME_INIT); 1675d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(CHECK_DISPLAY_ROTATION); 1676d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(SWITCH_CAMERA); 1677d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(SWITCH_CAMERA_START_ANIMATION); 1678d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(CAMERA_OPEN_DONE); 1679d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(START_PREVIEW_DONE); 1680d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(OPEN_CAMERA_FAIL); 1681d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(CAMERA_DISABLED); 1682d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1683d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPendingSwitchCameraId = -1; 1684d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFocusManager != null) mFocusManager.removeMessages(); 1685d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1686d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1687d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void initializeControlByIntent() { 1688d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mIsImageCaptureIntent) { 1689d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Cannot use RotateImageView for "done" and "cancel" button because 1690d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // the tablet layout uses RotateLayout, which cannot be cast to 1691d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // RotateImageView. 1692d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mReviewDoneButton = (Rotatable) mRootView.findViewById(R.id.btn_done); 1693d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mReviewCancelButton = (Rotatable) mRootView.findViewById(R.id.btn_cancel); 1694d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mReviewRetakeButton = mRootView.findViewById(R.id.btn_retake); 1695d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mRootView.findViewById(R.id.btn_cancel).setVisibility(View.VISIBLE); 1696d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1697d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Not grayed out upon disabled, to make the follow-up fade-out 1698d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // effect look smooth. Note that the review done button in tablet 1699d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // layout is not a TwoStateImageView. 1700d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mReviewDoneButton instanceof TwoStateImageView) { 1701d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb ((TwoStateImageView) mReviewDoneButton).enableFilter(false); 1702d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1703d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1704d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setupCaptureParams(); 1705d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1706d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.mThumbnailView = ((RotateImageView) mRootView.findViewById(R.id.thumbnail)); 1707d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mActivity.mThumbnailView != null) { 1708d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.mThumbnailView.enableFilter(false); 1709d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.mThumbnailView.setVisibility(View.VISIBLE); 1710d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.mThumbnailViewWidth = mActivity.mThumbnailView.getLayoutParams().width; 1711d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1712d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mModePicker = (ModePicker) mRootView.findViewById(R.id.mode_picker); 1713d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mModePicker.setVisibility(View.VISIBLE); 1714b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb// mModePicker.setOnModeChangeListener(this); 1715d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mModePicker.setCurrentMode(ModePicker.MODE_CAMERA); 1716d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1717d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1718d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1719d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1720b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb /** 1721b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb * The focus manager is the first UI related element to get initialized, 1722b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb * and it requires the RenderOverlay, so initialize it here 1723b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb */ 1724d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void initializeFocusManager() { 1725d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Create FocusManager object. startPreview needs it. 1726b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay); 1727d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; 1728d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); 1729d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String[] defaultFocusModes = mActivity.getResources().getStringArray( 1730d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb R.array.pref_camera_focusmode_default_array); 1731b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb mFocusManager = new FocusOverlayManager(mPreferences, defaultFocusModes, 1732b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb mInitialParams, this, mirror, 1733d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getMainLooper()); 1734d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1735d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1736d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void initializeMiscControls() { 1737d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // startPreview needs this. 1738d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreviewFrameLayout = (PreviewFrameLayout) mRootView.findViewById(R.id.frame); 1739d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set touch focus listener. 1740d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.setSingleTapUpListener(mPreviewFrameLayout); 1741d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1742d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mOnScreenIndicators = (Rotatable) mRootView.findViewById(R.id.on_screen_indicators); 1743d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView = (FaceView) mRootView.findViewById(R.id.face_view); 1744d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreviewFrameLayout.setOnSizeChangedListener(this); 1745d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreviewFrameLayout.setOnLayoutChangeListener(mActivity); 1746d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!ApiHelper.HAS_SURFACE_TEXTURE) { 1747d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreviewSurfaceView = 1748d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb (PreviewSurfaceView) mRootView.findViewById(R.id.preview_surface_view); 1749d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreviewSurfaceView.setVisibility(View.VISIBLE); 1750d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreviewSurfaceView.getHolder().addCallback(this); 1751d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1752d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1753d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1754d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1755d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onConfigurationChanged(Configuration newConfig) { 1756d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "onConfigurationChanged"); 1757d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setDisplayOrientation(); 1758d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1759d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb ((ViewGroup) mRootView).removeAllViews(); 1760d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb LayoutInflater inflater = mActivity.getLayoutInflater(); 1761d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb inflater.inflate(R.layout.photo_module, (ViewGroup) mRootView); 1762d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1763d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // from onCreate() 1764d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeControlByIntent(); 1765d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFocusManager != null) mFocusManager.removeMessages(); 1766d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeFocusManager(); 1767d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeMiscControls(); 1768b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb loadCameraPreferences(); 1769b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb// initializeIndicatorControl(); 1770d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1771d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // from onResume() 1772d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mIsImageCaptureIntent) mActivity.updateThumbnailView(); 1773d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1774d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // from initializeFirstTime() 1775d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterButton = mActivity.getShutterButton(); 1776d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterButton.setOnShutterButtonListener(this); 1777d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterButton.setVisibility(View.VISIBLE); 1778d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeZoom(); 1779d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initOnScreenIndicator(); 1780d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateOnScreenIndicators(); 1781d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFaceView != null) { 1782d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.clear(); 1783d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.setVisibility(View.VISIBLE); 1784d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.setDisplayOrientation(mDisplayOrientation); 1785d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; 1786d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.setMirror(info.facing == CameraInfo.CAMERA_FACING_FRONT); 1787d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.resume(); 1788d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.setFaceView(mFaceView); 1789d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1790d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1791d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1792d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1793d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onActivityResult( 1794d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int requestCode, int resultCode, Intent data) { 1795d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb switch (requestCode) { 1796d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case REQUEST_CROP: { 1797d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Intent intent = new Intent(); 1798d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (data != null) { 1799d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Bundle extras = data.getExtras(); 1800d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (extras != null) { 1801d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb intent.putExtras(extras); 1802d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1803d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1804d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.setResultEx(resultCode, intent); 1805d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.finish(); 1806d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1807d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb File path = mActivity.getFileStreamPath(sTempCropFilename); 1808d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb path.delete(); 1809d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1810d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb break; 1811d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1812d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1813d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1814d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1815d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean canTakePicture() { 1816d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return isCameraIdle() && (mActivity.getStorageSpace() > Storage.LOW_STORAGE_THRESHOLD); 1817d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1818d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1819d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1820d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void autoFocus() { 1821d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusStartTime = System.currentTimeMillis(); 1822d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.autoFocus(mAutoFocusCallback); 1823d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraState(FOCUSING); 1824d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1825d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1826d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1827d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void cancelAutoFocus() { 1828d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.cancelAutoFocus(); 1829d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraState(IDLE); 1830d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraParameters(UPDATE_PARAM_PREFERENCE); 1831d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1832d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1833d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Preview area is touched. Handle touch focus. 1834d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1835d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onSingleTapUp(View view, int x, int y) { 1836d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused || mCameraDevice == null || !mFirstTimeInitialized 1837d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb || mCameraState == SNAPSHOT_IN_PROGRESS 1838d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb || mCameraState == SWITCHING_CAMERA 1839d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb || mCameraState == PREVIEW_STOPPED) { 1840d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 1841d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1842d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1843d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Do not trigger touch focus if popup window is opened. 1844d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (collapseCameraControls()) return; 1845d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1846d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Check if metering area or focus area is supported. 1847d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mFocusAreaSupported && !mMeteringAreaSupported) return; 1848d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1849d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.onSingleTapUp(x, y); 1850d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1851d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1852d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1853d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public boolean onBackPressed() { 1854d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!isCameraIdle()) { 1855d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore backs while we're taking a picture 1856d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return true; 1857d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1858d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return collapseCameraControls(); 1859d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1860d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1861d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1862d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1863d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public boolean onKeyDown(int keyCode, KeyEvent event) { 1864d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb switch (keyCode) { 1865d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case KeyEvent.KEYCODE_FOCUS: 1866d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFirstTimeInitialized && event.getRepeatCount() == 0) { 1867d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb onShutterButtonFocus(true); 1868d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1869d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return true; 1870d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case KeyEvent.KEYCODE_CAMERA: 1871d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFirstTimeInitialized && event.getRepeatCount() == 0) { 1872d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb onShutterButtonClick(); 1873d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1874d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return true; 1875d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case KeyEvent.KEYCODE_DPAD_CENTER: 1876d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If we get a dpad center event without any focused view, move 1877d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // the focus to the shutter button and press it. 1878d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFirstTimeInitialized && event.getRepeatCount() == 0) { 1879d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Start auto-focus immediately to reduce shutter lag. After 1880d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // the shutter button gets the focus, onShutterButtonFocus() 1881d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // will be called again but it is fine. 1882d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (collapseCameraControls()) return true; 1883d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb onShutterButtonFocus(true); 1884d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mShutterButton.isInTouchMode()) { 1885d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterButton.requestFocusFromTouch(); 1886d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1887d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterButton.requestFocus(); 1888d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1889d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mShutterButton.setPressed(true); 1890d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1891d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return true; 1892d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1893d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return false; 1894d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1895d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1896d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 1897d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public boolean onKeyUp(int keyCode, KeyEvent event) { 1898d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb switch (keyCode) { 1899d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb case KeyEvent.KEYCODE_FOCUS: 1900d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFirstTimeInitialized) { 1901d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb onShutterButtonFocus(false); 1902d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1903d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return true; 1904d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1905d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return false; 1906d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1907d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1908d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) 1909d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void closeCamera() { 1910d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraDevice != null) { 1911d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setZoomChangeListener(null); 1912d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if(ApiHelper.HAS_FACE_DETECTION) { 1913d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setFaceDetectionListener(null); 1914d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1915d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setErrorCallback(null); 1916d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraHolder.instance().release(); 1917d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceDetectionStarted = false; 1918d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice = null; 1919d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraState(PREVIEW_STOPPED); 1920d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.onCameraReleased(); 1921d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1922d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1923d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1924d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setDisplayOrientation() { 1925d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mDisplayRotation = Util.getDisplayRotation(mActivity); 1926d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mDisplayOrientation = Util.getDisplayOrientation(mDisplayRotation, mCameraId); 1927d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDisplayOrientation = Util.getDisplayOrientation(0, mCameraId); 1928d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFaceView != null) { 1929d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceView.setDisplayOrientation(mDisplayOrientation); 1930d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1931d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.setDisplayOrientation(mDisplayOrientation); 1932d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1933d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1934d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Only called by UI thread. 1935d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setupPreview() { 1936d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.resetTouchFocus(); 1937d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb startPreview(); 1938d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraState(IDLE); 1939d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb startFaceDetection(); 1940d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1941d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1942d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // This can be called by UI Thread or CameraStartUpThread. So this should 1943d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // not modify the views. 1944d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void startPreview() { 1945d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setErrorCallback(mErrorCallback); 1946d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1947d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If we're previewing already, stop the preview first (this will blank 1948d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // the screen). 1949d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraState != PREVIEW_STOPPED) stopPreview(); 1950d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1951d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setDisplayOrientation(); 1952d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1953d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mSnapshotOnIdle) { 1954d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If the focus mode is continuous autofocus, call cancelAutoFocus to 1955d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // resume it because it may have been paused by autoFocus call. 1956d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (Util.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode())) { 1957d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.cancelAutoFocus(); 1958d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1959d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.setAeAwbLock(false); // Unlock AE and AWB. 1960d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1961d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraParameters(UPDATE_PARAM_ALL); 1962d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1963d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (ApiHelper.HAS_SURFACE_TEXTURE) { 1964b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail; 1965d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mSurfaceTexture == null) { 1966d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Size size = mParameters.getPreviewSize(); 1967d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraDisplayOrientation % 180 == 0) { 1968d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb screenNail.setSize(size.width, size.height); 1969d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1970d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb screenNail.setSize(size.height, size.width); 1971d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1972d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.notifyScreenNailChanged(); 1973d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb screenNail.acquireSurfaceTexture(); 1974d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSurfaceTexture = screenNail.getSurfaceTexture(); 1975d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1976d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation); 1977d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setPreviewTextureAsync((SurfaceTexture) mSurfaceTexture); 1978d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 1979d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setDisplayOrientation(mDisplayOrientation); 1980d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setPreviewDisplayAsync(mCameraSurfaceHolder); 1981d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1982d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1983d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "startPreview"); 1984d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.startPreviewAsync(); 1985d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1986d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.onPreviewStarted(); 1987d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1988d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mSnapshotOnIdle) { 1989d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.post(mDoSnapRunnable); 1990d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1991d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 1992d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 1993d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void stopPreview() { 1994d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) { 1995d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "stopPreview"); 1996d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.cancelAutoFocus(); // Reset the focus. 1997d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.stopPreview(); 1998d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFaceDetectionStarted = false; 1999d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2000d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraState(PREVIEW_STOPPED); 2001d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFocusManager != null) mFocusManager.onPreviewStopped(); 2002d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2003d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2004d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @SuppressWarnings("deprecation") 2005d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateCameraParametersInitialize() { 2006d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Reset preview frame rate to the maximum because it may be lowered by 2007d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // video camera application. 2008d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb List<Integer> frameRates = mParameters.getSupportedPreviewFrameRates(); 2009d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (frameRates != null) { 2010d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Integer max = Collections.max(frameRates); 2011d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setPreviewFrameRate(max); 2012d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2013d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2014d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.set(Util.RECORDING_HINT, Util.FALSE); 2015d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2016d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Disable video stabilization. Convenience methods not available in API 2017d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // level <= 14 2018d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String vstabSupported = mParameters.get("video-stabilization-supported"); 2019d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if ("true".equals(vstabSupported)) { 2020d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.set("video-stabilization", "false"); 2021d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2022d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2023d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2024d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateCameraParametersZoom() { 2025d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set zoom. 2026d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mParameters.isZoomSupported()) { 2027d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setZoom(mZoomValue); 2028d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2029d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2030d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2031d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2032d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) 2033d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setAutoExposureLockIfSupported() { 2034d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mAeLockSupported) { 2035d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setAutoExposureLock(mFocusManager.getAeAwbLock()); 2036d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2037d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2038d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2039d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) 2040d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setAutoWhiteBalanceLockIfSupported() { 2041d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mAwbLockSupported) { 2042d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setAutoWhiteBalanceLock(mFocusManager.getAeAwbLock()); 2043d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2044d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2045d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2046d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) 2047d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setFocusAreasIfSupported() { 2048d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFocusAreaSupported) { 2049d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setFocusAreas(mFocusManager.getFocusAreas()); 2050d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2051d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2052d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2053d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) 2054d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setMeteringAreasIfSupported() { 2055d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mMeteringAreaSupported) { 2056d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Use the same area for focus and metering. 2057d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setMeteringAreas(mFocusManager.getMeteringAreas()); 2058d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2059d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2060d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2061d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateCameraParametersPreference() { 2062d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setAutoExposureLockIfSupported(); 2063d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setAutoWhiteBalanceLockIfSupported(); 2064d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setFocusAreasIfSupported(); 2065d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setMeteringAreasIfSupported(); 2066d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2067d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set picture size. 2068d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String pictureSize = mPreferences.getString( 2069d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings.KEY_PICTURE_SIZE, null); 2070d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (pictureSize == null) { 2071d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings.initialCameraPictureSize(mActivity, mParameters); 2072d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 2073d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb List<Size> supported = mParameters.getSupportedPictureSizes(); 2074d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings.setCameraPictureSize( 2075d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb pictureSize, supported, mParameters); 2076d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2077d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Size size = mParameters.getPictureSize(); 2078d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2079d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set a preview size that is closest to the viewfinder height and has 2080d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // the right aspect ratio. 2081d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb List<Size> sizes = mParameters.getSupportedPreviewSizes(); 2082d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Size optimalSize = Util.getOptimalPreviewSize(mActivity, sizes, 2083d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb (double) size.width / size.height); 2084d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Size original = mParameters.getPreviewSize(); 2085d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!original.equals(optimalSize)) { 2086d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setPreviewSize(optimalSize.width, optimalSize.height); 2087d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2088d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Zoom related settings will be changed for different preview 2089d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // sizes, so set and read the parameters to get latest values 2090d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setParameters(mParameters); 2091d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters = mCameraDevice.getParameters(); 2092d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2093d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "Preview size is " + optimalSize.width + "x" + optimalSize.height); 2094d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2095d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Since change scene mode may change supported values, 2096d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set scene mode first, 2097d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSceneMode = mPreferences.getString( 2098d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings.KEY_SCENE_MODE, 2099d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getString(R.string.pref_camera_scenemode_default)); 2100d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (Util.isSupported(mSceneMode, mParameters.getSupportedSceneModes())) { 2101d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mParameters.getSceneMode().equals(mSceneMode)) { 2102d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setSceneMode(mSceneMode); 2103d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2104d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Setting scene mode will change the settings of flash mode, 2105d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // white balance, and focus mode. Here we read back the 2106d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // parameters, so we can know those settings. 2107d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setParameters(mParameters); 2108d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters = mCameraDevice.getParameters(); 2109d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2110d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 2111d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSceneMode = mParameters.getSceneMode(); 2112d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mSceneMode == null) { 2113d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSceneMode = Parameters.SCENE_MODE_AUTO; 2114d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2115d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2116d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2117d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set JPEG quality. 2118d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int jpegQuality = CameraProfile.getJpegEncodingQualityParameter(mCameraId, 2119d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraProfile.QUALITY_HIGH); 2120d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setJpegQuality(jpegQuality); 2121d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2122d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // For the following settings, we need to check if the settings are 2123d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // still supported by latest driver, if not, ignore the settings. 2124d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2125d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set exposure compensation 2126d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int value = CameraSettings.readExposure(mPreferences); 2127d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int max = mParameters.getMaxExposureCompensation(); 2128d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb int min = mParameters.getMinExposureCompensation(); 2129d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (value >= min && value <= max) { 2130d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setExposureCompensation(value); 2131d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 2132d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.w(TAG, "invalid exposure range: " + value); 2133d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2134d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2135d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) { 2136d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set flash mode. 2137d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String flashMode = mPreferences.getString( 2138d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings.KEY_FLASH_MODE, 2139d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getString(R.string.pref_camera_flashmode_default)); 2140d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb List<String> supportedFlash = mParameters.getSupportedFlashModes(); 2141d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (Util.isSupported(flashMode, supportedFlash)) { 2142d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setFlashMode(flashMode); 2143d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 2144d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb flashMode = mParameters.getFlashMode(); 2145d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (flashMode == null) { 2146d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb flashMode = mActivity.getString( 2147d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb R.string.pref_camera_flashmode_no_flash); 2148d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2149d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2150d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2151d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set white balance parameter. 2152d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String whiteBalance = mPreferences.getString( 2153d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings.KEY_WHITE_BALANCE, 2154d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getString(R.string.pref_camera_whitebalance_default)); 2155d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (Util.isSupported(whiteBalance, 2156d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.getSupportedWhiteBalance())) { 2157d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setWhiteBalance(whiteBalance); 2158d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 2159d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb whiteBalance = mParameters.getWhiteBalance(); 2160d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (whiteBalance == null) { 2161d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb whiteBalance = Parameters.WHITE_BALANCE_AUTO; 2162d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2163d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2164d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2165d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set focus mode. 2166d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.overrideFocusMode(null); 2167d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mParameters.setFocusMode(mFocusManager.getFocusMode()); 2168d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 2169d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.overrideFocusMode(mParameters.getFocusMode()); 2170d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2171d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2172d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mContinousFocusSupported && ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK) { 2173d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateAutoFocusMoveCallback(); 2174d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2175d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2176d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2177d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) 2178d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void updateAutoFocusMoveCallback() { 2179d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mParameters.getFocusMode().equals(Util.FOCUS_MODE_CONTINUOUS_PICTURE)) { 2180d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setAutoFocusMoveCallback( 2181d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb (AutoFocusMoveCallback) mAutoFocusMoveCallback); 2182d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 2183d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setAutoFocusMoveCallback(null); 2184d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2185d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2186d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2187d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We separate the parameters into several subsets, so we can update only 2188d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // the subsets actually need updating. The PREFERENCE set needs extra 2189d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // locking because the preference can be changed from GLThread as well. 2190d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setCameraParameters(int updateSet) { 2191d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if ((updateSet & UPDATE_PARAM_INITIALIZE) != 0) { 2192d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateCameraParametersInitialize(); 2193d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2194d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2195d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if ((updateSet & UPDATE_PARAM_ZOOM) != 0) { 2196d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateCameraParametersZoom(); 2197d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2198d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2199d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if ((updateSet & UPDATE_PARAM_PREFERENCE) != 0) { 2200d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateCameraParametersPreference(); 2201d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2202d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2203d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraDevice.setParameters(mParameters); 2204d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2205d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2206d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // If the Camera is idle, update the parameters immediately, otherwise 2207d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // accumulate them in mUpdateSet and update later. 2208d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setCameraParametersWhenIdle(int additionalUpdateSet) { 2209d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mUpdateSet |= additionalUpdateSet; 2210d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mCameraDevice == null) { 2211d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We will update all the parameters when we open the device, so 2212d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // we don't need to do anything now. 2213d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mUpdateSet = 0; 2214d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return; 2215d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else if (isCameraIdle()) { 2216d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraParameters(mUpdateSet); 2217d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateSceneModeUI(); 2218d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mUpdateSet = 0; 2219d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 2220d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (!mHandler.hasMessages(SET_CAMERA_PARAMETERS_WHEN_IDLE)) { 2221d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessageDelayed( 2222d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb SET_CAMERA_PARAMETERS_WHEN_IDLE, 1000); 2223d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2224d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2225d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2226d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2227d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean isCameraIdle() { 2228d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return (mCameraState == IDLE) || 2229d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb ((mFocusManager != null) && mFocusManager.isFocusCompleted() 2230d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb && (mCameraState != SWITCHING_CAMERA)); 2231d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2232d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2233d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private boolean isImageCaptureIntent() { 2234d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String action = mActivity.getIntent().getAction(); 2235d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action)); 2236d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2237d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2238d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void setupCaptureParams() { 2239d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Bundle myExtras = mActivity.getIntent().getExtras(); 2240d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (myExtras != null) { 2241d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mSaveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT); 2242d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCropValue = myExtras.getString("crop"); 2243d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2244d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2245d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2246d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void showPostCaptureAlert() { 2247d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mIsImageCaptureIntent) { 2248d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.fadeOut(mShutterButton); 2249d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2250d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.fadeIn(mReviewRetakeButton); 2251d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.fadeIn((View) mReviewDoneButton); 2252d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2253d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2254d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2255d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void hidePostCaptureAlert() { 2256d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mIsImageCaptureIntent) { 2257d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.fadeOut(mReviewRetakeButton); 2258d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.fadeOut((View) mReviewDoneButton); 2259d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2260d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.fadeIn(mShutterButton); 2261d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2262d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2263d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2264d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 2265d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onSharedPreferenceChanged() { 2266d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore the events after "onPause()" 2267d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused) return; 2268d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2269d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb boolean recordLocation = RecordLocationPreference.get( 2270d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreferences, mContentResolver); 2271d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mLocationManager.recordLocation(recordLocation); 2272d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2273d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE); 2274d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setPreviewFrameLayoutAspectRatio(); 2275d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateOnScreenIndicators(); 2276d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2277d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2278d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 2279d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onCameraPickerClicked(int cameraId) { 2280d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused || mPendingSwitchCameraId != -1) return; 2281d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2282d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPendingSwitchCameraId = cameraId; 2283d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (ApiHelper.HAS_SURFACE_TEXTURE) { 2284d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "Start to copy texture. cameraId=" + cameraId); 2285d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // We need to keep a preview frame for the animation before 2286d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // releasing the camera. This will trigger onPreviewTextureCopied. 2287b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb ((CameraScreenNail) mActivity.mCameraScreenNail).copyTexture(); 2288d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Disable all camera controls. 2289d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraState(SWITCHING_CAMERA); 2290d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } else { 2291d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb switchCamera(); 2292d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2293d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2294d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2295d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void switchCamera() { 2296d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused) return; 2297d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2298d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Log.v(TAG, "Start to switch camera. id=" + mPendingSwitchCameraId); 2299d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mCameraId = mPendingSwitchCameraId; 2300d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPendingSwitchCameraId = -1; 2301b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb// mCameraPicker.setCameraId(mCameraId); 2302d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2303d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // from onPause 2304d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb closeCamera(); 2305d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb collapseCameraControls(); 2306d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFaceView != null) mFaceView.clear(); 2307d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFocusManager != null) mFocusManager.removeMessages(); 2308d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2309d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Restart the camera and initialize the UI. From onCreate. 2310d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreferences.setLocalId(mActivity, mCameraId); 2311d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); 2312d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraOpenThread cameraOpenThread = new CameraOpenThread(); 2313d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb cameraOpenThread.start(); 2314d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb try { 2315d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb cameraOpenThread.join(); 2316d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } catch (InterruptedException ex) { 2317d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // ignore 2318d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2319d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeCapabilities(); 2320d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; 2321d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); 2322d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.setMirror(mirror); 2323d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusManager.setParameters(mInitialParams); 2324d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setupPreview(); 2325b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb loadCameraPreferences(); 2326b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb// initializeIndicatorControl(); 2327d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2328d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // from onResume 2329d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setOrientationIndicator(mOrientationCompensation, false); 2330d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // from initializeFirstTime 2331d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb initializeZoom(); 2332d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb updateOnScreenIndicators(); 2333d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb showTapToFocusToastIfNeeded(); 2334d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2335d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (ApiHelper.HAS_SURFACE_TEXTURE) { 2336d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Start switch camera animation. Post a message because 2337d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // onFrameAvailable from the old camera may already exist. 2338d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessage(SWITCH_CAMERA_START_ANIMATION); 2339d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2340d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2341d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2342d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Preview texture has been copied. Now camera can be released and the 2343d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // animation can be started. 2344d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 2345d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onPreviewTextureCopied() { 2346d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessage(SWITCH_CAMERA); 2347d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2348d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2349d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 2350d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onUserInteraction() { 2351d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb keepScreenOnAwhile(); 2352d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2353d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2354d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void resetScreenOn() { 2355d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(CLEAR_SCREEN_DELAY); 2356d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 2357d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2358d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2359d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void keepScreenOnAwhile() { 2360d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.removeMessages(CLEAR_SCREEN_DELAY); 2361d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 2362d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY); 2363d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2364d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2365d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 2366d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onRestorePreferencesClicked() { 2367d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused) return; 2368d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Runnable runnable = new Runnable() { 2369d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 2370d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void run() { 2371d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb restorePreferences(); 2372d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2373d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb }; 2374d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mRotateDialog.showAlertDialog( 2375d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb null, 2376d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getString(R.string.confirm_restore_message), 2377d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getString(android.R.string.ok), runnable, 2378d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mActivity.getString(android.R.string.cancel), null); 2379d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2380d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2381d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void restorePreferences() { 2382d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Reset the zoom. Zoom value is not stored in preference. 2383d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mParameters.isZoomSupported()) { 2384d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mZoomValue = 0; 2385d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb setCameraParametersWhenIdle(UPDATE_PARAM_ZOOM); 2386b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb // TODO: reset zoom 2387d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2388b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb CameraSettings.restorePreferences(mActivity, mPreferences, 2389b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb mParameters); 2390b19c713286b7beed376ec6c4390e7272a80aa5b9Michael Kolb onSharedPreferenceChanged(); 2391d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2392d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2393d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 2394d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onOverriddenPreferencesClicked() { 2395d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mPaused) return; 2396d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mNotSelectableToast == null) { 2397d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb String str = mActivity.getResources().getString(R.string.not_selectable_in_scene_mode); 2398d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mNotSelectableToast = Toast.makeText(mActivity, str, Toast.LENGTH_SHORT); 2399d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2400d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mNotSelectableToast.show(); 2401d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2402d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2403d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void showTapToFocusToast() { 2404d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb new RotateTextToast(mActivity, R.string.tap_to_focus, mOrientationCompensation).show(); 2405d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Clear the preference. 2406d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Editor editor = mPreferences.edit(); 2407d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb editor.putBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, false); 2408d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb editor.apply(); 2409d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2410d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2411d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb private void initializeCapabilities() { 2412d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mInitialParams = mCameraDevice.getParameters(); 2413d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mFocusAreaSupported = Util.isFocusAreaSupported(mInitialParams); 2414d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mMeteringAreaSupported = Util.isMeteringAreaSupported(mInitialParams); 2415d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mAeLockSupported = Util.isAutoExposureLockSupported(mInitialParams); 2416d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mAwbLockSupported = Util.isAutoWhiteBalanceLockSupported(mInitialParams); 2417d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mContinousFocusSupported = mInitialParams.getSupportedFocusModes().contains( 2418d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Util.FOCUS_MODE_CONTINUOUS_PICTURE); 2419d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2420d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2421d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // PreviewFrameLayout size has changed. 2422d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb @Override 2423d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb public void onSizeChanged(int width, int height) { 2424d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb if (mFocusManager != null) mFocusManager.setPreviewSize(width, height); 2425d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2426d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2427d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb void setPreviewFrameLayoutAspectRatio() { 2428d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb // Set the preview frame aspect ratio according to the picture size. 2429d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb Size size = mParameters.getPictureSize(); 2430d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb mPreviewFrameLayout.setAspectRatio((double) size.width / size.height); 2431d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb } 2432d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb 2433d3a252bb71d119cbaeff55aeaa27dd1f8adadba2Michael Kolb} 2434