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