blob: da312941e082661b5d70ad07b4dc21bb7c9ac310 [file] [log] [blame]
Michael Kolb8872c232013-01-29 10:33:22 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera;
18
19import android.annotation.TargetApi;
20import android.app.Activity;
Michael Kolb8872c232013-01-29 10:33:22 -080021import android.content.ContentProviderClient;
22import android.content.ContentResolver;
Angus Kong0d00a892013-03-26 11:40:40 -070023import android.content.Context;
Michael Kolb8872c232013-01-29 10:33:22 -080024import android.content.Intent;
25import android.content.SharedPreferences.Editor;
26import android.content.res.Configuration;
27import android.graphics.Bitmap;
28import android.graphics.SurfaceTexture;
29import android.hardware.Camera.CameraInfo;
Michael Kolb8872c232013-01-29 10:33:22 -080030import android.hardware.Camera.Parameters;
Michael Kolb8872c232013-01-29 10:33:22 -080031import android.hardware.Camera.Size;
Angus Kong0d00a892013-03-26 11:40:40 -070032import android.hardware.Sensor;
33import android.hardware.SensorEvent;
34import android.hardware.SensorEventListener;
35import android.hardware.SensorManager;
Michael Kolb8872c232013-01-29 10:33:22 -080036import android.location.Location;
37import android.media.CameraProfile;
38import android.net.Uri;
Sascha Haeberling638e6f02013-09-18 14:28:51 -070039import android.os.Build;
Michael Kolb8872c232013-01-29 10:33:22 -080040import android.os.Bundle;
Michael Kolb8872c232013-01-29 10:33:22 -080041import android.os.Handler;
42import android.os.Looper;
43import android.os.Message;
44import android.os.MessageQueue;
45import android.os.SystemClock;
46import android.provider.MediaStore;
47import android.util.Log;
Michael Kolb8872c232013-01-29 10:33:22 -080048import android.view.KeyEvent;
Michael Kolb8872c232013-01-29 10:33:22 -080049import android.view.OrientationEventListener;
Michael Kolb8872c232013-01-29 10:33:22 -080050import android.view.View;
Michael Kolb8872c232013-01-29 10:33:22 -080051import android.view.WindowManager;
Alok Kediya0dc64ff2013-09-27 20:22:45 +053052import android.widget.Toast;
53import android.widget.ProgressBar;
54import android.widget.SeekBar;
55import android.widget.SeekBar.OnSeekBarChangeListener;
56import android.widget.LinearLayout;
57import android.widget.TextView;
Michael Kolb8872c232013-01-29 10:33:22 -080058
Angus Kong9ef99252013-07-18 18:04:19 -070059import com.android.camera.CameraManager.CameraAFCallback;
60import com.android.camera.CameraManager.CameraAFMoveCallback;
61import com.android.camera.CameraManager.CameraPictureCallback;
Michael Kolb8872c232013-01-29 10:33:22 -080062import com.android.camera.CameraManager.CameraProxy;
Angus Kong9ef99252013-07-18 18:04:19 -070063import com.android.camera.CameraManager.CameraShutterCallback;
Ruben Brunka9d66bd2013-09-06 11:56:32 -070064import com.android.camera.PhotoModule.NamedImages.NamedEntity;
ztenghuia16e7b52013-08-23 11:47:56 -070065import com.android.camera.exif.ExifInterface;
66import com.android.camera.exif.ExifTag;
67import com.android.camera.exif.Rational;
Michael Kolbd6954f32013-03-08 20:43:01 -080068import com.android.camera.ui.CountDownView.OnCountDownFinishedListener;
Ruben Brunk4601f5d2013-09-24 18:35:22 -070069import com.android.camera.ui.ModuleSwitcher;
Michael Kolb8872c232013-01-29 10:33:22 -080070import com.android.camera.ui.RotateTextToast;
Angus Kongdcccc512013-08-08 17:06:03 -070071import com.android.camera.util.ApiHelper;
Angus Kongb50b5cb2013-08-09 14:55:20 -070072import com.android.camera.util.CameraUtil;
Ruben Brunk4601f5d2013-09-24 18:35:22 -070073import com.android.camera.util.GcamHelper;
Sascha Haeberling8e963a52013-08-06 11:43:02 -070074import com.android.camera.util.UsageStatistics;
75import com.android.camera2.R;
Michael Kolb8872c232013-01-29 10:33:22 -080076
Angus Kongdcccc512013-08-08 17:06:03 -070077import java.io.File;
78import java.io.FileNotFoundException;
79import java.io.FileOutputStream;
80import java.io.IOException;
81import java.io.OutputStream;
Angus Kongdcccc512013-08-08 17:06:03 -070082import java.util.List;
Ruben Brunka9d66bd2013-09-06 11:56:32 -070083import java.util.Vector;
Alok Kediya0dc64ff2013-09-27 20:22:45 +053084import java.util.HashMap;
85import android.util.AttributeSet;
86import android.graphics.Canvas;
87import android.graphics.Color;
88import android.graphics.Paint;
89import android.os.SystemProperties;
90import java.util.Collections;
91import java.util.Formatter;
Angus Kongdcccc512013-08-08 17:06:03 -070092
Michael Kolb8872c232013-01-29 10:33:22 -080093public class PhotoModule
Dan Aminzade92ae10e2013-08-13 14:44:25 -070094 implements CameraModule,
95 PhotoController,
96 FocusOverlayManager.Listener,
97 CameraPreference.OnPreferenceChangedListener,
98 ShutterButton.OnShutterButtonListener,
99 MediaSaveService.Listener,
100 OnCountDownFinishedListener,
101 SensorEventListener {
Michael Kolb8872c232013-01-29 10:33:22 -0800102
103 private static final String TAG = "CAM_PhotoModule";
104
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530105 //QCom data members
106 public static boolean mBrightnessVisible = true;
107 private static final int MAX_SHARPNESS_LEVEL = 6;
108 private boolean mRestartPreview = false;
109 private int mSnapshotMode;
Alok Kediya28c31962013-09-28 16:43:35 +0530110 private int mBurstSnapNum = 1;
111 private int mReceivedSnapNum = 0;
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530112 public boolean mFaceDetectionEnabled = false;
113
114 /*Histogram variables*/
115 private GraphView mGraphView;
116 private static final int STATS_DATA = 257;
117 public static int statsdata[] = new int[STATS_DATA];
118 public boolean mHiston = false;
Michael Kolb8872c232013-01-29 10:33:22 -0800119 // We number the request code from 1000 to avoid collision with Gallery.
120 private static final int REQUEST_CROP = 1000;
121
122 private static final int SETUP_PREVIEW = 1;
123 private static final int FIRST_TIME_INIT = 2;
124 private static final int CLEAR_SCREEN_DELAY = 3;
125 private static final int SET_CAMERA_PARAMETERS_WHEN_IDLE = 4;
Angus Kongdcccc512013-08-08 17:06:03 -0700126 private static final int SHOW_TAP_TO_FOCUS_TOAST = 5;
127 private static final int SWITCH_CAMERA = 6;
128 private static final int SWITCH_CAMERA_START_ANIMATION = 7;
129 private static final int CAMERA_OPEN_DONE = 8;
130 private static final int OPEN_CAMERA_FAIL = 9;
131 private static final int CAMERA_DISABLED = 10;
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530132 private static final int SET_SKIN_TONE_FACTOR = 11;
Alok Kediya3c9da9a2013-10-03 15:12:43 +0530133 private static final int SET_PHOTO_UI_PARAMS = 12;
Santhosh Kumar H Ed7dfbf82013-10-25 14:32:17 +0530134 private static final int SWITCH_TO_GCAM_MODULE = 13;
135 private static final int CONFIGURE_SKIN_TONE_FACTOR = 14;
136
Michael Kolb8872c232013-01-29 10:33:22 -0800137 // The subset of parameters we need to update in setCameraParameters().
138 private static final int UPDATE_PARAM_INITIALIZE = 1;
139 private static final int UPDATE_PARAM_ZOOM = 2;
140 private static final int UPDATE_PARAM_PREFERENCE = 4;
141 private static final int UPDATE_PARAM_ALL = -1;
142
143 // This is the timeout to keep the camera in onPause for the first time
144 // after screen on if the activity is started from secure lock screen.
145 private static final int KEEP_CAMERA_TIMEOUT = 1000; // ms
146
Ruben Brunkd7488272013-10-10 18:45:53 -0700147 private static final String DEBUG_IMAGE_PREFIX = "DEBUG_";
148
Michael Kolb8872c232013-01-29 10:33:22 -0800149 // copied from Camera hierarchy
150 private CameraActivity mActivity;
Michael Kolb8872c232013-01-29 10:33:22 -0800151 private CameraProxy mCameraDevice;
152 private int mCameraId;
153 private Parameters mParameters;
154 private boolean mPaused;
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530155 private View mRootView;
Michael Kolbd6954f32013-03-08 20:43:01 -0800156
157 private PhotoUI mUI;
Michael Kolb8872c232013-01-29 10:33:22 -0800158
Michael Kolb8872c232013-01-29 10:33:22 -0800159 // The activity is going to switch to the specified camera id. This is
160 // needed because texture copy is done in GL thread. -1 means camera is not
161 // switching.
162 protected int mPendingSwitchCameraId = -1;
163 private boolean mOpenCameraFail;
164 private boolean mCameraDisabled;
165
166 // When setCameraParametersWhenIdle() is called, we accumulate the subsets
167 // needed to be updated in mUpdateSet.
168 private int mUpdateSet;
169
170 private static final int SCREEN_DELAY = 2 * 60 * 1000;
171
172 private int mZoomValue; // The current zoom value.
Michael Kolb8872c232013-01-29 10:33:22 -0800173
174 private Parameters mInitialParams;
175 private boolean mFocusAreaSupported;
176 private boolean mMeteringAreaSupported;
177 private boolean mAeLockSupported;
178 private boolean mAwbLockSupported;
Angus Kongdcccc512013-08-08 17:06:03 -0700179 private boolean mContinuousFocusSupported;
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530180 private boolean mTouchAfAecFlag;
Michael Kolb8872c232013-01-29 10:33:22 -0800181
182 // The degrees of the device rotated clockwise from its natural orientation.
183 private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
184 private ComboPreferences mPreferences;
185
186 private static final String sTempCropFilename = "crop-temp";
187
188 private ContentProviderClient mMediaProviderClient;
Michael Kolb8872c232013-01-29 10:33:22 -0800189 private boolean mFaceDetectionStarted = false;
190
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530191 private static final int MINIMUM_BRIGHTNESS = 0;
192 private static final int MAXIMUM_BRIGHTNESS = 6;
193 private int mbrightness = 3;
194 private int mbrightness_step = 1;
195 private ProgressBar brightnessProgressBar;
196 // Constant from android.hardware.Camera.Parameters
197 private static final String KEY_PICTURE_FORMAT = "picture-format";
198 private static final String KEY_QC_RAW_PICUTRE_SIZE = "raw-size";
Alok Kediyad8887ed2013-09-28 17:12:35 +0530199 public static final String PIXEL_FORMAT_JPEG = "jpeg";
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530200
201 private static final int MIN_SCE_FACTOR = -10;
202 private static final int MAX_SCE_FACTOR = +10;
203 private int SCE_FACTOR_STEP = 10;
204 private int mskinToneValue = 0;
205 private boolean mSkinToneSeekBar= false;
206 private boolean mSeekBarInitialized = false;
207 private SeekBar skinToneSeekBar;
208 private TextView LeftValue;
209 private TextView RightValue;
210 private TextView Title;
211
Michael Kolb8872c232013-01-29 10:33:22 -0800212 // mCropValue and mSaveUri are used only if isImageCaptureIntent() is true.
213 private String mCropValue;
214 private Uri mSaveUri;
215
Ruben Brunkd217ed02013-10-08 23:31:13 -0700216 private Uri mDebugUri;
217
Angus Kongce5480e2013-01-29 17:43:48 -0800218 // We use a queue to generated names of the images to be used later
219 // when the image is ready to be saved.
Michael Kolb8872c232013-01-29 10:33:22 -0800220 private NamedImages mNamedImages;
221
222 private Runnable mDoSnapRunnable = new Runnable() {
223 @Override
224 public void run() {
225 onShutterButtonClick();
226 }
227 };
228
Michael Kolb8872c232013-01-29 10:33:22 -0800229 /**
230 * An unpublished intent flag requesting to return as soon as capturing
231 * is completed.
232 *
233 * TODO: consider publishing by moving into MediaStore.
234 */
235 private static final String EXTRA_QUICK_CAPTURE =
236 "android.intent.extra.quickCapture";
237
238 // The display rotation in degrees. This is only valid when mCameraState is
239 // not PREVIEW_STOPPED.
240 private int mDisplayRotation;
241 // The value for android.hardware.Camera.setDisplayOrientation.
242 private int mCameraDisplayOrientation;
243 // The value for UI components like indicators.
244 private int mDisplayOrientation;
245 // The value for android.hardware.Camera.Parameters.setRotation.
246 private int mJpegRotation;
Doris Liu29da2db2013-08-28 14:28:45 -0700247 // Indicates whether we are using front camera
248 private boolean mMirror;
Michael Kolb8872c232013-01-29 10:33:22 -0800249 private boolean mFirstTimeInitialized;
250 private boolean mIsImageCaptureIntent;
251
Michael Kolb8872c232013-01-29 10:33:22 -0800252 private int mCameraState = PREVIEW_STOPPED;
253 private boolean mSnapshotOnIdle = false;
254
255 private ContentResolver mContentResolver;
256
257 private LocationManager mLocationManager;
258
Michael Kolb8872c232013-01-29 10:33:22 -0800259 private final PostViewPictureCallback mPostViewPictureCallback =
260 new PostViewPictureCallback();
261 private final RawPictureCallback mRawPictureCallback =
262 new RawPictureCallback();
263 private final AutoFocusCallback mAutoFocusCallback =
264 new AutoFocusCallback();
265 private final Object mAutoFocusMoveCallback =
266 ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK
Dan Aminzade92ae10e2013-08-13 14:44:25 -0700267 ? new AutoFocusMoveCallback()
268 : null;
Michael Kolb8872c232013-01-29 10:33:22 -0800269
270 private final CameraErrorCallback mErrorCallback = new CameraErrorCallback();
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530271 private final StatsCallback mStatsCallback = new StatsCallback();
Michael Kolb8872c232013-01-29 10:33:22 -0800272
273 private long mFocusStartTime;
274 private long mShutterCallbackTime;
275 private long mPostViewPictureCallbackTime;
276 private long mRawPictureCallbackTime;
277 private long mJpegPictureCallbackTime;
278 private long mOnResumeTime;
279 private byte[] mJpegImageData;
280
281 // These latency time are for the CameraLatency test.
282 public long mAutoFocusTime;
283 public long mShutterLag;
284 public long mShutterToPictureDisplayedTime;
285 public long mPictureDisplayedToJpegCallbackTime;
286 public long mJpegCallbackFinishTime;
287 public long mCaptureStartTime;
288
289 // This handles everything about focus.
290 private FocusOverlayManager mFocusManager;
291
Michael Kolb8872c232013-01-29 10:33:22 -0800292 private String mSceneMode;
Alok Kediya5fdf67e2013-10-02 18:00:14 +0530293 private String mCurrTouchAfAec = Parameters.TOUCH_AF_AEC_ON;
Michael Kolb8872c232013-01-29 10:33:22 -0800294
295 private final Handler mHandler = new MainHandler();
296 private PreferenceGroup mPreferenceGroup;
297
298 private boolean mQuickCapture;
Angus Kong0d00a892013-03-26 11:40:40 -0700299 private SensorManager mSensorManager;
300 private float[] mGData = new float[3];
301 private float[] mMData = new float[3];
302 private float[] mR = new float[16];
303 private int mHeading = -1;
304
Angus Kongdcccc512013-08-08 17:06:03 -0700305 // True if all the parameters needed to start preview is ready.
306 private boolean mCameraPreviewParamsReady = false;
Doris Liu6432cd62013-06-13 17:20:31 -0700307
Angus Kongce5480e2013-01-29 17:43:48 -0800308 private MediaSaveService.OnMediaSavedListener mOnMediaSavedListener =
309 new MediaSaveService.OnMediaSavedListener() {
310 @Override
311 public void onMediaSaved(Uri uri) {
312 if (uri != null) {
Doris Liu6432cd62013-06-13 17:20:31 -0700313 mActivity.notifyNewMedia(uri);
Angus Kongce5480e2013-01-29 17:43:48 -0800314 }
315 }
316 };
Michael Kolb8872c232013-01-29 10:33:22 -0800317
Angus Kongdcccc512013-08-08 17:06:03 -0700318 private void checkDisplayRotation() {
319 // Set the display orientation if display rotation has changed.
320 // Sometimes this happens when the device is held upside
321 // down and camera app is opened. Rotation animation will
322 // take some time and the rotation value we have got may be
323 // wrong. Framework does not have a callback for this now.
324 if (CameraUtil.getDisplayRotation(mActivity) != mDisplayRotation) {
325 setDisplayOrientation();
Michael Kolb8872c232013-01-29 10:33:22 -0800326 }
Angus Kongdcccc512013-08-08 17:06:03 -0700327 if (SystemClock.uptimeMillis() - mOnResumeTime < 5000) {
328 mHandler.postDelayed(new Runnable() {
329 @Override
330 public void run() {
331 checkDisplayRotation();
332 }
333 }, 100);
Michael Kolb8872c232013-01-29 10:33:22 -0800334 }
335 }
336
337 /**
338 * This Handler is used to post message back onto the main thread of the
339 * application
340 */
341 private class MainHandler extends Handler {
342 @Override
343 public void handleMessage(Message msg) {
344 switch (msg.what) {
345 case SETUP_PREVIEW: {
346 setupPreview();
347 break;
348 }
349
350 case CLEAR_SCREEN_DELAY: {
351 mActivity.getWindow().clearFlags(
352 WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
353 break;
354 }
355
356 case FIRST_TIME_INIT: {
357 initializeFirstTime();
358 break;
359 }
360
361 case SET_CAMERA_PARAMETERS_WHEN_IDLE: {
362 setCameraParametersWhenIdle(0);
363 break;
364 }
365
Michael Kolb8872c232013-01-29 10:33:22 -0800366 case SHOW_TAP_TO_FOCUS_TOAST: {
367 showTapToFocusToast();
368 break;
369 }
370
371 case SWITCH_CAMERA: {
372 switchCamera();
373 break;
374 }
375
376 case SWITCH_CAMERA_START_ANIMATION: {
Dan Aminzade92ae10e2013-08-13 14:44:25 -0700377 // TODO: Need to revisit
378 // ((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera();
Michael Kolb8872c232013-01-29 10:33:22 -0800379 break;
380 }
381
382 case CAMERA_OPEN_DONE: {
Michael Kolbd6954f32013-03-08 20:43:01 -0800383 onCameraOpened();
Michael Kolb8872c232013-01-29 10:33:22 -0800384 break;
385 }
386
Michael Kolb8872c232013-01-29 10:33:22 -0800387 case OPEN_CAMERA_FAIL: {
Michael Kolb8872c232013-01-29 10:33:22 -0800388 mOpenCameraFail = true;
Angus Kongb50b5cb2013-08-09 14:55:20 -0700389 CameraUtil.showErrorAndFinish(mActivity,
Michael Kolb8872c232013-01-29 10:33:22 -0800390 R.string.cannot_connect_camera);
391 break;
392 }
393
394 case CAMERA_DISABLED: {
Michael Kolb8872c232013-01-29 10:33:22 -0800395 mCameraDisabled = true;
Angus Kongb50b5cb2013-08-09 14:55:20 -0700396 CameraUtil.showErrorAndFinish(mActivity,
Michael Kolb8872c232013-01-29 10:33:22 -0800397 R.string.camera_disabled);
398 break;
399 }
Santhosh Kumar H Ed7dfbf82013-10-25 14:32:17 +0530400
401 case SWITCH_TO_GCAM_MODULE: {
402 mActivity.onModuleSelected(ModuleSwitcher.GCAM_MODULE_INDEX);
403 }
404
405 case CONFIGURE_SKIN_TONE_FACTOR: {
406 if (isCameraIdle()) {
407 mParameters = mCameraDevice.getParameters();
408 mParameters.set("skinToneEnhancement", String.valueOf(msg.arg1));
409 mCameraDevice.setParameters(mParameters);
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530410 }
411 break;
Santhosh Kumar H Ed7dfbf82013-10-25 14:32:17 +0530412 }
Michael Kolb8872c232013-01-29 10:33:22 -0800413 }
414 }
415 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530416 private BroadcastReceiver mReceiver = null;
417 private class ShutterBroadcastReceiver extends BroadcastReceiver {
418 @Override
419 public void onReceive(Context context, Intent intent) {
420 String action = intent.getAction();
421 if (action.equals(CameraUtil.ACTION_CAMERA_SHUTTER_CLICK)) {
422 onShutterButtonFocus(true);
423 onShutterButtonClick();
424 }
425 }
426 }
Michael Kolb8872c232013-01-29 10:33:22 -0800427 @Override
Doris Liu6432cd62013-06-13 17:20:31 -0700428 public void init(CameraActivity activity, View parent) {
Michael Kolb8872c232013-01-29 10:33:22 -0800429 mActivity = activity;
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530430 mRootView = parent;
Michael Kolbd6954f32013-03-08 20:43:01 -0800431 mUI = new PhotoUI(activity, this, parent);
Michael Kolb8872c232013-01-29 10:33:22 -0800432 mPreferences = new ComboPreferences(mActivity);
433 CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal());
434 mCameraId = getPreferredCameraId(mPreferences);
435
436 mContentResolver = mActivity.getContentResolver();
437
Michael Kolb8872c232013-01-29 10:33:22 -0800438 // Surface texture is from camera screen nail and startPreview needs it.
439 // This must be done before startPreview.
440 mIsImageCaptureIntent = isImageCaptureIntent();
Michael Kolb8872c232013-01-29 10:33:22 -0800441
442 mPreferences.setLocalId(mActivity, mCameraId);
443 CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
444 // we need to reset exposure for the preview
445 resetExposureCompensation();
Michael Kolb8872c232013-01-29 10:33:22 -0800446
447 initializeControlByIntent();
448 mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false);
Michael Kolbd6954f32013-03-08 20:43:01 -0800449 mLocationManager = new LocationManager(mActivity, mUI);
Angus Kong0d00a892013-03-26 11:40:40 -0700450 mSensorManager = (SensorManager)(mActivity.getSystemService(Context.SENSOR_SERVICE));
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530451
452 brightnessProgressBar = (ProgressBar)mRootView.findViewById(R.id.progress);
453 if (brightnessProgressBar instanceof SeekBar) {
454 SeekBar seeker = (SeekBar) brightnessProgressBar;
455 seeker.setOnSeekBarChangeListener(mSeekListener);
456 }
457 brightnessProgressBar.setMax(MAXIMUM_BRIGHTNESS);
458 brightnessProgressBar.setProgress(mbrightness);
459 skinToneSeekBar = (SeekBar) mRootView.findViewById(R.id.skintoneseek);
460 skinToneSeekBar.setOnSeekBarChangeListener(mskinToneSeekListener);
461 skinToneSeekBar.setVisibility(View.INVISIBLE);
462 Title = (TextView)mRootView.findViewById(R.id.skintonetitle);
463 RightValue = (TextView)mRootView.findViewById(R.id.skintoneright);
464 LeftValue = (TextView)mRootView.findViewById(R.id.skintoneleft);
465
Michael Kolbd6954f32013-03-08 20:43:01 -0800466 }
467
468 private void initializeControlByIntent() {
469 mUI.initializeControlByIntent();
470 if (mIsImageCaptureIntent) {
471 setupCaptureParams();
472 }
473 }
474
475 private void onPreviewStarted() {
Michael Kolbd6954f32013-03-08 20:43:01 -0800476 setCameraState(IDLE);
Michael Kolbd6954f32013-03-08 20:43:01 -0800477 startFaceDetection();
478 locationFirstRun();
Michael Kolb8872c232013-01-29 10:33:22 -0800479 }
480
481 // Prompt the user to pick to record location for the very first run of
482 // camera only
483 private void locationFirstRun() {
484 if (RecordLocationPreference.isSet(mPreferences)) {
485 return;
486 }
487 if (mActivity.isSecureCamera()) return;
488 // Check if the back camera exists
489 int backCameraId = CameraHolder.instance().getBackCameraId();
490 if (backCameraId == -1) {
491 // If there is no back camera, do not show the prompt.
492 return;
493 }
Doris Liu6a83d522013-07-02 12:03:32 -0700494 mUI.showLocationDialog();
495 }
Michael Kolb8872c232013-01-29 10:33:22 -0800496
ztenghui7b265a62013-09-09 14:58:44 -0700497 @Override
Doris Liu6a83d522013-07-02 12:03:32 -0700498 public void enableRecordingLocation(boolean enable) {
499 setLocationPreference(enable ? RecordLocationPreference.VALUE_ON
500 : RecordLocationPreference.VALUE_OFF);
Michael Kolb8872c232013-01-29 10:33:22 -0800501 }
502
Angus Kongdcccc512013-08-08 17:06:03 -0700503 @Override
504 public void onPreviewUIReady() {
505 startPreview();
506 }
507
508 @Override
509 public void onPreviewUIDestroyed() {
510 if (mCameraDevice == null) {
511 return;
512 }
513 mCameraDevice.setPreviewTexture(null);
514 stopPreview();
515 }
516
Michael Kolb8872c232013-01-29 10:33:22 -0800517 private void setLocationPreference(String value) {
518 mPreferences.edit()
Dan Aminzade92ae10e2013-08-13 14:44:25 -0700519 .putString(CameraSettings.KEY_RECORD_LOCATION, value)
520 .apply();
Michael Kolb8872c232013-01-29 10:33:22 -0800521 // TODO: Fix this to use the actual onSharedPreferencesChanged listener
522 // instead of invoking manually
523 onSharedPreferenceChanged();
524 }
525
Michael Kolbd6954f32013-03-08 20:43:01 -0800526 private void onCameraOpened() {
527 View root = mUI.getRootView();
Michael Kolb8872c232013-01-29 10:33:22 -0800528 // These depend on camera parameters.
Michael Kolbd6954f32013-03-08 20:43:01 -0800529
530 int width = root.getWidth();
531 int height = root.getHeight();
Doris Liu6a0de792013-02-26 10:54:25 -0800532 mFocusManager.setPreviewSize(width, height);
Michael Kolbd6954f32013-03-08 20:43:01 -0800533 openCameraCommon();
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530534 resizeForPreviewAspectRatio();
Michael Kolb8872c232013-01-29 10:33:22 -0800535 }
536
Michael Kolbd6954f32013-03-08 20:43:01 -0800537 private void switchCamera() {
538 if (mPaused) return;
539
540 Log.v(TAG, "Start to switch camera. id=" + mPendingSwitchCameraId);
541 mCameraId = mPendingSwitchCameraId;
542 mPendingSwitchCameraId = -1;
543 setCameraId(mCameraId);
544
545 // from onPause
546 closeCamera();
547 mUI.collapseCameraControls();
548 mUI.clearFaces();
SanthoshHEee63d7f2013-09-05 14:43:35 +0530549 disableSkinToneSeekBar();
Michael Kolbd6954f32013-03-08 20:43:01 -0800550 if (mFocusManager != null) mFocusManager.removeMessages();
551
552 // Restart the camera and initialize the UI. From onCreate.
553 mPreferences.setLocalId(mActivity, mCameraId);
554 CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
Angus Kong4f795b82013-09-16 14:25:35 -0700555 mCameraDevice = CameraUtil.openCamera(
556 mActivity, mCameraId, mHandler,
557 mActivity.getCameraOpenErrorCallback());
558 if (mCameraDevice == null) {
559 Log.e(TAG, "Failed to open camera:" + mCameraId + ", aborting.");
Michael Kolbd6954f32013-03-08 20:43:01 -0800560 return;
Doris Liu09106a42013-03-05 09:54:25 -0800561 }
Angus Kong4f795b82013-09-16 14:25:35 -0700562 mParameters = mCameraDevice.getParameters();
Michael Kolbd6954f32013-03-08 20:43:01 -0800563 initializeCapabilities();
564 CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
Doris Liu29da2db2013-08-28 14:28:45 -0700565 mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
566 mFocusManager.setMirror(mMirror);
Michael Kolbd6954f32013-03-08 20:43:01 -0800567 mFocusManager.setParameters(mInitialParams);
568 setupPreview();
569
Doris Liu6432cd62013-06-13 17:20:31 -0700570 // reset zoom value index
571 mZoomValue = 0;
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530572 resizeForPreviewAspectRatio();
Michael Kolbd6954f32013-03-08 20:43:01 -0800573 openCameraCommon();
574
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700575 // Start switch camera animation. Post a message because
576 // onFrameAvailable from the old camera may already exist.
577 mHandler.sendEmptyMessage(SWITCH_CAMERA_START_ANIMATION);
Doris Liu48239f42013-03-04 22:19:10 -0800578 }
579
Michael Kolbd6954f32013-03-08 20:43:01 -0800580 protected void setCameraId(int cameraId) {
581 ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CAMERA_ID);
582 pref.setValue("" + cameraId);
583 }
584
585 // either open a new camera or switch cameras
586 private void openCameraCommon() {
Michael Kolb8872c232013-01-29 10:33:22 -0800587 loadCameraPreferences();
Michael Kolbd6954f32013-03-08 20:43:01 -0800588
589 mUI.onCameraOpened(mPreferenceGroup, mPreferences, mParameters, this);
Angus Kong0fb819b2013-10-08 13:44:19 -0700590 if (mIsImageCaptureIntent) {
591 mUI.overrideSettings(CameraSettings.KEY_CAMERA_HDR_PLUS,
592 mActivity.getString(R.string.setting_off_value));
593 }
Michael Kolbd6954f32013-03-08 20:43:01 -0800594 updateSceneMode();
Alok Kediya427798d2013-09-28 17:42:32 +0530595 updateHdrMode();
Michael Kolbd6954f32013-03-08 20:43:01 -0800596 showTapToFocusToastIfNeeded();
597
598
Michael Kolb8872c232013-01-29 10:33:22 -0800599 }
600
ztenghui7b265a62013-09-09 14:58:44 -0700601 @Override
Doris Liub3749f22013-09-25 12:22:08 -0700602 public void onScreenSizeChanged(int width, int height) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800603 if (mFocusManager != null) mFocusManager.setPreviewSize(width, height);
Michael Kolbd6954f32013-03-08 20:43:01 -0800604 }
Michael Kolb8872c232013-01-29 10:33:22 -0800605
606 private void resetExposureCompensation() {
607 String value = mPreferences.getString(CameraSettings.KEY_EXPOSURE,
608 CameraSettings.EXPOSURE_DEFAULT_VALUE);
609 if (!CameraSettings.EXPOSURE_DEFAULT_VALUE.equals(value)) {
610 Editor editor = mPreferences.edit();
611 editor.putString(CameraSettings.KEY_EXPOSURE, "0");
612 editor.apply();
613 }
614 }
615
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +0530616 void setPreviewFrameLayoutCameraOrientation(){
617 CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
618 //if camera mount angle is 0 or 180, we want to resize preview
619 if (info.orientation % 180 == 0){
620 mUI.cameraOrientationPreviewResize(true);
621 } else{
622 mUI.cameraOrientationPreviewResize(false);
623 }
624 }
625
626 private void resizeForPreviewAspectRatio() {
627 setPreviewFrameLayoutCameraOrientation();
628 Size size = mParameters.getPictureSize();
629 Log.e(TAG,"Width = "+ size.width+ "Height = "+size.height);
630 mUI.setAspectRatio((float) size.width / size.height);
631 }
632
633
Michael Kolb8872c232013-01-29 10:33:22 -0800634 private void keepMediaProviderInstance() {
635 // We want to keep a reference to MediaProvider in camera's lifecycle.
636 // TODO: Utilize mMediaProviderClient instance to replace
637 // ContentResolver calls.
638 if (mMediaProviderClient == null) {
639 mMediaProviderClient = mContentResolver
640 .acquireContentProviderClient(MediaStore.AUTHORITY);
641 }
642 }
643
644 // Snapshots can only be taken after this is called. It should be called
645 // once only. We could have done these things in onCreate() but we want to
646 // make preview screen appear as soon as possible.
647 private void initializeFirstTime() {
Sascha Haeberling330dafb2013-10-10 19:00:41 -0700648 if (mFirstTimeInitialized || mPaused) {
649 return;
650 }
Michael Kolb8872c232013-01-29 10:33:22 -0800651
652 // Initialize location service.
653 boolean recordLocation = RecordLocationPreference.get(
654 mPreferences, mContentResolver);
655 mLocationManager.recordLocation(recordLocation);
656
657 keepMediaProviderInstance();
658
Michael Kolbd6954f32013-03-08 20:43:01 -0800659 mUI.initializeFirstTime();
Angus Kong86d36312013-01-31 18:22:44 -0800660 MediaSaveService s = mActivity.getMediaSaveService();
661 // We set the listener only when both service and shutterbutton
662 // are initialized.
663 if (s != null) {
664 s.setListener(this);
665 }
Michael Kolb8872c232013-01-29 10:33:22 -0800666
Michael Kolb8872c232013-01-29 10:33:22 -0800667 mNamedImages = new NamedImages();
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530668 mGraphView = (GraphView)mRootView.findViewById(R.id.graph_view);
669 if(mGraphView == null){
670 Log.e(TAG, "mGraphView is null");
671 } else{
672 mGraphView.setPhotoModuleObject(this);
673 }
Michael Kolb8872c232013-01-29 10:33:22 -0800674
675 mFirstTimeInitialized = true;
676 addIdleHandler();
677
678 mActivity.updateStorageSpaceAndHint();
679 }
680
Michael Kolbd6954f32013-03-08 20:43:01 -0800681 // If the activity is paused and resumed, this method will be called in
682 // onResume.
683 private void initializeSecondTime() {
684 // Start location update if needed.
685 boolean recordLocation = RecordLocationPreference.get(
686 mPreferences, mContentResolver);
687 mLocationManager.recordLocation(recordLocation);
688 MediaSaveService s = mActivity.getMediaSaveService();
689 if (s != null) {
690 s.setListener(this);
691 }
692 mNamedImages = new NamedImages();
693 mUI.initializeSecondTime(mParameters);
694 keepMediaProviderInstance();
695 }
696
Michael Kolb8872c232013-01-29 10:33:22 -0800697 private void showTapToFocusToastIfNeeded() {
698 // Show the tap to focus toast if this is the first start.
699 if (mFocusAreaSupported &&
700 mPreferences.getBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, true)) {
701 // Delay the toast for one second to wait for orientation.
702 mHandler.sendEmptyMessageDelayed(SHOW_TAP_TO_FOCUS_TOAST, 1000);
703 }
704 }
705
706 private void addIdleHandler() {
707 MessageQueue queue = Looper.myQueue();
708 queue.addIdleHandler(new MessageQueue.IdleHandler() {
709 @Override
710 public boolean queueIdle() {
711 Storage.ensureOSXCompatible();
712 return false;
713 }
714 });
715 }
716
Michael Kolb8872c232013-01-29 10:33:22 -0800717 @Override
718 public void startFaceDetection() {
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530719 if (mFaceDetectionEnabled == false
720 || mFaceDetectionStarted || mCameraState != IDLE) return;
Michael Kolb8872c232013-01-29 10:33:22 -0800721 if (mParameters.getMaxNumDetectedFaces() > 0) {
722 mFaceDetectionStarted = true;
Michael Kolb8872c232013-01-29 10:33:22 -0800723 CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
Michael Kolbd6954f32013-03-08 20:43:01 -0800724 mUI.onStartFaceDetection(mDisplayOrientation,
725 (info.facing == CameraInfo.CAMERA_FACING_FRONT));
Angus Kong9e765522013-07-31 14:05:20 -0700726 mCameraDevice.setFaceDetectionCallback(mHandler, mUI);
Michael Kolb8872c232013-01-29 10:33:22 -0800727 mCameraDevice.startFaceDetection();
728 }
729 }
730
Michael Kolb8872c232013-01-29 10:33:22 -0800731 @Override
732 public void stopFaceDetection() {
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530733 if (mFaceDetectionEnabled == false || !mFaceDetectionStarted) return;
Michael Kolb8872c232013-01-29 10:33:22 -0800734 if (mParameters.getMaxNumDetectedFaces() > 0) {
735 mFaceDetectionStarted = false;
Angus Kong9e765522013-07-31 14:05:20 -0700736 mCameraDevice.setFaceDetectionCallback(null, null);
Michael Kolb8872c232013-01-29 10:33:22 -0800737 mCameraDevice.stopFaceDetection();
Michael Kolbd6954f32013-03-08 20:43:01 -0800738 mUI.clearFaces();
Michael Kolb8872c232013-01-29 10:33:22 -0800739 }
740 }
741
Michael Kolb8872c232013-01-29 10:33:22 -0800742 private final class ShutterCallback
Angus Kong9ef99252013-07-18 18:04:19 -0700743 implements CameraShutterCallback {
Angus Kongdcb0ef12013-03-25 23:11:43 -0700744
Sascha Haeberling37f36112013-08-06 14:31:52 -0700745 private boolean mNeedsAnimation;
Angus Kongdcb0ef12013-03-25 23:11:43 -0700746
Sascha Haeberling37f36112013-08-06 14:31:52 -0700747 public ShutterCallback(boolean needsAnimation) {
748 mNeedsAnimation = needsAnimation;
Angus Kongdcb0ef12013-03-25 23:11:43 -0700749 }
750
Michael Kolb8872c232013-01-29 10:33:22 -0800751 @Override
Angus Kong9ef99252013-07-18 18:04:19 -0700752 public void onShutter(CameraProxy camera) {
Michael Kolb8872c232013-01-29 10:33:22 -0800753 mShutterCallbackTime = System.currentTimeMillis();
754 mShutterLag = mShutterCallbackTime - mCaptureStartTime;
Alok Kediya2bc105d2013-09-28 18:17:41 +0530755 Log.e(TAG, "[KPI Perf] PROFILE_SHUTTER_LAG mShutterLag = " + mShutterLag + "ms");
Sascha Haeberling37f36112013-08-06 14:31:52 -0700756 if (mNeedsAnimation) {
757 mActivity.runOnUiThread(new Runnable() {
758 @Override
759 public void run() {
760 animateAfterShutter();
761 }
762 });
Angus Kongdcb0ef12013-03-25 23:11:43 -0700763 }
Michael Kolb8872c232013-01-29 10:33:22 -0800764 }
765 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530766 private final class StatsCallback
767 implements android.hardware.Camera.CameraDataCallback {
768 @Override
769 public void onCameraData(int [] data, android.hardware.Camera camera) {
770 //if(!mPreviewing || !mHiston || !mFirstTimeInitialized){
771 if(!mHiston || !mFirstTimeInitialized){
772 return;
773 }
774 /*The first element in the array stores max hist value . Stats data begin from second value*/
775 synchronized(statsdata) {
776 System.arraycopy(data,0,statsdata,0,STATS_DATA);
777 }
778 mActivity.runOnUiThread(new Runnable() {
779 public void run() {
780 if(mGraphView != null)
781 mGraphView.PreviewChanged();
782 }
783 });
784 }
785 }
Angus Kong9ef99252013-07-18 18:04:19 -0700786 private final class PostViewPictureCallback
787 implements CameraPictureCallback {
Michael Kolb8872c232013-01-29 10:33:22 -0800788 @Override
Angus Kong9ef99252013-07-18 18:04:19 -0700789 public void onPictureTaken(byte [] data, CameraProxy camera) {
Michael Kolb8872c232013-01-29 10:33:22 -0800790 mPostViewPictureCallbackTime = System.currentTimeMillis();
791 Log.v(TAG, "mShutterToPostViewCallbackTime = "
792 + (mPostViewPictureCallbackTime - mShutterCallbackTime)
793 + "ms");
794 }
795 }
796
Angus Kong9ef99252013-07-18 18:04:19 -0700797 private final class RawPictureCallback
798 implements CameraPictureCallback {
Michael Kolb8872c232013-01-29 10:33:22 -0800799 @Override
Angus Kong9ef99252013-07-18 18:04:19 -0700800 public void onPictureTaken(byte [] rawData, CameraProxy camera) {
Michael Kolb8872c232013-01-29 10:33:22 -0800801 mRawPictureCallbackTime = System.currentTimeMillis();
802 Log.v(TAG, "mShutterToRawCallbackTime = "
803 + (mRawPictureCallbackTime - mShutterCallbackTime) + "ms");
804 }
805 }
806
Angus Kong9ef99252013-07-18 18:04:19 -0700807 private final class JpegPictureCallback
808 implements CameraPictureCallback {
Michael Kolb8872c232013-01-29 10:33:22 -0800809 Location mLocation;
810
811 public JpegPictureCallback(Location loc) {
812 mLocation = loc;
813 }
814
815 @Override
Angus Kong9ef99252013-07-18 18:04:19 -0700816 public void onPictureTaken(final byte [] jpegData, CameraProxy camera) {
Sascha Haeberling88901942013-08-28 17:49:00 -0700817 mUI.enableShutter(true);
Michael Kolb8872c232013-01-29 10:33:22 -0800818 if (mPaused) {
819 return;
820 }
Doris Liu6432cd62013-06-13 17:20:31 -0700821 if (mIsImageCaptureIntent) {
822 stopPreview();
823 }
Angus Kongb50b5cb2013-08-09 14:55:20 -0700824 if (mSceneMode == CameraUtil.SCENE_MODE_HDR) {
Doris Liu6432cd62013-06-13 17:20:31 -0700825 mUI.showSwitcher();
826 mUI.setSwipingEnabled(true);
Michael Kolb8872c232013-01-29 10:33:22 -0800827 }
828
Alok Kediya28c31962013-09-28 16:43:35 +0530829 mReceivedSnapNum = mReceivedSnapNum + 1;
Michael Kolb8872c232013-01-29 10:33:22 -0800830 mJpegPictureCallbackTime = System.currentTimeMillis();
Alok Kediya28c31962013-09-28 16:43:35 +0530831 if(mSnapshotMode == CameraInfo.CAMERA_SUPPORT_MODE_ZSL) {
832 Log.v(TAG, "JpegPictureCallback : in zslmode");
833 mParameters = mCameraDevice.getParameters();
834 mBurstSnapNum = mParameters.getInt("num-snaps-per-shutter");
835 }
836 Log.v(TAG, "JpegPictureCallback: Received = " + mReceivedSnapNum +
837 "Burst count = " + mBurstSnapNum);
Michael Kolb8872c232013-01-29 10:33:22 -0800838 // If postview callback has arrived, the captured image is displayed
839 // in postview callback. If not, the captured image is displayed in
840 // raw picture callback.
841 if (mPostViewPictureCallbackTime != 0) {
842 mShutterToPictureDisplayedTime =
843 mPostViewPictureCallbackTime - mShutterCallbackTime;
844 mPictureDisplayedToJpegCallbackTime =
845 mJpegPictureCallbackTime - mPostViewPictureCallbackTime;
846 } else {
847 mShutterToPictureDisplayedTime =
848 mRawPictureCallbackTime - mShutterCallbackTime;
849 mPictureDisplayedToJpegCallbackTime =
850 mJpegPictureCallbackTime - mRawPictureCallbackTime;
851 }
852 Log.v(TAG, "mPictureDisplayedToJpegCallbackTime = "
853 + mPictureDisplayedToJpegCallbackTime + "ms");
854
Michael Kolb8872c232013-01-29 10:33:22 -0800855 mFocusManager.updateFocusUI(); // Ensure focus indicator is hidden.
Alok Kediya28c31962013-09-28 16:43:35 +0530856
857 boolean needRestartPreview = !mIsImageCaptureIntent
858 && (mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_ZSL)
859 && (mReceivedSnapNum == mBurstSnapNum);
860 if (needRestartPreview) {
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700861 setupPreview();
Alok Kediya28c31962013-09-28 16:43:35 +0530862 }else if (mReceivedSnapNum == mBurstSnapNum){
863 mFocusManager.resetTouchFocus();
864 setCameraState(IDLE);
Michael Kolb8872c232013-01-29 10:33:22 -0800865 }
866
Doris Liu36e56fb2013-09-11 17:38:08 -0700867 ExifInterface exif = Exif.getExif(jpegData);
868 int orientation = Exif.getOrientation(exif);
Ruben Brunkd217ed02013-10-08 23:31:13 -0700869
Ruben Brunkd7488272013-10-10 18:45:53 -0700870 if (!mIsImageCaptureIntent) {
Alok Kediya28c31962013-09-28 16:43:35 +0530871 // Burst snapshot. Generate new image name.
872 if (mReceivedSnapNum > 1)
873 mNamedImages.nameNewImage(mCaptureStartTime);
874
Michael Kolb8872c232013-01-29 10:33:22 -0800875 // Calculate the width and the height of the jpeg.
876 Size s = mParameters.getPictureSize();
Michael Kolb8872c232013-01-29 10:33:22 -0800877 int width, height;
878 if ((mJpegRotation + orientation) % 180 == 0) {
879 width = s.width;
880 height = s.height;
881 } else {
882 width = s.height;
883 height = s.width;
884 }
Alok Kediyad8887ed2013-09-28 17:12:35 +0530885
886 String pictureFormat = mParameters.get(KEY_PICTURE_FORMAT);
887 if (pictureFormat != null && !pictureFormat.equalsIgnoreCase(PIXEL_FORMAT_JPEG)) {
888 // overwrite width and height if raw picture
889 String pair = mParameters.get(KEY_QC_RAW_PICUTRE_SIZE);
890 if (pair != null) {
891 int pos = pair.indexOf('x');
892 if (pos != -1) {
893 width = Integer.parseInt(pair.substring(0, pos));
894 height = Integer.parseInt(pair.substring(pos + 1));
895 }
896 }
897 }
Ruben Brunka9d66bd2013-09-06 11:56:32 -0700898 NamedEntity name = mNamedImages.getNextNameEntity();
899 String title = (name == null) ? null : name.title;
900 long date = (name == null) ? -1 : name.date;
Ruben Brunkd7488272013-10-10 18:45:53 -0700901
902 // Handle debug mode outputs
903 if (mDebugUri != null) {
904 // If using a debug uri, save jpeg there.
905 saveToDebugUri(jpegData);
906
907 // Adjust the title of the debug image shown in mediastore.
908 if (title != null) {
909 title = DEBUG_IMAGE_PREFIX + title;
910 }
911 }
912
Michael Kolb8872c232013-01-29 10:33:22 -0800913 if (title == null) {
914 Log.e(TAG, "Unbalanced name/data pair");
915 } else {
916 if (date == -1) date = mCaptureStartTime;
Angus Kong0d00a892013-03-26 11:40:40 -0700917 if (mHeading >= 0) {
918 // heading direction has been updated by the sensor.
919 ExifTag directionRefTag = exif.buildTag(
920 ExifInterface.TAG_GPS_IMG_DIRECTION_REF,
921 ExifInterface.GpsTrackRef.MAGNETIC_DIRECTION);
922 ExifTag directionTag = exif.buildTag(
923 ExifInterface.TAG_GPS_IMG_DIRECTION,
924 new Rational(mHeading, 1));
925 exif.setTag(directionRefTag);
926 exif.setTag(directionTag);
927 }
Alok Kediyad8887ed2013-09-28 17:12:35 +0530928 String mPictureFormat = mParameters.get(KEY_PICTURE_FORMAT);
Angus Kong86d36312013-01-31 18:22:44 -0800929 mActivity.getMediaSaveService().addImage(
930 jpegData, title, date, mLocation, width, height,
Alok Kediyad8887ed2013-09-28 17:12:35 +0530931 orientation, exif, mOnMediaSavedListener, mContentResolver, mPictureFormat);
Michael Kolb8872c232013-01-29 10:33:22 -0800932 }
Doris Liuce2acbc2013-08-21 18:45:29 -0700933 // Animate capture with real jpeg data instead of a preview frame.
Doris Liu29da2db2013-08-28 14:28:45 -0700934 mUI.animateCapture(jpegData, orientation, mMirror);
Michael Kolb8872c232013-01-29 10:33:22 -0800935 } else {
936 mJpegImageData = jpegData;
937 if (!mQuickCapture) {
Doris Liu36e56fb2013-09-11 17:38:08 -0700938 mUI.showCapturedImageForReview(jpegData, orientation, mMirror);
Michael Kolb8872c232013-01-29 10:33:22 -0800939 } else {
Michael Kolbd6954f32013-03-08 20:43:01 -0800940 onCaptureDone();
Michael Kolb8872c232013-01-29 10:33:22 -0800941 }
942 }
943
944 // Check this in advance of each shot so we don't add to shutter
945 // latency. It's true that someone else could write to the SD card in
946 // the mean time and fill it, but that could have happened between the
947 // shutter press and saving the JPEG too.
948 mActivity.updateStorageSpaceAndHint();
949
950 long now = System.currentTimeMillis();
951 mJpegCallbackFinishTime = now - mJpegPictureCallbackTime;
952 Log.v(TAG, "mJpegCallbackFinishTime = "
953 + mJpegCallbackFinishTime + "ms");
Alok Kediya28c31962013-09-28 16:43:35 +0530954 if (mReceivedSnapNum == mBurstSnapNum)
955 mJpegPictureCallbackTime = 0;
956
Alok Kediyaa4bd0a62013-09-28 16:10:53 +0530957 if (mHiston && (mSnapshotMode ==CameraInfo.CAMERA_SUPPORT_MODE_ZSL)) {
958 mActivity.runOnUiThread(new Runnable() {
959 public void run() {
960 if (mGraphView != null) {
961 mGraphView.setVisibility(View.VISIBLE);
962 mGraphView.PreviewChanged();
963 }
964 }
965 });
966 }
Michael Kolb8872c232013-01-29 10:33:22 -0800967 }
968 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530969 private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
970 public void onStartTrackingTouch(SeekBar bar) {
971 // no support
972 }
973 public void onProgressChanged(SeekBar bar, int progress, boolean fromtouch) {
974 }
975 public void onStopTrackingTouch(SeekBar bar) {
976 }
977 };
Michael Kolb8872c232013-01-29 10:33:22 -0800978
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530979 private OnSeekBarChangeListener mskinToneSeekListener = new OnSeekBarChangeListener() {
980 public void onStartTrackingTouch(SeekBar bar) {
981 // no support
982 }
983
Santhosh Kumar H Ed7dfbf82013-10-25 14:32:17 +0530984 private OnSeekBarChangeListener mskinToneSeekListener = new OnSeekBarChangeListener() {
985 public void onStartTrackingTouch(SeekBar bar) {
986 // no support
987 }
988
Alok Kediya0dc64ff2013-09-27 20:22:45 +0530989 public void onProgressChanged(SeekBar bar, int progress, boolean fromtouch) {
990 int value = (progress + MIN_SCE_FACTOR) * SCE_FACTOR_STEP;
991 if(progress > (MAX_SCE_FACTOR - MIN_SCE_FACTOR)/2){
992 RightValue.setText(String.valueOf(value));
993 LeftValue.setText("");
994 } else if (progress < (MAX_SCE_FACTOR - MIN_SCE_FACTOR)/2){
995 LeftValue.setText(String.valueOf(value));
996 RightValue.setText("");
997 } else {
998 LeftValue.setText("");
999 RightValue.setText("");
1000 }
Santhosh Kumar H Ed7dfbf82013-10-25 14:32:17 +05301001 if (value != mskinToneValue && mCameraDevice != null) {
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301002 mskinToneValue = value;
Santhosh Kumar H Ed7dfbf82013-10-25 14:32:17 +05301003 Message msg = mHandler.obtainMessage(CONFIGURE_SKIN_TONE_FACTOR, mskinToneValue, 0);
1004 mHandler.sendMessage(msg);
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301005 }
1006 }
1007
1008 public void onStopTrackingTouch(SeekBar bar) {
1009 Log.v(TAG, "Set onStopTrackingTouch mskinToneValue = " + mskinToneValue);
1010 Editor editor = mPreferences.edit();
1011 editor.putString(CameraSettings.KEY_SKIN_TONE_ENHANCEMENT_FACTOR,
1012 Integer.toString(mskinToneValue));
1013 editor.apply();
1014 }
1015 };
Angus Kong9ef99252013-07-18 18:04:19 -07001016 private final class AutoFocusCallback implements CameraAFCallback {
Michael Kolb8872c232013-01-29 10:33:22 -08001017 @Override
1018 public void onAutoFocus(
Angus Kong9ef99252013-07-18 18:04:19 -07001019 boolean focused, CameraProxy camera) {
Michael Kolb8872c232013-01-29 10:33:22 -08001020 if (mPaused) return;
1021
1022 mAutoFocusTime = System.currentTimeMillis() - mFocusStartTime;
1023 Log.v(TAG, "mAutoFocusTime = " + mAutoFocusTime + "ms");
1024 setCameraState(IDLE);
Michael Kolbd6954f32013-03-08 20:43:01 -08001025 mFocusManager.onAutoFocus(focused, mUI.isShutterPressed());
Michael Kolb8872c232013-01-29 10:33:22 -08001026 }
1027 }
1028
Sascha Haeberling638e6f02013-09-18 14:28:51 -07001029 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
Michael Kolb8872c232013-01-29 10:33:22 -08001030 private final class AutoFocusMoveCallback
Angus Kong9ef99252013-07-18 18:04:19 -07001031 implements CameraAFMoveCallback {
Michael Kolb8872c232013-01-29 10:33:22 -08001032 @Override
1033 public void onAutoFocusMoving(
Dan Aminzade92ae10e2013-08-13 14:44:25 -07001034 boolean moving, CameraProxy camera) {
1035 mFocusManager.onAutoFocusMoving(moving);
Michael Kolb8872c232013-01-29 10:33:22 -08001036 }
1037 }
1038
Ruben Brunka9d66bd2013-09-06 11:56:32 -07001039 /**
1040 * This class is just a thread-safe queue for name,date holder objects.
1041 */
1042 public static class NamedImages {
1043 private Vector<NamedEntity> mQueue;
Michael Kolb8872c232013-01-29 10:33:22 -08001044
1045 public NamedImages() {
Ruben Brunka9d66bd2013-09-06 11:56:32 -07001046 mQueue = new Vector<NamedEntity>();
Michael Kolb8872c232013-01-29 10:33:22 -08001047 }
1048
Ruben Brunka9d66bd2013-09-06 11:56:32 -07001049 public void nameNewImage(long date) {
Michael Kolb8872c232013-01-29 10:33:22 -08001050 NamedEntity r = new NamedEntity();
Angus Kongb50b5cb2013-08-09 14:55:20 -07001051 r.title = CameraUtil.createJpegName(date);
Michael Kolb8872c232013-01-29 10:33:22 -08001052 r.date = date;
1053 mQueue.add(r);
1054 }
1055
Ruben Brunka9d66bd2013-09-06 11:56:32 -07001056 public NamedEntity getNextNameEntity() {
1057 synchronized(mQueue) {
1058 if (!mQueue.isEmpty()) {
1059 return mQueue.remove(0);
1060 }
Michael Kolb8872c232013-01-29 10:33:22 -08001061 }
Ruben Brunka9d66bd2013-09-06 11:56:32 -07001062 return null;
Michael Kolb8872c232013-01-29 10:33:22 -08001063 }
1064
Ruben Brunka9d66bd2013-09-06 11:56:32 -07001065 public static class NamedEntity {
1066 public String title;
1067 public long date;
Michael Kolb8872c232013-01-29 10:33:22 -08001068 }
1069 }
1070
1071 private void setCameraState(int state) {
1072 mCameraState = state;
1073 switch (state) {
Dan Aminzade92ae10e2013-08-13 14:44:25 -07001074 case PhotoController.PREVIEW_STOPPED:
1075 case PhotoController.SNAPSHOT_IN_PROGRESS:
1076 case PhotoController.SWITCHING_CAMERA:
1077 mUI.enableGestures(false);
1078 break;
1079 case PhotoController.IDLE:
1080 mUI.enableGestures(true);
1081 break;
Michael Kolb8872c232013-01-29 10:33:22 -08001082 }
1083 }
1084
Sascha Haeberling37f36112013-08-06 14:31:52 -07001085 private void animateAfterShutter() {
Michael Kolb8872c232013-01-29 10:33:22 -08001086 // Only animate when in full screen capture mode
1087 // i.e. If monkey/a user swipes to the gallery during picture taking,
1088 // don't show animation
Doris Liuc2e9abd2013-06-19 14:20:51 -07001089 if (!mIsImageCaptureIntent) {
1090 mUI.animateFlash();
Doris Liuc2e9abd2013-06-19 14:20:51 -07001091 }
Michael Kolb8872c232013-01-29 10:33:22 -08001092 }
1093
1094 @Override
1095 public boolean capture() {
1096 // If we are already in the middle of taking a snapshot or the image save request
1097 // is full then ignore.
1098 if (mCameraDevice == null || mCameraState == SNAPSHOT_IN_PROGRESS
Angus Kong86d36312013-01-31 18:22:44 -08001099 || mCameraState == SWITCHING_CAMERA
1100 || mActivity.getMediaSaveService().isQueueFull()) {
Michael Kolb8872c232013-01-29 10:33:22 -08001101 return false;
1102 }
1103 mCaptureStartTime = System.currentTimeMillis();
1104 mPostViewPictureCallbackTime = 0;
1105 mJpegImageData = null;
1106
Angus Kongb50b5cb2013-08-09 14:55:20 -07001107 final boolean animateBefore = (mSceneMode == CameraUtil.SCENE_MODE_HDR);
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301108 if(mHiston) {
1109 if (mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_ZSL) {
1110 mHiston = false;
1111 mCameraDevice.setHistogramMode(null);
1112 }
1113 mActivity.runOnUiThread(new Runnable() {
1114 public void run() {
1115 if(mGraphView != null)
1116 mGraphView.setVisibility(View.INVISIBLE);
1117 }
1118 });
1119 }
Michael Kolb8872c232013-01-29 10:33:22 -08001120
1121 if (animateBefore) {
Sascha Haeberling37f36112013-08-06 14:31:52 -07001122 animateAfterShutter();
Michael Kolb8872c232013-01-29 10:33:22 -08001123 }
1124
1125 // Set rotation and gps data.
Doris Liu3cf565c2013-02-15 10:55:37 -08001126 int orientation;
1127 // We need to be consistent with the framework orientation (i.e. the
1128 // orientation of the UI.) when the auto-rotate screen setting is on.
1129 if (mActivity.isAutoRotateScreen()) {
1130 orientation = (360 - mDisplayRotation) % 360;
1131 } else {
1132 orientation = mOrientation;
1133 }
Angus Kongb50b5cb2013-08-09 14:55:20 -07001134 mJpegRotation = CameraUtil.getJpegRotation(mCameraId, orientation);
Michael Kolb8872c232013-01-29 10:33:22 -08001135 mParameters.setRotation(mJpegRotation);
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301136 String pictureFormat = mParameters.get(KEY_PICTURE_FORMAT);
1137 Location loc = null;
1138 if (pictureFormat != null &&
1139 PIXEL_FORMAT_JPEG.equalsIgnoreCase(pictureFormat)) {
1140 loc = mLocationManager.getCurrentLocation();
1141 }
Angus Kongb50b5cb2013-08-09 14:55:20 -07001142 CameraUtil.setGpsParameters(mParameters, loc);
Michael Kolb8872c232013-01-29 10:33:22 -08001143 mCameraDevice.setParameters(mParameters);
Alok Kediya28c31962013-09-28 16:43:35 +05301144 mParameters = mCameraDevice.getParameters();
1145
1146 mBurstSnapNum = mParameters.getInt("num-snaps-per-shutter");
1147 mReceivedSnapNum = 0;
Michael Kolb8872c232013-01-29 10:33:22 -08001148
Sascha Haeberling88901942013-08-28 17:49:00 -07001149 // We don't want user to press the button again while taking a
1150 // multi-second HDR photo.
1151 mUI.enableShutter(false);
Angus Kong9ef99252013-07-18 18:04:19 -07001152 mCameraDevice.takePicture(mHandler,
1153 new ShutterCallback(!animateBefore),
Angus Kongdcb0ef12013-03-25 23:11:43 -07001154 mRawPictureCallback, mPostViewPictureCallback,
Angus Kong9ef99252013-07-18 18:04:19 -07001155 new JpegPictureCallback(loc));
Michael Kolb8872c232013-01-29 10:33:22 -08001156
Ruben Brunka9d66bd2013-09-06 11:56:32 -07001157 mNamedImages.nameNewImage(mCaptureStartTime);
Michael Kolb8872c232013-01-29 10:33:22 -08001158
1159 mFaceDetectionStarted = false;
1160 setCameraState(SNAPSHOT_IN_PROGRESS);
Bobby Georgescu301b6462013-04-01 15:33:17 -07001161 UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
1162 UsageStatistics.ACTION_CAPTURE_DONE, "Photo");
Michael Kolb8872c232013-01-29 10:33:22 -08001163 return true;
1164 }
1165
1166 @Override
1167 public void setFocusParameters() {
1168 setCameraParameters(UPDATE_PARAM_PREFERENCE);
1169 }
1170
1171 private int getPreferredCameraId(ComboPreferences preferences) {
Angus Kongb50b5cb2013-08-09 14:55:20 -07001172 int intentCameraId = CameraUtil.getCameraFacingIntentExtras(mActivity);
Michael Kolb8872c232013-01-29 10:33:22 -08001173 if (intentCameraId != -1) {
1174 // Testing purpose. Launch a specific camera through the intent
1175 // extras.
1176 return intentCameraId;
1177 } else {
1178 return CameraSettings.readPreferredCameraId(preferences);
1179 }
1180 }
1181
Alok Kediya427798d2013-09-28 17:42:32 +05301182 private void updateHdrMode() {
1183 String zsl = mPreferences.getString(CameraSettings.KEY_ZSL,
1184 mActivity.getString(R.string.pref_camera_zsl_default));
1185 if (zsl.equals("on")) {
1186 mUI.overrideSettings(CameraSettings.KEY_CAMERA_HDR,
1187 mParameters.getAEBracket());
1188 } else {
1189 mUI.overrideSettings(CameraSettings.KEY_CAMERA_HDR, null);
1190 }
1191 }
1192
Michael Kolbd6954f32013-03-08 20:43:01 -08001193 private void updateSceneMode() {
Michael Kolb8872c232013-01-29 10:33:22 -08001194 // If scene mode is set, we cannot set flash mode, white balance, and
1195 // focus mode, instead, we read it from driver
1196 if (!Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) {
1197 overrideCameraSettings(mParameters.getFlashMode(),
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301198 mParameters.getWhiteBalance(), mParameters.getFocusMode(),
1199 Integer.toString(mParameters.getExposureCompensation()),
Alok Kediya5fdf67e2013-10-02 18:00:14 +05301200 mCurrTouchAfAec, mParameters.getAutoExposure());
Michael Kolb8872c232013-01-29 10:33:22 -08001201 } else {
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301202 overrideCameraSettings(null, null, null, null, null, null);
Michael Kolb8872c232013-01-29 10:33:22 -08001203 }
1204 }
1205
1206 private void overrideCameraSettings(final String flashMode,
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301207 final String whiteBalance, final String focusMode,
1208 final String exposureMode, final String touchMode,
1209 final String autoExposure) {
Michael Kolbd6954f32013-03-08 20:43:01 -08001210 mUI.overrideSettings(
1211 CameraSettings.KEY_FLASH_MODE, flashMode,
1212 CameraSettings.KEY_WHITE_BALANCE, whiteBalance,
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301213 CameraSettings.KEY_FOCUS_MODE, focusMode,
1214 CameraSettings.KEY_EXPOSURE, exposureMode,
1215 CameraSettings.KEY_TOUCH_AF_AEC, touchMode,
1216 CameraSettings.KEY_AUTOEXPOSURE, autoExposure);
Michael Kolb8872c232013-01-29 10:33:22 -08001217 }
1218
1219 private void loadCameraPreferences() {
1220 CameraSettings settings = new CameraSettings(mActivity, mInitialParams,
1221 mCameraId, CameraHolder.instance().getCameraInfo());
1222 mPreferenceGroup = settings.getPreferenceGroup(R.xml.camera_preferences);
1223 }
1224
1225 @Override
Michael Kolb8872c232013-01-29 10:33:22 -08001226 public void onOrientationChanged(int orientation) {
1227 // We keep the last known orientation. So if the user first orient
1228 // the camera then point the camera to floor or sky, we still have
1229 // the correct orientation.
1230 if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) return;
Alok Kediya4b6f3f92013-09-28 17:39:13 +05301231 int oldOrientation = mOrientation;
Angus Kongb50b5cb2013-08-09 14:55:20 -07001232 mOrientation = CameraUtil.roundOrientation(orientation, mOrientation);
Alok Kediya4b6f3f92013-09-28 17:39:13 +05301233 if (oldOrientation != mOrientation) {
1234 Log.v(TAG, "onOrientationChanged, update parameters");
1235 if (mParameters != null && mCameraDevice != null) {
1236 onSharedPreferenceChanged();
1237 }
1238 }
Michael Kolb8872c232013-01-29 10:33:22 -08001239
1240 // Show the toast after getting the first orientation changed.
1241 if (mHandler.hasMessages(SHOW_TAP_TO_FOCUS_TOAST)) {
1242 mHandler.removeMessages(SHOW_TAP_TO_FOCUS_TOAST);
1243 showTapToFocusToast();
1244 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301245
1246 // need to re-initialize mGraphView to show histogram on rotate
1247 mGraphView = (GraphView)mRootView.findViewById(R.id.graph_view);
1248 if(mGraphView != null){
1249 mGraphView.setPhotoModuleObject(this);
1250 mGraphView.PreviewChanged();
1251 }
Michael Kolb8872c232013-01-29 10:33:22 -08001252 }
1253
1254 @Override
1255 public void onStop() {
1256 if (mMediaProviderClient != null) {
1257 mMediaProviderClient.release();
1258 mMediaProviderClient = null;
1259 }
1260 }
1261
Michael Kolbd6954f32013-03-08 20:43:01 -08001262 @Override
1263 public void onCaptureCancelled() {
1264 mActivity.setResultEx(Activity.RESULT_CANCELED, new Intent());
1265 mActivity.finish();
Michael Kolb8872c232013-01-29 10:33:22 -08001266 }
1267
Michael Kolbd6954f32013-03-08 20:43:01 -08001268 @Override
1269 public void onCaptureRetake() {
Michael Kolb8872c232013-01-29 10:33:22 -08001270 if (mPaused)
1271 return;
Michael Kolbd6954f32013-03-08 20:43:01 -08001272 mUI.hidePostCaptureAlert();
Michael Kolb8872c232013-01-29 10:33:22 -08001273 setupPreview();
1274 }
1275
Michael Kolbd6954f32013-03-08 20:43:01 -08001276 @Override
1277 public void onCaptureDone() {
Michael Kolb8872c232013-01-29 10:33:22 -08001278 if (mPaused) {
1279 return;
1280 }
1281
1282 byte[] data = mJpegImageData;
1283
1284 if (mCropValue == null) {
1285 // First handle the no crop case -- just return the value. If the
1286 // caller specifies a "save uri" then write the data to its
1287 // stream. Otherwise, pass back a scaled down version of the bitmap
1288 // directly in the extras.
1289 if (mSaveUri != null) {
1290 OutputStream outputStream = null;
1291 try {
1292 outputStream = mContentResolver.openOutputStream(mSaveUri);
1293 outputStream.write(data);
1294 outputStream.close();
1295
1296 mActivity.setResultEx(Activity.RESULT_OK);
1297 mActivity.finish();
1298 } catch (IOException ex) {
1299 // ignore exception
1300 } finally {
Angus Kongb50b5cb2013-08-09 14:55:20 -07001301 CameraUtil.closeSilently(outputStream);
Michael Kolb8872c232013-01-29 10:33:22 -08001302 }
1303 } else {
Angus Kong0d00a892013-03-26 11:40:40 -07001304 ExifInterface exif = Exif.getExif(data);
1305 int orientation = Exif.getOrientation(exif);
Angus Kongb50b5cb2013-08-09 14:55:20 -07001306 Bitmap bitmap = CameraUtil.makeBitmap(data, 50 * 1024);
1307 bitmap = CameraUtil.rotate(bitmap, orientation);
Michael Kolb8872c232013-01-29 10:33:22 -08001308 mActivity.setResultEx(Activity.RESULT_OK,
1309 new Intent("inline-data").putExtra("data", bitmap));
1310 mActivity.finish();
1311 }
1312 } else {
1313 // Save the image to a temp file and invoke the cropper
1314 Uri tempUri = null;
1315 FileOutputStream tempStream = null;
1316 try {
1317 File path = mActivity.getFileStreamPath(sTempCropFilename);
1318 path.delete();
1319 tempStream = mActivity.openFileOutput(sTempCropFilename, 0);
1320 tempStream.write(data);
1321 tempStream.close();
1322 tempUri = Uri.fromFile(path);
1323 } catch (FileNotFoundException ex) {
1324 mActivity.setResultEx(Activity.RESULT_CANCELED);
1325 mActivity.finish();
1326 return;
1327 } catch (IOException ex) {
1328 mActivity.setResultEx(Activity.RESULT_CANCELED);
1329 mActivity.finish();
1330 return;
1331 } finally {
Angus Kongb50b5cb2013-08-09 14:55:20 -07001332 CameraUtil.closeSilently(tempStream);
Michael Kolb8872c232013-01-29 10:33:22 -08001333 }
1334
1335 Bundle newExtras = new Bundle();
1336 if (mCropValue.equals("circle")) {
1337 newExtras.putString("circleCrop", "true");
1338 }
1339 if (mSaveUri != null) {
1340 newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, mSaveUri);
1341 } else {
Angus Kongb50b5cb2013-08-09 14:55:20 -07001342 newExtras.putBoolean(CameraUtil.KEY_RETURN_DATA, true);
Michael Kolb8872c232013-01-29 10:33:22 -08001343 }
1344 if (mActivity.isSecureCamera()) {
Angus Kongb50b5cb2013-08-09 14:55:20 -07001345 newExtras.putBoolean(CameraUtil.KEY_SHOW_WHEN_LOCKED, true);
Michael Kolb8872c232013-01-29 10:33:22 -08001346 }
1347
Sascha Haeberling37f36112013-08-06 14:31:52 -07001348 // TODO: Share this constant.
Sascha Haeberling8e963a52013-08-06 11:43:02 -07001349 final String CROP_ACTION = "com.android.camera.action.CROP";
1350 Intent cropIntent = new Intent(CROP_ACTION);
Michael Kolb8872c232013-01-29 10:33:22 -08001351
1352 cropIntent.setData(tempUri);
1353 cropIntent.putExtras(newExtras);
1354
1355 mActivity.startActivityForResult(cropIntent, REQUEST_CROP);
1356 }
1357 }
1358
Michael Kolb8872c232013-01-29 10:33:22 -08001359 @Override
1360 public void onShutterButtonFocus(boolean pressed) {
Michael Kolbd6954f32013-03-08 20:43:01 -08001361 if (mPaused || mUI.collapseCameraControls()
Michael Kolb8872c232013-01-29 10:33:22 -08001362 || (mCameraState == SNAPSHOT_IN_PROGRESS)
1363 || (mCameraState == PREVIEW_STOPPED)) return;
1364
1365 // Do not do focus if there is not enough storage.
1366 if (pressed && !canTakePicture()) return;
1367
1368 if (pressed) {
Michael Kolb8872c232013-01-29 10:33:22 -08001369 mFocusManager.onShutterDown();
1370 } else {
Doris Liuda50e052013-02-07 14:36:32 -08001371 // for countdown mode, we need to postpone the shutter release
1372 // i.e. lock the focus during countdown.
Michael Kolbd6954f32013-03-08 20:43:01 -08001373 if (!mUI.isCountingDown()) {
Doris Liuda50e052013-02-07 14:36:32 -08001374 mFocusManager.onShutterUp();
1375 }
Michael Kolb8872c232013-01-29 10:33:22 -08001376 }
1377 }
1378
1379 @Override
1380 public void onShutterButtonClick() {
Michael Kolbd6954f32013-03-08 20:43:01 -08001381 if (mPaused || mUI.collapseCameraControls()
Michael Kolb8872c232013-01-29 10:33:22 -08001382 || (mCameraState == SWITCHING_CAMERA)
1383 || (mCameraState == PREVIEW_STOPPED)) return;
1384
1385 // Do not take the picture if there is not enough storage.
Angus Kong2dcc0a92013-09-25 13:00:08 -07001386 if (mActivity.getStorageSpaceBytes() <= Storage.LOW_STORAGE_THRESHOLD_BYTES) {
Michael Kolb8872c232013-01-29 10:33:22 -08001387 Log.i(TAG, "Not enough space or storage not ready. remaining="
Angus Kong2dcc0a92013-09-25 13:00:08 -07001388 + mActivity.getStorageSpaceBytes());
Michael Kolb8872c232013-01-29 10:33:22 -08001389 return;
1390 }
1391 Log.v(TAG, "onShutterButtonClick: mCameraState=" + mCameraState);
1392
Angus Kongb50b5cb2013-08-09 14:55:20 -07001393 if (mSceneMode == CameraUtil.SCENE_MODE_HDR) {
Doris Liu6432cd62013-06-13 17:20:31 -07001394 mUI.hideSwitcher();
1395 mUI.setSwipingEnabled(false);
Doris Liu9cdfe002013-04-16 09:50:56 -07001396 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301397
1398 //Need to disable focus for ZSL mode
1399 if(mSnapshotMode == CameraInfo.CAMERA_SUPPORT_MODE_ZSL) {
1400 mFocusManager.setZslEnable(true);
1401 } else {
1402 mFocusManager.setZslEnable(false);
1403 }
1404
Michael Kolb8872c232013-01-29 10:33:22 -08001405 // If the user wants to do a snapshot while the previous one is still
1406 // in progress, remember the fact and do it after we finish the previous
1407 // one and re-start the preview. Snapshot in progress also includes the
1408 // state that autofocus is focusing and a picture will be taken when
1409 // focus callback arrives.
1410 if ((mFocusManager.isFocusingSnapOnFinish() || mCameraState == SNAPSHOT_IN_PROGRESS)
1411 && !mIsImageCaptureIntent) {
1412 mSnapshotOnIdle = true;
1413 return;
1414 }
1415
1416 String timer = mPreferences.getString(
1417 CameraSettings.KEY_TIMER,
1418 mActivity.getString(R.string.pref_camera_timer_default));
1419 boolean playSound = mPreferences.getString(CameraSettings.KEY_TIMER_SOUND_EFFECTS,
1420 mActivity.getString(R.string.pref_camera_timer_sound_default))
1421 .equals(mActivity.getString(R.string.setting_on_value));
1422
1423 int seconds = Integer.parseInt(timer);
1424 // When shutter button is pressed, check whether the previous countdown is
1425 // finished. If not, cancel the previous countdown and start a new one.
Michael Kolbd6954f32013-03-08 20:43:01 -08001426 if (mUI.isCountingDown()) {
1427 mUI.cancelCountDown();
1428 }
1429 if (seconds > 0) {
1430 mUI.startCountDown(seconds, playSound);
Michael Kolb8872c232013-01-29 10:33:22 -08001431 } else {
Dan Aminzade92ae10e2013-08-13 14:44:25 -07001432 mSnapshotOnIdle = false;
1433 mFocusManager.doSnap();
Michael Kolb8872c232013-01-29 10:33:22 -08001434 }
1435 }
1436
1437 @Override
1438 public void installIntentFilter() {
Sascha Haeberling4de78802013-10-06 18:07:07 -07001439 // Do nothing.
Michael Kolb8872c232013-01-29 10:33:22 -08001440 }
1441
1442 @Override
1443 public boolean updateStorageHintOnResume() {
1444 return mFirstTimeInitialized;
1445 }
1446
1447 @Override
Michael Kolb8872c232013-01-29 10:33:22 -08001448 public void onResumeBeforeSuper() {
1449 mPaused = false;
1450 }
1451
Angus Kong4f795b82013-09-16 14:25:35 -07001452 /**
1453 * Opens the camera device.
1454 *
1455 * @return Whether the camera was opened successfully.
1456 */
1457 private boolean prepareCamera() {
1458 // We need to check whether the activity is paused before long
1459 // operations to ensure that onPause() can be done ASAP.
1460 mCameraDevice = CameraUtil.openCamera(
1461 mActivity, mCameraId, mHandler,
1462 mActivity.getCameraOpenErrorCallback());
1463 if (mCameraDevice == null) {
1464 Log.e(TAG, "Failed to open camera:" + mCameraId);
1465 return false;
Angus Kongdcccc512013-08-08 17:06:03 -07001466 }
Angus Kong4f795b82013-09-16 14:25:35 -07001467 mParameters = mCameraDevice.getParameters();
1468
1469 initializeCapabilities();
1470 if (mFocusManager == null) initializeFocusManager();
1471 setCameraParameters(UPDATE_PARAM_ALL);
1472 mHandler.sendEmptyMessage(CAMERA_OPEN_DONE);
1473 mCameraPreviewParamsReady = true;
1474 startPreview();
1475 mOnResumeTime = SystemClock.uptimeMillis();
1476 checkDisplayRotation();
1477 return true;
Angus Kongdcccc512013-08-08 17:06:03 -07001478 }
1479
1480
Michael Kolb8872c232013-01-29 10:33:22 -08001481 @Override
1482 public void onResumeAfterSuper() {
1483 if (mOpenCameraFail || mCameraDisabled) return;
1484
1485 mJpegPictureCallbackTime = 0;
1486 mZoomValue = 0;
Angus Kongdcccc512013-08-08 17:06:03 -07001487 resetExposureCompensation();
Angus Kong4f795b82013-09-16 14:25:35 -07001488 if (!prepareCamera()) {
1489 // Camera failure.
1490 return;
1491 }
Michael Kolb8872c232013-01-29 10:33:22 -08001492
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301493 if (mSkinToneSeekBar != true)
1494 {
1495 Log.v(TAG, "Send tone bar: mSkinToneSeekBar = " + mSkinToneSeekBar);
1496 mHandler.sendEmptyMessage(SET_SKIN_TONE_FACTOR);
1497 }
Michael Kolb8872c232013-01-29 10:33:22 -08001498 // If first time initialization is not finished, put it in the
1499 // message queue.
1500 if (!mFirstTimeInitialized) {
1501 mHandler.sendEmptyMessage(FIRST_TIME_INIT);
1502 } else {
1503 initializeSecondTime();
1504 }
Doris Liu59390062013-10-10 17:20:56 -07001505 mUI.initDisplayChangeListener();
Michael Kolb8872c232013-01-29 10:33:22 -08001506 keepScreenOnAwhile();
1507
Bobby Georgescu0a7dd572013-03-12 22:45:17 -07001508 UsageStatistics.onContentViewChanged(
1509 UsageStatistics.COMPONENT_CAMERA, "PhotoModule");
Angus Kong0d00a892013-03-26 11:40:40 -07001510
1511 Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
1512 if (gsensor != null) {
1513 mSensorManager.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_NORMAL);
1514 }
1515
1516 Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
1517 if (msensor != null) {
1518 mSensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_NORMAL);
1519 }
Michael Kolb8872c232013-01-29 10:33:22 -08001520 }
1521
Michael Kolb8872c232013-01-29 10:33:22 -08001522 @Override
1523 public void onPauseBeforeSuper() {
1524 mPaused = true;
Angus Kong0d00a892013-03-26 11:40:40 -07001525 Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
1526 if (gsensor != null) {
1527 mSensorManager.unregisterListener(this, gsensor);
1528 }
1529
1530 Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
1531 if (msensor != null) {
1532 mSensorManager.unregisterListener(this, msensor);
1533 }
Michael Kolb8872c232013-01-29 10:33:22 -08001534 }
1535
1536 @Override
1537 public void onPauseAfterSuper() {
Michael Kolb8872c232013-01-29 10:33:22 -08001538 // When camera is started from secure lock screen for the first time
1539 // after screen on, the activity gets onCreate->onResume->onPause->onResume.
1540 // To reduce the latency, keep the camera for a short time so it does
1541 // not need to be opened again.
1542 if (mCameraDevice != null && mActivity.isSecureCamera()
Angus Kong6a8e8a12013-07-19 14:55:07 -07001543 && CameraActivity.isFirstStartAfterScreenOn()) {
1544 CameraActivity.resetFirstStartAfterScreenOn();
Michael Kolb8872c232013-01-29 10:33:22 -08001545 CameraHolder.instance().keep(KEEP_CAMERA_TIMEOUT);
1546 }
1547 // Reset the focus first. Camera CTS does not guarantee that
1548 // cancelAutoFocus is allowed after preview stops.
1549 if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) {
1550 mCameraDevice.cancelAutoFocus();
1551 }
1552 stopPreview();
Michael Kolb8872c232013-01-29 10:33:22 -08001553
Angus Kongce5480e2013-01-29 17:43:48 -08001554 mNamedImages = null;
Michael Kolb8872c232013-01-29 10:33:22 -08001555
1556 if (mLocationManager != null) mLocationManager.recordLocation(false);
1557
1558 // If we are in an image capture intent and has taken
1559 // a picture, we just clear it in onPause.
1560 mJpegImageData = null;
1561
Angus Kongdcccc512013-08-08 17:06:03 -07001562 // Remove the messages and runnables in the queue.
1563 mHandler.removeCallbacksAndMessages(null);
Michael Kolb8872c232013-01-29 10:33:22 -08001564
Michael Kolbd6954f32013-03-08 20:43:01 -08001565 closeCamera();
1566
1567 resetScreenOn();
1568 mUI.onPause();
1569
Michael Kolb8872c232013-01-29 10:33:22 -08001570 mPendingSwitchCameraId = -1;
1571 if (mFocusManager != null) mFocusManager.removeMessages();
Angus Kong86d36312013-01-31 18:22:44 -08001572 MediaSaveService s = mActivity.getMediaSaveService();
1573 if (s != null) {
1574 s.setListener(null);
1575 }
Doris Liu59390062013-10-10 17:20:56 -07001576 mUI.removeDisplayChangeListener();
Michael Kolb8872c232013-01-29 10:33:22 -08001577 }
1578
Michael Kolb8872c232013-01-29 10:33:22 -08001579 /**
1580 * The focus manager is the first UI related element to get initialized,
1581 * and it requires the RenderOverlay, so initialize it here
1582 */
1583 private void initializeFocusManager() {
1584 // Create FocusManager object. startPreview needs it.
Michael Kolb8872c232013-01-29 10:33:22 -08001585 // if mFocusManager not null, reuse it
1586 // otherwise create a new instance
1587 if (mFocusManager != null) {
1588 mFocusManager.removeMessages();
1589 } else {
1590 CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
Doris Liu29da2db2013-08-28 14:28:45 -07001591 mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
Michael Kolb8872c232013-01-29 10:33:22 -08001592 String[] defaultFocusModes = mActivity.getResources().getStringArray(
1593 R.array.pref_camera_focusmode_default_array);
1594 mFocusManager = new FocusOverlayManager(mPreferences, defaultFocusModes,
Doris Liu29da2db2013-08-28 14:28:45 -07001595 mInitialParams, this, mMirror,
Michael Kolbd6954f32013-03-08 20:43:01 -08001596 mActivity.getMainLooper(), mUI);
Michael Kolb8872c232013-01-29 10:33:22 -08001597 }
1598 }
1599
Michael Kolb8872c232013-01-29 10:33:22 -08001600 @Override
1601 public void onConfigurationChanged(Configuration newConfig) {
1602 Log.v(TAG, "onConfigurationChanged");
1603 setDisplayOrientation();
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +05301604 resizeForPreviewAspectRatio();
Michael Kolb8872c232013-01-29 10:33:22 -08001605 }
1606
1607 @Override
Doris Liu6432cd62013-06-13 17:20:31 -07001608 public void updateCameraOrientation() {
Angus Kongb50b5cb2013-08-09 14:55:20 -07001609 if (mDisplayRotation != CameraUtil.getDisplayRotation(mActivity)) {
Doris Liu6432cd62013-06-13 17:20:31 -07001610 setDisplayOrientation();
1611 }
1612 }
1613
1614 @Override
Michael Kolb8872c232013-01-29 10:33:22 -08001615 public void onActivityResult(
1616 int requestCode, int resultCode, Intent data) {
1617 switch (requestCode) {
1618 case REQUEST_CROP: {
1619 Intent intent = new Intent();
1620 if (data != null) {
1621 Bundle extras = data.getExtras();
1622 if (extras != null) {
1623 intent.putExtras(extras);
1624 }
1625 }
1626 mActivity.setResultEx(resultCode, intent);
1627 mActivity.finish();
1628
1629 File path = mActivity.getFileStreamPath(sTempCropFilename);
1630 path.delete();
1631
1632 break;
1633 }
1634 }
1635 }
1636
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301637 protected CameraManager.CameraProxy getCamera() {
1638 return mCameraDevice;
1639 }
1640
Michael Kolb8872c232013-01-29 10:33:22 -08001641 private boolean canTakePicture() {
Angus Kong2dcc0a92013-09-25 13:00:08 -07001642 return isCameraIdle() && (mActivity.getStorageSpaceBytes() > Storage.LOW_STORAGE_THRESHOLD_BYTES);
Michael Kolb8872c232013-01-29 10:33:22 -08001643 }
1644
1645 @Override
1646 public void autoFocus() {
1647 mFocusStartTime = System.currentTimeMillis();
Angus Kong9ef99252013-07-18 18:04:19 -07001648 mCameraDevice.autoFocus(mHandler, mAutoFocusCallback);
Michael Kolb8872c232013-01-29 10:33:22 -08001649 setCameraState(FOCUSING);
1650 }
1651
1652 @Override
1653 public void cancelAutoFocus() {
1654 mCameraDevice.cancelAutoFocus();
1655 setCameraState(IDLE);
1656 setCameraParameters(UPDATE_PARAM_PREFERENCE);
1657 }
1658
1659 // Preview area is touched. Handle touch focus.
1660 @Override
1661 public void onSingleTapUp(View view, int x, int y) {
1662 if (mPaused || mCameraDevice == null || !mFirstTimeInitialized
1663 || mCameraState == SNAPSHOT_IN_PROGRESS
1664 || mCameraState == SWITCHING_CAMERA
1665 || mCameraState == PREVIEW_STOPPED) {
1666 return;
1667 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301668 //If Touch AF/AEC is disabled in UI, return
1669 if(this.mTouchAfAecFlag == false) {
1670 return;
1671 }
Michael Kolb8872c232013-01-29 10:33:22 -08001672 // Check if metering area or focus area is supported.
1673 if (!mFocusAreaSupported && !mMeteringAreaSupported) return;
1674 mFocusManager.onSingleTapUp(x, y);
1675 }
1676
1677 @Override
1678 public boolean onBackPressed() {
Michael Kolbd6954f32013-03-08 20:43:01 -08001679 return mUI.onBackPressed();
Michael Kolb8872c232013-01-29 10:33:22 -08001680 }
1681
1682 @Override
1683 public boolean onKeyDown(int keyCode, KeyEvent event) {
1684 switch (keyCode) {
Dan Aminzade92ae10e2013-08-13 14:44:25 -07001685 case KeyEvent.KEYCODE_VOLUME_UP:
1686 case KeyEvent.KEYCODE_VOLUME_DOWN:
1687 case KeyEvent.KEYCODE_FOCUS:
1688 if (/*TODO: mActivity.isInCameraApp() &&*/ mFirstTimeInitialized) {
1689 if (event.getRepeatCount() == 0) {
1690 onShutterButtonFocus(true);
1691 }
1692 return true;
1693 }
1694 return false;
1695 case KeyEvent.KEYCODE_CAMERA:
1696 if (mFirstTimeInitialized && event.getRepeatCount() == 0) {
1697 onShutterButtonClick();
Michael Kolb8872c232013-01-29 10:33:22 -08001698 }
1699 return true;
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301700 case KeyEvent.KEYCODE_DPAD_LEFT:
1701 if ( (mCameraState != PREVIEW_STOPPED) &&
1702 (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING) &&
1703 (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING_SNAP_ON_FINISH) ) {
1704 if (mbrightness > MINIMUM_BRIGHTNESS) {
1705 mbrightness-=mbrightness_step;
1706 /* Set the "luma-adaptation" parameter */
1707 mParameters = mCameraDevice.getParameters();
1708 mParameters.set("luma-adaptation", String.valueOf(mbrightness));
1709 mCameraDevice.setParameters(mParameters);
1710 }
1711 brightnessProgressBar.setProgress(mbrightness);
1712 brightnessProgressBar.setVisibility(View.VISIBLE);
1713 }
1714 break;
1715 case KeyEvent.KEYCODE_DPAD_RIGHT:
1716 if ( (mCameraState != PREVIEW_STOPPED) &&
1717 (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING) &&
1718 (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING_SNAP_ON_FINISH) ) {
1719 if (mbrightness < MAXIMUM_BRIGHTNESS) {
1720 mbrightness+=mbrightness_step;
1721 /* Set the "luma-adaptation" parameter */
1722 mParameters = mCameraDevice.getParameters();
1723 mParameters.set("luma-adaptation", String.valueOf(mbrightness));
1724 mCameraDevice.setParameters(mParameters);
1725 }
1726 brightnessProgressBar.setProgress(mbrightness);
1727 brightnessProgressBar.setVisibility(View.VISIBLE);
1728 }
1729 break;
Dan Aminzade92ae10e2013-08-13 14:44:25 -07001730 case KeyEvent.KEYCODE_DPAD_CENTER:
1731 // If we get a dpad center event without any focused view, move
1732 // the focus to the shutter button and press it.
1733 if (mFirstTimeInitialized && event.getRepeatCount() == 0) {
1734 // Start auto-focus immediately to reduce shutter lag. After
1735 // the shutter button gets the focus, onShutterButtonFocus()
1736 // will be called again but it is fine.
1737 onShutterButtonFocus(true);
1738 mUI.pressShutterButton();
1739 }
1740 return true;
Michael Kolb8872c232013-01-29 10:33:22 -08001741 }
1742 return false;
1743 }
1744
1745 @Override
1746 public boolean onKeyUp(int keyCode, KeyEvent event) {
1747 switch (keyCode) {
Dan Aminzade92ae10e2013-08-13 14:44:25 -07001748 case KeyEvent.KEYCODE_VOLUME_UP:
1749 case KeyEvent.KEYCODE_VOLUME_DOWN:
1750 if (/*mActivity.isInCameraApp() && */ mFirstTimeInitialized) {
1751 onShutterButtonClick();
1752 return true;
1753 }
1754 return false;
1755 case KeyEvent.KEYCODE_FOCUS:
1756 if (mFirstTimeInitialized) {
1757 onShutterButtonFocus(false);
1758 }
Michael Kolb8872c232013-01-29 10:33:22 -08001759 return true;
Michael Kolb8872c232013-01-29 10:33:22 -08001760 }
1761 return false;
1762 }
1763
Michael Kolb8872c232013-01-29 10:33:22 -08001764 private void closeCamera() {
1765 if (mCameraDevice != null) {
1766 mCameraDevice.setZoomChangeListener(null);
Sascha Haeberling638e6f02013-09-18 14:28:51 -07001767 mCameraDevice.setFaceDetectionCallback(null, null);
Michael Kolb8872c232013-01-29 10:33:22 -08001768 mCameraDevice.setErrorCallback(null);
1769 CameraHolder.instance().release();
1770 mFaceDetectionStarted = false;
1771 mCameraDevice = null;
1772 setCameraState(PREVIEW_STOPPED);
1773 mFocusManager.onCameraReleased();
1774 }
1775 }
1776
1777 private void setDisplayOrientation() {
Angus Kongb50b5cb2013-08-09 14:55:20 -07001778 mDisplayRotation = CameraUtil.getDisplayRotation(mActivity);
1779 mDisplayOrientation = CameraUtil.getDisplayOrientation(mDisplayRotation, mCameraId);
Doris Liu6432cd62013-06-13 17:20:31 -07001780 mCameraDisplayOrientation = mDisplayOrientation;
Michael Kolbd6954f32013-03-08 20:43:01 -08001781 mUI.setDisplayOrientation(mDisplayOrientation);
Michael Kolb8872c232013-01-29 10:33:22 -08001782 if (mFocusManager != null) {
1783 mFocusManager.setDisplayOrientation(mDisplayOrientation);
1784 }
Doris Liu6432cd62013-06-13 17:20:31 -07001785 // Change the camera display orientation
1786 if (mCameraDevice != null) {
1787 mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation);
1788 }
Michael Kolb8872c232013-01-29 10:33:22 -08001789 }
1790
Sascha Haeberlingddef7792013-08-13 14:41:10 -07001791 /** Only called by UI thread. */
Michael Kolb8872c232013-01-29 10:33:22 -08001792 private void setupPreview() {
1793 mFocusManager.resetTouchFocus();
1794 startPreview();
Michael Kolb8872c232013-01-29 10:33:22 -08001795 }
1796
Angus Kongdcccc512013-08-08 17:06:03 -07001797 // This can only be called by UI Thread.
Michael Kolb8872c232013-01-29 10:33:22 -08001798 private void startPreview() {
Angus Kongdcccc512013-08-08 17:06:03 -07001799 if (mPaused) {
1800 return;
1801 }
1802 SurfaceTexture st = mUI.getSurfaceTexture();
1803 if (st == null) {
1804 Log.w(TAG, "startPreview: surfaceTexture is not ready.");
1805 return;
1806 }
1807 if (!mCameraPreviewParamsReady) {
1808 Log.w(TAG, "startPreview: parameters for preview is not ready.");
1809 return;
1810 }
Michael Kolb8872c232013-01-29 10:33:22 -08001811 mCameraDevice.setErrorCallback(mErrorCallback);
1812
1813 // ICS camera frameworks has a bug. Face detection state is not cleared
1814 // after taking a picture. Stop the preview to work around it. The bug
1815 // was fixed in JB.
1816 if (mCameraState != PREVIEW_STOPPED) stopPreview();
1817
1818 setDisplayOrientation();
1819
1820 if (!mSnapshotOnIdle) {
1821 // If the focus mode is continuous autofocus, call cancelAutoFocus to
1822 // resume it because it may have been paused by autoFocus call.
Angus Kongb50b5cb2013-08-09 14:55:20 -07001823 if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode())) {
Michael Kolb8872c232013-01-29 10:33:22 -08001824 mCameraDevice.cancelAutoFocus();
1825 }
1826 mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
1827 }
1828 setCameraParameters(UPDATE_PARAM_ALL);
Doris Liu6432cd62013-06-13 17:20:31 -07001829 // Let UI set its expected aspect ratio
Angus Kongdcccc512013-08-08 17:06:03 -07001830 mCameraDevice.setPreviewTexture(st);
Michael Kolb8872c232013-01-29 10:33:22 -08001831
1832 Log.v(TAG, "startPreview");
Angus Kong9ef99252013-07-18 18:04:19 -07001833 mCameraDevice.startPreview();
Michael Kolb8872c232013-01-29 10:33:22 -08001834 mFocusManager.onPreviewStarted();
Angus Kongdcccc512013-08-08 17:06:03 -07001835 onPreviewStarted();
Michael Kolb8872c232013-01-29 10:33:22 -08001836
1837 if (mSnapshotOnIdle) {
1838 mHandler.post(mDoSnapRunnable);
1839 }
1840 }
1841
Michael Kolbd6954f32013-03-08 20:43:01 -08001842 @Override
1843 public void stopPreview() {
Michael Kolb8872c232013-01-29 10:33:22 -08001844 if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) {
1845 Log.v(TAG, "stopPreview");
1846 mCameraDevice.stopPreview();
Michael Kolb8872c232013-01-29 10:33:22 -08001847 }
1848 setCameraState(PREVIEW_STOPPED);
1849 if (mFocusManager != null) mFocusManager.onPreviewStopped();
1850 }
1851
1852 @SuppressWarnings("deprecation")
1853 private void updateCameraParametersInitialize() {
1854 // Reset preview frame rate to the maximum because it may be lowered by
1855 // video camera application.
ztenghui16a35202013-09-23 11:35:36 -07001856 int[] fpsRange = CameraUtil.getPhotoPreviewFpsRange(mParameters);
1857 if (fpsRange != null && fpsRange.length > 0) {
Doris Liu6432cd62013-06-13 17:20:31 -07001858 mParameters.setPreviewFpsRange(
1859 fpsRange[Parameters.PREVIEW_FPS_MIN_INDEX],
1860 fpsRange[Parameters.PREVIEW_FPS_MAX_INDEX]);
Michael Kolb8872c232013-01-29 10:33:22 -08001861 }
1862
Angus Kongb50b5cb2013-08-09 14:55:20 -07001863 mParameters.set(CameraUtil.RECORDING_HINT, CameraUtil.FALSE);
Michael Kolb8872c232013-01-29 10:33:22 -08001864
1865 // Disable video stabilization. Convenience methods not available in API
1866 // level <= 14
1867 String vstabSupported = mParameters.get("video-stabilization-supported");
1868 if ("true".equals(vstabSupported)) {
1869 mParameters.set("video-stabilization", "false");
1870 }
1871 }
1872
1873 private void updateCameraParametersZoom() {
1874 // Set zoom.
1875 if (mParameters.isZoomSupported()) {
Alok Kediya5213f272013-10-02 17:51:19 +05301876 Parameters p = mCameraDevice.getParameters();
1877 mZoomValue = p.getZoom();
Michael Kolb8872c232013-01-29 10:33:22 -08001878 mParameters.setZoom(mZoomValue);
1879 }
1880 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301881 private boolean needRestart() {
1882 mRestartPreview = false;
1883 String zsl = mPreferences.getString(CameraSettings.KEY_ZSL,
1884 mActivity.getString(R.string.pref_camera_zsl_default));
1885 if(zsl.equals("on") && mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_ZSL
1886 && mCameraState != PREVIEW_STOPPED) {
1887 //Switch on ZSL Camera mode
1888 Log.v(TAG, "Switching to ZSL Camera Mode. Restart Preview");
1889 mRestartPreview = true;
1890 return mRestartPreview;
1891 }
1892 if(zsl.equals("off") && mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_NONZSL
1893 && mCameraState != PREVIEW_STOPPED) {
1894 //Switch on Normal Camera mode
1895 Log.v(TAG, "Switching to Normal Camera Mode. Restart Preview");
1896 mRestartPreview = true;
1897 return mRestartPreview;
1898 }
1899 return mRestartPreview;
1900 }
1901
1902 private void qcomUpdateCameraParametersPreference() {
1903 //qcom Related Parameter update
1904 //Set Brightness.
1905 mParameters.set("luma-adaptation", String.valueOf(mbrightness));
1906
1907 if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) {
1908 // Set Touch AF/AEC parameter.
1909 String touchAfAec = mPreferences.getString(
1910 CameraSettings.KEY_TOUCH_AF_AEC,
1911 mActivity.getString(R.string.pref_camera_touchafaec_default));
1912 if (CameraUtil.isSupported(touchAfAec, mParameters.getSupportedTouchAfAec())) {
Alok Kediya5fdf67e2013-10-02 18:00:14 +05301913 mCurrTouchAfAec = touchAfAec;
Alok Kediya0dc64ff2013-09-27 20:22:45 +05301914 mParameters.setTouchAfAec(touchAfAec);
1915 }
1916 } else {
1917 mParameters.setTouchAfAec(mParameters.TOUCH_AF_AEC_OFF);
1918 mFocusManager.resetTouchFocus();
1919 }
1920 try {
1921 if(mParameters.getTouchAfAec().equals(mParameters.TOUCH_AF_AEC_ON))
1922 this.mTouchAfAecFlag = true;
1923 else
1924 this.mTouchAfAecFlag = false;
1925 } catch(Exception e){
1926 Log.e(TAG, "Handled NULL pointer Exception");
1927 }
1928
1929 // Set Picture Format
1930 // Picture Formats specified in UI should be consistent with
1931 // PIXEL_FORMAT_JPEG and PIXEL_FORMAT_RAW constants
1932 String pictureFormat = mPreferences.getString(
1933 CameraSettings.KEY_PICTURE_FORMAT,
1934 mActivity.getString(R.string.pref_camera_picture_format_default));
1935 mParameters.set(KEY_PICTURE_FORMAT, pictureFormat);
1936
1937 // Set JPEG quality.
1938 String jpegQuality = mPreferences.getString(
1939 CameraSettings.KEY_JPEG_QUALITY,
1940 mActivity.getString(R.string.pref_camera_jpegquality_default));
1941 //mUnsupportedJpegQuality = false;
1942 Size pic_size = mParameters.getPictureSize();
1943 if (pic_size == null) {
1944 Log.e(TAG, "error getPictureSize: size is null");
1945 }
1946 else{
1947 if("100".equals(jpegQuality) && (pic_size.width >= 3200)){
1948 //mUnsupportedJpegQuality = true;
1949 }else {
1950 mParameters.setJpegQuality(JpegEncodingQualityMappings.getQualityNumber(jpegQuality));
1951 }
1952 }
1953
1954 // Set Selectable Zone Af parameter.
1955 String selectableZoneAf = mPreferences.getString(
1956 CameraSettings.KEY_SELECTABLE_ZONE_AF,
1957 mActivity.getString(R.string.pref_camera_selectablezoneaf_default));
1958 List<String> str = mParameters.getSupportedSelectableZoneAf();
1959 if (CameraUtil.isSupported(selectableZoneAf, mParameters.getSupportedSelectableZoneAf())) {
1960 mParameters.setSelectableZoneAf(selectableZoneAf);
1961 }
1962
1963 // Set wavelet denoise mode
1964 if (mParameters.getSupportedDenoiseModes() != null) {
1965 String Denoise = mPreferences.getString( CameraSettings.KEY_DENOISE,
1966 mActivity.getString(R.string.pref_camera_denoise_default));
1967 mParameters.setDenoise(Denoise);
1968 }
1969 // Set Redeye Reduction
1970 String redeyeReduction = mPreferences.getString(
1971 CameraSettings.KEY_REDEYE_REDUCTION,
1972 mActivity.getString(R.string.pref_camera_redeyereduction_default));
1973 if (CameraUtil.isSupported(redeyeReduction,
1974 mParameters.getSupportedRedeyeReductionModes())) {
1975 mParameters.setRedeyeReductionMode(redeyeReduction);
1976 }
1977 // Set ISO parameter
1978 String iso = mPreferences.getString(
1979 CameraSettings.KEY_ISO,
1980 mActivity.getString(R.string.pref_camera_iso_default));
1981 if (CameraUtil.isSupported(iso,
1982 mParameters.getSupportedIsoValues())) {
1983 mParameters.setISOValue(iso);
1984 }
1985 // Set color effect parameter.
1986 String colorEffect = mPreferences.getString(
1987 CameraSettings.KEY_COLOR_EFFECT,
1988 mActivity.getString(R.string.pref_camera_coloreffect_default));
1989 Log.v(TAG, "Color effect value =" + colorEffect);
1990 if (CameraUtil.isSupported(colorEffect, mParameters.getSupportedColorEffects())) {
1991 mParameters.setColorEffect(colorEffect);
1992 }
1993 //Set Saturation
1994 String saturationStr = mPreferences.getString(
1995 CameraSettings.KEY_SATURATION,
1996 mActivity.getString(R.string.pref_camera_saturation_default));
1997 int saturation = Integer.parseInt(saturationStr);
1998 Log.v(TAG, "Saturation value =" + saturation);
1999 if((0 <= saturation) && (saturation <= mParameters.getMaxSaturation())){
2000 mParameters.setSaturation(saturation);
2001 }
2002 // Set contrast parameter.
2003 String contrastStr = mPreferences.getString(
2004 CameraSettings.KEY_CONTRAST,
2005 mActivity.getString(R.string.pref_camera_contrast_default));
2006 int contrast = Integer.parseInt(contrastStr);
2007 Log.v(TAG, "Contrast value =" +contrast);
2008 if((0 <= contrast) && (contrast <= mParameters.getMaxContrast())){
2009 mParameters.setContrast(contrast);
2010 }
2011 // Set sharpness parameter
2012 String sharpnessStr = mPreferences.getString(
2013 CameraSettings.KEY_SHARPNESS,
2014 mActivity.getString(R.string.pref_camera_sharpness_default));
2015 int sharpness = Integer.parseInt(sharpnessStr) *
2016 (mParameters.getMaxSharpness()/MAX_SHARPNESS_LEVEL);
2017 Log.v(TAG, "Sharpness value =" + sharpness);
2018 if((0 <= sharpness) && (sharpness <= mParameters.getMaxSharpness())){
2019 mParameters.setSharpness(sharpness);
2020 }
Alok Kediya7e531092013-09-28 16:30:15 +05302021 // Set Face Recognition
2022 String faceRC = mPreferences.getString(
2023 CameraSettings.KEY_FACE_RECOGNITION,
2024 mActivity.getString(R.string.pref_camera_facerc_default));
2025 Log.v(TAG, "Face Recognition value = " + faceRC);
2026 if (CameraUtil.isSupported(faceRC,
2027 CameraSettings.getSupportedFaceRecognitionModes(mParameters))) {
2028 mParameters.set(CameraSettings.KEY_QC_FACE_RECOGNITION, faceRC);
2029 }
Alok Kediyac862c8b2013-09-28 16:23:35 +05302030 // Set AE Bracketing
2031 String aeBracketing = mPreferences.getString(
2032 CameraSettings.KEY_AE_BRACKET_HDR,
2033 mActivity.getString(R.string.pref_camera_ae_bracket_hdr_default));
2034 Log.v(TAG, "AE Bracketing value =" + aeBracketing);
2035 if (CameraUtil.isSupported(aeBracketing,
2036 CameraSettings.getSupportedAEBracketingModes(mParameters))) {
2037 mParameters.set(CameraSettings.KEY_QC_AE_BRACKETING, aeBracketing);
2038 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302039 // Set auto exposure parameter.
2040 String autoExposure = mPreferences.getString(
2041 CameraSettings.KEY_AUTOEXPOSURE,
2042 mActivity.getString(R.string.pref_camera_autoexposure_default));
2043 Log.v(TAG, "autoExposure value =" + autoExposure);
2044 if (CameraUtil.isSupported(autoExposure, mParameters.getSupportedAutoexposure())) {
2045 mParameters.setAutoExposure(autoExposure);
2046 }
2047
2048 // Set anti banding parameter.
2049 String antiBanding = mPreferences.getString(
2050 CameraSettings.KEY_ANTIBANDING,
2051 mActivity.getString(R.string.pref_camera_antibanding_default));
2052 Log.v(TAG, "antiBanding value =" + antiBanding);
2053 if (CameraUtil.isSupported(antiBanding, mParameters.getSupportedAntibanding())) {
2054 mParameters.setAntibanding(antiBanding);
2055 }
2056
2057 String zsl = mPreferences.getString(CameraSettings.KEY_ZSL,
2058 mActivity.getString(R.string.pref_camera_zsl_default));
2059 String hdr = mPreferences.getString(CameraSettings.KEY_CAMERA_HDR,
2060 mActivity.getString(R.string.pref_camera_hdr_default));
2061 mParameters.setZSLMode(zsl);
2062 if(zsl.equals("on")) {
2063 //Switch on ZSL Camera mode
2064 mSnapshotMode = CameraInfo.CAMERA_SUPPORT_MODE_ZSL;
2065 mParameters.setCameraMode(1);
2066 mFocusManager.setZslEnable(true);
2067
2068 // Currently HDR is not supported under ZSL mode
2069 Editor editor = mPreferences.edit();
2070 editor.putString(CameraSettings.KEY_AE_BRACKET_HDR, mActivity.getString(R.string.setting_off_value));
2071
2072 //Raw picture format is not supported under ZSL mode
2073 editor.putString(CameraSettings.KEY_PICTURE_FORMAT, mActivity.getString(R.string.pref_camera_picture_format_value_jpeg));
2074 editor.apply();
2075
2076 if(!pictureFormat.equals(PIXEL_FORMAT_JPEG)) {
2077 mActivity.runOnUiThread(new Runnable() {
2078 public void run() {
2079 Toast.makeText(mActivity, R.string.error_app_unsupported_raw,
2080 Toast.LENGTH_SHORT).show();
2081 }
2082 });
2083 }
2084
2085 if(hdr.equals(mActivity.getString(R.string.setting_on_value))) {
2086 mActivity.runOnUiThread(new Runnable() {
2087 public void run() {
2088 Toast.makeText(mActivity, R.string.error_app_unsupported_hdr_zsl,
2089 Toast.LENGTH_SHORT).show();
2090 }
2091 });
2092 }
2093 } else if(zsl.equals("off")) {
2094 mSnapshotMode = CameraInfo.CAMERA_SUPPORT_MODE_NONZSL;
2095 mParameters.setCameraMode(0);
2096 mFocusManager.setZslEnable(false);
2097 }
2098 // Set face detetction parameter.
2099 String faceDetection = mPreferences.getString(
2100 CameraSettings.KEY_FACE_DETECTION,
2101 mActivity.getString(R.string.pref_camera_facedetection_default));
2102
2103 if (CameraUtil.isSupported(faceDetection, mParameters.getSupportedFaceDetectionModes())) {
2104 mParameters.setFaceDetectionMode(faceDetection);
2105 if(faceDetection.equals("on") && mFaceDetectionEnabled == false) {
2106 mFaceDetectionEnabled = true;
2107 startFaceDetection();
2108 }
2109 if(faceDetection.equals("off") && mFaceDetectionEnabled == true) {
2110 stopFaceDetection();
2111 mFaceDetectionEnabled = false;
2112 }
2113 }
2114 //Set Skin Tone Correction factor
2115 Log.v(TAG, "set tone bar: mSceneMode = " + mSceneMode);
2116 if(mSeekBarInitialized == true)
2117 mHandler.sendEmptyMessage(SET_SKIN_TONE_FACTOR);
SanthoshHEee63d7f2013-09-05 14:43:35 +05302118 // skin tone ie enabled only for auto,party and portrait BSM
2119 // when color effects are not enabled
2120 if((Parameters.SCENE_MODE_PARTY.equals(mSceneMode) ||
2121 Parameters.SCENE_MODE_PORTRAIT.equals(mSceneMode)) &&
2122 (Parameters.EFFECT_NONE.equals(colorEffect))) {
2123 //Set Skin Tone Correction factor
2124 Log.v(TAG, "set tone bar: mSceneMode = " + mSceneMode);
2125 if(mSeekBarInitialized == true)
2126 mHandler.sendEmptyMessage(SET_SKIN_TONE_FACTOR);
2127 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302128
2129 //Set Histogram
2130 String histogram = mPreferences.getString(
2131 CameraSettings.KEY_HISTOGRAM,
2132 mActivity.getString(R.string.pref_camera_histogram_default));
2133 if (CameraUtil.isSupported(histogram,
2134 mParameters.getSupportedHistogramModes()) && mCameraDevice != null) {
2135 // Call for histogram
2136 if(histogram.equals("enable")) {
2137 mActivity.runOnUiThread(new Runnable() {
2138 public void run() {
2139 if(mGraphView != null) {
2140 mGraphView.setVisibility(View.VISIBLE);
2141 mGraphView.PreviewChanged();
2142 }
2143 }
2144 });
2145 mCameraDevice.setHistogramMode(mStatsCallback);
2146 mHiston = true;
2147 } else {
2148 mHiston = false;
2149 mActivity.runOnUiThread(new Runnable() {
2150 public void run() {
2151 if (mGraphView != null)
2152 mGraphView.setVisibility(View.INVISIBLE);
2153 }
2154 });
2155 mCameraDevice.setHistogramMode(null);
2156 }
2157 }
Alok Kediya4b6f3f92013-09-28 17:39:13 +05302158 // Read Flip mode from adb command
2159 //value: 0(default) - FLIP_MODE_OFF
2160 //value: 1 - FLIP_MODE_H
2161 //value: 2 - FLIP_MODE_V
2162 //value: 3 - FLIP_MODE_VH
2163 int preview_flip_value = SystemProperties.getInt("debug.camera.preview.flip", 0);
2164 int video_flip_value = SystemProperties.getInt("debug.camera.video.flip", 0);
2165 int picture_flip_value = SystemProperties.getInt("debug.camera.picture.flip", 0);
2166 int rotation = CameraUtil.getJpegRotation(mCameraId, mOrientation);
2167 mParameters.setRotation(rotation);
2168 if (rotation == 90 || rotation == 270) {
2169 // in case of 90 or 270 degree, V/H flip should reverse
2170 if (preview_flip_value == 1) {
2171 preview_flip_value = 2;
2172 } else if (preview_flip_value == 2) {
2173 preview_flip_value = 1;
2174 }
2175 if (video_flip_value == 1) {
2176 video_flip_value = 2;
2177 } else if (video_flip_value == 2) {
2178 video_flip_value = 1;
2179 }
2180 if (picture_flip_value == 1) {
2181 picture_flip_value = 2;
2182 } else if (picture_flip_value == 2) {
2183 picture_flip_value = 1;
2184 }
2185 }
2186 String preview_flip = CameraUtil.getFilpModeString(preview_flip_value);
2187 String video_flip = CameraUtil.getFilpModeString(video_flip_value);
2188 String picture_flip = CameraUtil.getFilpModeString(picture_flip_value);
2189 if(CameraUtil.isSupported(preview_flip, CameraSettings.getSupportedFlipMode(mParameters))){
2190 mParameters.set(CameraSettings.KEY_QC_PREVIEW_FLIP, preview_flip);
2191 }
2192 if(CameraUtil.isSupported(video_flip, CameraSettings.getSupportedFlipMode(mParameters))){
2193 mParameters.set(CameraSettings.KEY_QC_VIDEO_FLIP, video_flip);
2194 }
2195 if(CameraUtil.isSupported(picture_flip, CameraSettings.getSupportedFlipMode(mParameters))){
2196 mParameters.set(CameraSettings.KEY_QC_SNAPSHOT_PICTURE_FLIP, picture_flip);
2197 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302198 }
Sascha Haeberling638e6f02013-09-18 14:28:51 -07002199 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
Michael Kolb8872c232013-01-29 10:33:22 -08002200 private void setAutoExposureLockIfSupported() {
2201 if (mAeLockSupported) {
2202 mParameters.setAutoExposureLock(mFocusManager.getAeAwbLock());
2203 }
2204 }
2205
Sascha Haeberling638e6f02013-09-18 14:28:51 -07002206 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
Michael Kolb8872c232013-01-29 10:33:22 -08002207 private void setAutoWhiteBalanceLockIfSupported() {
2208 if (mAwbLockSupported) {
2209 mParameters.setAutoWhiteBalanceLock(mFocusManager.getAeAwbLock());
2210 }
2211 }
2212
Michael Kolb8872c232013-01-29 10:33:22 -08002213 private void setFocusAreasIfSupported() {
2214 if (mFocusAreaSupported) {
2215 mParameters.setFocusAreas(mFocusManager.getFocusAreas());
2216 }
2217 }
2218
Michael Kolb8872c232013-01-29 10:33:22 -08002219 private void setMeteringAreasIfSupported() {
2220 if (mMeteringAreaSupported) {
Michael Kolb8872c232013-01-29 10:33:22 -08002221 mParameters.setMeteringAreas(mFocusManager.getMeteringAreas());
2222 }
2223 }
2224
Ruben Brunk4601f5d2013-09-24 18:35:22 -07002225 private boolean updateCameraParametersPreference() {
Michael Kolb8872c232013-01-29 10:33:22 -08002226 setAutoExposureLockIfSupported();
2227 setAutoWhiteBalanceLockIfSupported();
2228 setFocusAreasIfSupported();
2229 setMeteringAreasIfSupported();
2230
2231 // Set picture size.
2232 String pictureSize = mPreferences.getString(
2233 CameraSettings.KEY_PICTURE_SIZE, null);
2234 if (pictureSize == null) {
2235 CameraSettings.initialCameraPictureSize(mActivity, mParameters);
2236 } else {
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302237 Size old_size = mParameters.getPictureSize();
2238 Log.v(TAG, "old picture_size = " + old_size.width + " x " + old_size.height);
Michael Kolb8872c232013-01-29 10:33:22 -08002239 List<Size> supported = mParameters.getSupportedPictureSizes();
2240 CameraSettings.setCameraPictureSize(
2241 pictureSize, supported, mParameters);
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302242 Size size = mParameters.getPictureSize();
2243 Log.v(TAG, "new picture_size = " + size.width + " x " + size.height);
2244 if (old_size != null && size != null) {
2245 if(!size.equals(old_size) && mCameraState != PREVIEW_STOPPED) {
2246 Log.v(TAG, "Picture Size changed. Restart Preview");
2247 mRestartPreview = true;
2248 }
2249 }
Michael Kolb8872c232013-01-29 10:33:22 -08002250 }
2251 Size size = mParameters.getPictureSize();
2252
2253 // Set a preview size that is closest to the viewfinder height and has
2254 // the right aspect ratio.
2255 List<Size> sizes = mParameters.getSupportedPreviewSizes();
Angus Kongb50b5cb2013-08-09 14:55:20 -07002256 Size optimalSize = CameraUtil.getOptimalPreviewSize(mActivity, sizes,
Michael Kolb8872c232013-01-29 10:33:22 -08002257 (double) size.width / size.height);
2258 Size original = mParameters.getPreviewSize();
2259 if (!original.equals(optimalSize)) {
2260 mParameters.setPreviewSize(optimalSize.width, optimalSize.height);
Doris Liu6432cd62013-06-13 17:20:31 -07002261
Michael Kolb8872c232013-01-29 10:33:22 -08002262 // Zoom related settings will be changed for different preview
2263 // sizes, so set and read the parameters to get latest values
Michael Kolb4a4d4ef2013-05-30 08:35:26 -07002264 if (mHandler.getLooper() == Looper.myLooper()) {
2265 // On UI thread only, not when camera starts up
2266 setupPreview();
2267 } else {
2268 mCameraDevice.setParameters(mParameters);
2269 }
Michael Kolb8872c232013-01-29 10:33:22 -08002270 mParameters = mCameraDevice.getParameters();
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302271 Log.v(TAG, "Preview Size changed. Restart Preview");
2272 mRestartPreview = true;
Michael Kolb8872c232013-01-29 10:33:22 -08002273 }
2274 Log.v(TAG, "Preview size is " + optimalSize.width + "x" + optimalSize.height);
2275
2276 // Since changing scene mode may change supported values, set scene mode
2277 // first. HDR is a scene mode. To promote it in UI, it is stored in a
2278 // separate preference.
Sascha Haeberling98f38bb2013-09-24 18:58:34 -07002279 String onValue = mActivity.getString(R.string.setting_on_value);
Michael Kolb8872c232013-01-29 10:33:22 -08002280 String hdr = mPreferences.getString(CameraSettings.KEY_CAMERA_HDR,
2281 mActivity.getString(R.string.pref_camera_hdr_default));
Sascha Haeberling9bf0fd62013-10-03 12:10:48 -07002282 String hdrPlus = mPreferences.getString(CameraSettings.KEY_CAMERA_HDR_PLUS,
2283 mActivity.getString(R.string.pref_camera_hdr_plus_default));
Ruben Brunk4601f5d2013-09-24 18:35:22 -07002284 boolean hdrOn = onValue.equals(hdr);
Sascha Haeberling9bf0fd62013-10-03 12:10:48 -07002285 boolean hdrPlusOn = onValue.equals(hdrPlus);
Sascha Haeberling98f38bb2013-09-24 18:58:34 -07002286
2287 boolean doGcamModeSwitch = false;
Sascha Haeberling9bf0fd62013-10-03 12:10:48 -07002288 if (hdrPlusOn && GcamHelper.hasGcamCapture()) {
Ruben Brunk4601f5d2013-09-24 18:35:22 -07002289 // Kick off mode switch to gcam.
2290 doGcamModeSwitch = true;
Michael Kolb8872c232013-01-29 10:33:22 -08002291 } else {
Ruben Brunk4601f5d2013-09-24 18:35:22 -07002292 if (hdrOn) {
2293 mSceneMode = CameraUtil.SCENE_MODE_HDR;
2294 } else {
2295 mSceneMode = mPreferences.getString(
2296 CameraSettings.KEY_SCENE_MODE,
2297 mActivity.getString(R.string.pref_camera_scenemode_default));
2298 }
Michael Kolb8872c232013-01-29 10:33:22 -08002299 }
Angus Kongb50b5cb2013-08-09 14:55:20 -07002300 if (CameraUtil.isSupported(mSceneMode, mParameters.getSupportedSceneModes())) {
Michael Kolb8872c232013-01-29 10:33:22 -08002301 if (!mParameters.getSceneMode().equals(mSceneMode)) {
2302 mParameters.setSceneMode(mSceneMode);
2303
2304 // Setting scene mode will change the settings of flash mode,
2305 // white balance, and focus mode. Here we read back the
2306 // parameters, so we can know those settings.
2307 mCameraDevice.setParameters(mParameters);
2308 mParameters = mCameraDevice.getParameters();
2309 }
2310 } else {
2311 mSceneMode = mParameters.getSceneMode();
2312 if (mSceneMode == null) {
2313 mSceneMode = Parameters.SCENE_MODE_AUTO;
2314 }
2315 }
2316
2317 // Set JPEG quality.
2318 int jpegQuality = CameraProfile.getJpegEncodingQualityParameter(mCameraId,
2319 CameraProfile.QUALITY_HIGH);
2320 mParameters.setJpegQuality(jpegQuality);
2321
2322 // For the following settings, we need to check if the settings are
2323 // still supported by latest driver, if not, ignore the settings.
2324
2325 // Set exposure compensation
2326 int value = CameraSettings.readExposure(mPreferences);
2327 int max = mParameters.getMaxExposureCompensation();
2328 int min = mParameters.getMinExposureCompensation();
2329 if (value >= min && value <= max) {
2330 mParameters.setExposureCompensation(value);
2331 } else {
2332 Log.w(TAG, "invalid exposure range: " + value);
2333 }
2334
2335 if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) {
2336 // Set flash mode.
2337 String flashMode = mPreferences.getString(
2338 CameraSettings.KEY_FLASH_MODE,
2339 mActivity.getString(R.string.pref_camera_flashmode_default));
2340 List<String> supportedFlash = mParameters.getSupportedFlashModes();
Angus Kongb50b5cb2013-08-09 14:55:20 -07002341 if (CameraUtil.isSupported(flashMode, supportedFlash)) {
Michael Kolb8872c232013-01-29 10:33:22 -08002342 mParameters.setFlashMode(flashMode);
2343 } else {
2344 flashMode = mParameters.getFlashMode();
2345 if (flashMode == null) {
2346 flashMode = mActivity.getString(
2347 R.string.pref_camera_flashmode_no_flash);
2348 }
2349 }
2350
2351 // Set white balance parameter.
2352 String whiteBalance = mPreferences.getString(
2353 CameraSettings.KEY_WHITE_BALANCE,
2354 mActivity.getString(R.string.pref_camera_whitebalance_default));
Angus Kongb50b5cb2013-08-09 14:55:20 -07002355 if (CameraUtil.isSupported(whiteBalance,
Michael Kolb8872c232013-01-29 10:33:22 -08002356 mParameters.getSupportedWhiteBalance())) {
2357 mParameters.setWhiteBalance(whiteBalance);
2358 } else {
2359 whiteBalance = mParameters.getWhiteBalance();
2360 if (whiteBalance == null) {
2361 whiteBalance = Parameters.WHITE_BALANCE_AUTO;
2362 }
2363 }
2364
2365 // Set focus mode.
2366 mFocusManager.overrideFocusMode(null);
2367 mParameters.setFocusMode(mFocusManager.getFocusMode());
2368 } else {
2369 mFocusManager.overrideFocusMode(mParameters.getFocusMode());
2370 }
2371
Angus Kongdcccc512013-08-08 17:06:03 -07002372 if (mContinuousFocusSupported && ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK) {
Michael Kolb8872c232013-01-29 10:33:22 -08002373 updateAutoFocusMoveCallback();
2374 }
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302375 //QCom related parameters updated here.
2376 qcomUpdateCameraParametersPreference();
Ruben Brunk4601f5d2013-09-24 18:35:22 -07002377 return doGcamModeSwitch;
Michael Kolb8872c232013-01-29 10:33:22 -08002378 }
2379
Sascha Haeberling638e6f02013-09-18 14:28:51 -07002380 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
Michael Kolb8872c232013-01-29 10:33:22 -08002381 private void updateAutoFocusMoveCallback() {
Angus Kongb50b5cb2013-08-09 14:55:20 -07002382 if (mParameters.getFocusMode().equals(CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE)) {
Angus Kong9ef99252013-07-18 18:04:19 -07002383 mCameraDevice.setAutoFocusMoveCallback(mHandler,
Angus Kong4f795b82013-09-16 14:25:35 -07002384 (CameraAFMoveCallback) mAutoFocusMoveCallback);
Michael Kolb8872c232013-01-29 10:33:22 -08002385 } else {
Angus Kong9ef99252013-07-18 18:04:19 -07002386 mCameraDevice.setAutoFocusMoveCallback(null, null);
Michael Kolb8872c232013-01-29 10:33:22 -08002387 }
2388 }
2389
2390 // We separate the parameters into several subsets, so we can update only
2391 // the subsets actually need updating. The PREFERENCE set needs extra
2392 // locking because the preference can be changed from GLThread as well.
2393 private void setCameraParameters(int updateSet) {
Ruben Brunk4601f5d2013-09-24 18:35:22 -07002394 boolean doModeSwitch = false;
2395
Michael Kolb8872c232013-01-29 10:33:22 -08002396 if ((updateSet & UPDATE_PARAM_INITIALIZE) != 0) {
2397 updateCameraParametersInitialize();
2398 }
2399
2400 if ((updateSet & UPDATE_PARAM_ZOOM) != 0) {
2401 updateCameraParametersZoom();
2402 }
2403
2404 if ((updateSet & UPDATE_PARAM_PREFERENCE) != 0) {
Ruben Brunk4601f5d2013-09-24 18:35:22 -07002405 doModeSwitch = updateCameraParametersPreference();
Michael Kolb8872c232013-01-29 10:33:22 -08002406 }
2407
2408 mCameraDevice.setParameters(mParameters);
Ruben Brunk4601f5d2013-09-24 18:35:22 -07002409
Sascha Haeberling9bf0fd62013-10-03 12:10:48 -07002410 // Switch to gcam module if HDR+ was selected
Angus Kong0fb819b2013-10-08 13:44:19 -07002411 if (doModeSwitch && !mIsImageCaptureIntent) {
ztenghui367c7c82013-10-16 14:43:26 -07002412 mHandler.sendEmptyMessage(SWITCH_TO_GCAM_MODULE);
Ruben Brunk4601f5d2013-09-24 18:35:22 -07002413 }
Michael Kolb8872c232013-01-29 10:33:22 -08002414 }
2415
2416 // If the Camera is idle, update the parameters immediately, otherwise
2417 // accumulate them in mUpdateSet and update later.
2418 private void setCameraParametersWhenIdle(int additionalUpdateSet) {
2419 mUpdateSet |= additionalUpdateSet;
2420 if (mCameraDevice == null) {
2421 // We will update all the parameters when we open the device, so
2422 // we don't need to do anything now.
2423 mUpdateSet = 0;
2424 return;
2425 } else if (isCameraIdle()) {
2426 setCameraParameters(mUpdateSet);
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302427 if(mRestartPreview && mCameraState != PREVIEW_STOPPED) {
2428 Log.v(TAG, "Restarting Preview...");
2429 stopPreview();
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +05302430 resizeForPreviewAspectRatio();
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302431 startPreview();
2432 setCameraState(IDLE);
2433 }
2434 mRestartPreview = false;
Michael Kolbd6954f32013-03-08 20:43:01 -08002435 updateSceneMode();
Alok Kediya427798d2013-09-28 17:42:32 +05302436 updateHdrMode();
Michael Kolb8872c232013-01-29 10:33:22 -08002437 mUpdateSet = 0;
2438 } else {
2439 if (!mHandler.hasMessages(SET_CAMERA_PARAMETERS_WHEN_IDLE)) {
2440 mHandler.sendEmptyMessageDelayed(
2441 SET_CAMERA_PARAMETERS_WHEN_IDLE, 1000);
2442 }
2443 }
2444 }
2445
ztenghui7b265a62013-09-09 14:58:44 -07002446 @Override
Michael Kolbd6954f32013-03-08 20:43:01 -08002447 public boolean isCameraIdle() {
Michael Kolb8872c232013-01-29 10:33:22 -08002448 return (mCameraState == IDLE) ||
2449 (mCameraState == PREVIEW_STOPPED) ||
2450 ((mFocusManager != null) && mFocusManager.isFocusCompleted()
2451 && (mCameraState != SWITCHING_CAMERA));
2452 }
2453
ztenghui7b265a62013-09-09 14:58:44 -07002454 @Override
Michael Kolbd6954f32013-03-08 20:43:01 -08002455 public boolean isImageCaptureIntent() {
Michael Kolb8872c232013-01-29 10:33:22 -08002456 String action = mActivity.getIntent().getAction();
2457 return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action)
Angus Kong6a8e8a12013-07-19 14:55:07 -07002458 || CameraActivity.ACTION_IMAGE_CAPTURE_SECURE.equals(action));
Michael Kolb8872c232013-01-29 10:33:22 -08002459 }
2460
2461 private void setupCaptureParams() {
2462 Bundle myExtras = mActivity.getIntent().getExtras();
2463 if (myExtras != null) {
2464 mSaveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
2465 mCropValue = myExtras.getString("crop");
2466 }
2467 }
2468
Michael Kolb8872c232013-01-29 10:33:22 -08002469 @Override
2470 public void onSharedPreferenceChanged() {
2471 // ignore the events after "onPause()"
2472 if (mPaused) return;
2473
2474 boolean recordLocation = RecordLocationPreference.get(
2475 mPreferences, mContentResolver);
2476 mLocationManager.recordLocation(recordLocation);
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302477 if(needRestart()){
2478 Log.v(TAG, "Restarting Preview... Camera Mode Changhed");
2479 stopPreview();
2480 startPreview();
2481 setCameraState(IDLE);
2482 mRestartPreview = false;
2483 }
Alok Kediya3c9da9a2013-10-03 15:12:43 +05302484 /* Check if the PhotoUI Menu is initialized or not. This
2485 * should be initialized during onCameraOpen() which should
2486 * have been called by now. But for some reason that is not
2487 * executed till now, then schedule these functionality for
2488 * later by posting a message to the handler */
2489 if (mUI.mMenuInitialized) {
2490 setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE);
2491 mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup,
2492 mPreferences);
2493 } else {
2494 mHandler.sendEmptyMessage(SET_PHOTO_UI_PARAMS);
2495 }
Santhosh Kumar H E6bc53a12013-10-25 13:14:10 +05302496 resizeForPreviewAspectRatio();
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302497 if (mSeekBarInitialized == true){
2498 Log.v(TAG, "onSharedPreferenceChanged Skin tone bar: change");
2499 // skin tone is enabled only for party and portrait BSM
2500 // when color effects are not enabled
2501 String colorEffect = mPreferences.getString(
2502 CameraSettings.KEY_COLOR_EFFECT,
2503 mActivity.getString(R.string.pref_camera_coloreffect_default));
2504 if((Parameters.SCENE_MODE_PARTY.equals(mSceneMode) ||
2505 Parameters.SCENE_MODE_PORTRAIT.equals(mSceneMode)) &&
2506 (Parameters.EFFECT_NONE.equals(colorEffect))) {
2507 Log.v(TAG, "Party/Portrait + No effect, SkinToneBar enabled");
2508 } else {
2509 disableSkinToneSeekBar();
2510 }
2511 }
Michael Kolb8872c232013-01-29 10:33:22 -08002512 }
2513
2514 @Override
2515 public void onCameraPickerClicked(int cameraId) {
2516 if (mPaused || mPendingSwitchCameraId != -1) return;
2517
2518 mPendingSwitchCameraId = cameraId;
Doris Liu6432cd62013-06-13 17:20:31 -07002519
2520 Log.v(TAG, "Start to switch camera. cameraId=" + cameraId);
2521 // We need to keep a preview frame for the animation before
2522 // releasing the camera. This will trigger onPreviewTextureCopied.
2523 //TODO: Need to animate the camera switch
2524 switchCamera();
Michael Kolb8872c232013-01-29 10:33:22 -08002525 }
2526
Michael Kolb8872c232013-01-29 10:33:22 -08002527 // Preview texture has been copied. Now camera can be released and the
2528 // animation can be started.
2529 @Override
2530 public void onPreviewTextureCopied() {
2531 mHandler.sendEmptyMessage(SWITCH_CAMERA);
2532 }
2533
2534 @Override
2535 public void onCaptureTextureCopied() {
2536 }
2537
2538 @Override
2539 public void onUserInteraction() {
Dan Aminzade92ae10e2013-08-13 14:44:25 -07002540 if (!mActivity.isFinishing()) keepScreenOnAwhile();
Michael Kolb8872c232013-01-29 10:33:22 -08002541 }
2542
2543 private void resetScreenOn() {
2544 mHandler.removeMessages(CLEAR_SCREEN_DELAY);
2545 mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
2546 }
2547
2548 private void keepScreenOnAwhile() {
2549 mHandler.removeMessages(CLEAR_SCREEN_DELAY);
2550 mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
2551 mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
2552 }
2553
Michael Kolb8872c232013-01-29 10:33:22 -08002554 @Override
2555 public void onOverriddenPreferencesClicked() {
2556 if (mPaused) return;
Michael Kolbd6954f32013-03-08 20:43:01 -08002557 mUI.showPreferencesToast();
Michael Kolb8872c232013-01-29 10:33:22 -08002558 }
2559
2560 private void showTapToFocusToast() {
2561 // TODO: Use a toast?
2562 new RotateTextToast(mActivity, R.string.tap_to_focus, 0).show();
2563 // Clear the preference.
2564 Editor editor = mPreferences.edit();
2565 editor.putBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, false);
2566 editor.apply();
2567 }
2568
2569 private void initializeCapabilities() {
2570 mInitialParams = mCameraDevice.getParameters();
Angus Kongb50b5cb2013-08-09 14:55:20 -07002571 mFocusAreaSupported = CameraUtil.isFocusAreaSupported(mInitialParams);
2572 mMeteringAreaSupported = CameraUtil.isMeteringAreaSupported(mInitialParams);
2573 mAeLockSupported = CameraUtil.isAutoExposureLockSupported(mInitialParams);
2574 mAwbLockSupported = CameraUtil.isAutoWhiteBalanceLockSupported(mInitialParams);
Angus Kongdcccc512013-08-08 17:06:03 -07002575 mContinuousFocusSupported = mInitialParams.getSupportedFocusModes().contains(
Angus Kongb50b5cb2013-08-09 14:55:20 -07002576 CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE);
Michael Kolb8872c232013-01-29 10:33:22 -08002577 }
2578
Michael Kolb8872c232013-01-29 10:33:22 -08002579 @Override
2580 public void onCountDownFinished() {
2581 mSnapshotOnIdle = false;
2582 mFocusManager.doSnap();
Doris Liuda50e052013-02-07 14:36:32 -08002583 mFocusManager.onShutterUp();
Michael Kolb8872c232013-01-29 10:33:22 -08002584 }
2585
Michael Kolb8872c232013-01-29 10:33:22 -08002586 @Override
Michael Kolb8872c232013-01-29 10:33:22 -08002587 public void onShowSwitcherPopup() {
Michael Kolbd6954f32013-03-08 20:43:01 -08002588 mUI.onShowSwitcherPopup();
Michael Kolb8872c232013-01-29 10:33:22 -08002589 }
2590
Angus Kongce5480e2013-01-29 17:43:48 -08002591 @Override
Michael Kolbd6954f32013-03-08 20:43:01 -08002592 public int onZoomChanged(int index) {
2593 // Not useful to change zoom value when the activity is paused.
2594 if (mPaused) return index;
2595 mZoomValue = index;
2596 if (mParameters == null || mCameraDevice == null) return index;
2597 // Set zoom parameters asynchronously
2598 mParameters.setZoom(mZoomValue);
Angus Kong36ed8672013-04-15 12:11:15 -07002599 mCameraDevice.setParameters(mParameters);
Michael Kolbd6954f32013-03-08 20:43:01 -08002600 Parameters p = mCameraDevice.getParameters();
2601 if (p != null) return p.getZoom();
2602 return index;
Angus Kongce5480e2013-01-29 17:43:48 -08002603 }
2604
2605 @Override
Michael Kolbd6954f32013-03-08 20:43:01 -08002606 public int getCameraState() {
2607 return mCameraState;
2608 }
2609
2610 @Override
2611 public void onQueueStatus(boolean full) {
2612 mUI.enableShutter(!full);
Angus Kongce5480e2013-01-29 17:43:48 -08002613 }
Angus Kong86d36312013-01-31 18:22:44 -08002614
2615 @Override
2616 public void onMediaSaveServiceConnected(MediaSaveService s) {
2617 // We set the listener only when both service and shutterbutton
2618 // are initialized.
Michael Kolbd6954f32013-03-08 20:43:01 -08002619 if (mFirstTimeInitialized) {
2620 s.setListener(this);
2621 }
Angus Kong86d36312013-01-31 18:22:44 -08002622 }
Angus Kong0d00a892013-03-26 11:40:40 -07002623
2624 @Override
2625 public void onAccuracyChanged(Sensor sensor, int accuracy) {
2626 }
2627
2628 @Override
2629 public void onSensorChanged(SensorEvent event) {
2630 int type = event.sensor.getType();
2631 float[] data;
2632 if (type == Sensor.TYPE_ACCELEROMETER) {
2633 data = mGData;
2634 } else if (type == Sensor.TYPE_MAGNETIC_FIELD) {
2635 data = mMData;
2636 } else {
2637 // we should not be here.
2638 return;
2639 }
2640 for (int i = 0; i < 3 ; i++) {
2641 data[i] = event.values[i];
2642 }
2643 float[] orientation = new float[3];
2644 SensorManager.getRotationMatrix(mR, null, mGData, mMData);
2645 SensorManager.getOrientation(mR, orientation);
2646 mHeading = (int) (orientation[0] * 180f / Math.PI) % 360;
2647 if (mHeading < 0) {
2648 mHeading += 360;
2649 }
Angus Kong0d00a892013-03-26 11:40:40 -07002650 }
Doris Liu6432cd62013-06-13 17:20:31 -07002651 @Override
ztenghui7b265a62013-09-09 14:58:44 -07002652 public void onPreviewFocusChanged(boolean previewFocused) {
2653 mUI.onPreviewFocusChanged(previewFocused);
Doris Liu6432cd62013-06-13 17:20:31 -07002654 }
Santhosh Kumar H Eac015202013-10-17 12:12:31 +05302655
2656 private void enableSkinToneSeekBar() {
2657 int progress;
2658 if(brightnessProgressBar != null)
2659 brightnessProgressBar.setVisibility(View.INVISIBLE);
2660 skinToneSeekBar.setMax(MAX_SCE_FACTOR-MIN_SCE_FACTOR);
2661 skinToneSeekBar.setVisibility(View.VISIBLE);
2662 skinToneSeekBar.requestFocus();
2663 if (mskinToneValue != 0) {
2664 progress = (mskinToneValue/SCE_FACTOR_STEP)-MIN_SCE_FACTOR;
2665 mskinToneSeekListener.onProgressChanged(skinToneSeekBar, progress, false);
2666 } else {
2667 progress = (MAX_SCE_FACTOR-MIN_SCE_FACTOR)/2;
2668 RightValue.setText("");
2669 LeftValue.setText("");
2670 }
2671 skinToneSeekBar.setProgress(progress);
2672 mActivity.findViewById(R.id.linear).bringToFront();
2673 skinToneSeekBar.bringToFront();
2674 Title.setText("Skin Tone Enhancement");
2675 Title.setVisibility(View.VISIBLE);
2676 RightValue.setVisibility(View.VISIBLE);
2677 LeftValue.setVisibility(View.VISIBLE);
2678 mSkinToneSeekBar = true;
2679 }
2680
2681 private void disableSkinToneSeekBar() {
2682 skinToneSeekBar.setVisibility(View.INVISIBLE);
2683 Title.setVisibility(View.INVISIBLE);
2684 RightValue.setVisibility(View.INVISIBLE);
2685 LeftValue.setVisibility(View.INVISIBLE);
2686 mskinToneValue = 0;
2687 mSkinToneSeekBar = false;
2688 Editor editor = mPreferences.edit();
2689 editor.putString(CameraSettings.KEY_SKIN_TONE_ENHANCEMENT_FACTOR,
2690 Integer.toString(mskinToneValue - MIN_SCE_FACTOR));
2691 editor.apply();
2692 if(brightnessProgressBar != null)
2693 brightnessProgressBar.setVisibility(View.VISIBLE);
2694}
2695
2696/*
2697 * Provide a mapping for Jpeg encoding quality levels
2698 * from String representation to numeric representation.
2699 */
Doris Liu6432cd62013-06-13 17:20:31 -07002700 @Override
2701 public void onRestorePreferencesClicked() {}
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302702 private void setSkinToneFactor() {
2703 if(mCameraDevice == null || mParameters == null || skinToneSeekBar == null)
2704 return;
Doris Liu6432cd62013-06-13 17:20:31 -07002705
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302706 String skinToneEnhancementPref = "enable";
2707 if(CameraUtil.isSupported(skinToneEnhancementPref,
2708 mParameters.getSupportedSkinToneEnhancementModes())) {
2709 if(skinToneEnhancementPref.equals("enable")) {
2710 int skinToneValue =0;
2711 int progress;
2712 //get the value for the first time!
2713 if (mskinToneValue ==0) {
2714 String factor = mPreferences.getString(
2715 CameraSettings.KEY_SKIN_TONE_ENHANCEMENT_FACTOR, "0");
2716 skinToneValue = Integer.parseInt(factor);
2717 }
2718
2719 Log.v(TAG, "Skin tone bar: enable = " + mskinToneValue);
2720 enableSkinToneSeekBar();
2721 //As a wrokaround set progress again to show the actually progress on screen.
2722 if (skinToneValue != 0) {
2723 progress = (skinToneValue/SCE_FACTOR_STEP)-MIN_SCE_FACTOR;
2724 skinToneSeekBar.setProgress(progress);
2725 }
2726 } else {
2727 Log.v(TAG, "Skin tone bar: disable");
2728 disableSkinToneSeekBar();
2729 }
2730 } else {
2731 Log.v(TAG, "Skin tone bar: Not supported");
2732 skinToneSeekBar.setVisibility(View.INVISIBLE);
2733 }
2734 }
2735
2736 private void enableSkinToneSeekBar() {
2737 int progress;
2738 if(brightnessProgressBar != null)
2739 brightnessProgressBar.setVisibility(View.INVISIBLE);
2740 skinToneSeekBar.setMax(MAX_SCE_FACTOR-MIN_SCE_FACTOR);
2741 skinToneSeekBar.setVisibility(View.VISIBLE);
2742 skinToneSeekBar.requestFocus();
2743 if (mskinToneValue != 0) {
2744 progress = (mskinToneValue/SCE_FACTOR_STEP)-MIN_SCE_FACTOR;
2745 mskinToneSeekListener.onProgressChanged(skinToneSeekBar, progress, false);
2746 } else {
2747 progress = (MAX_SCE_FACTOR-MIN_SCE_FACTOR)/2;
2748 RightValue.setText("");
2749 LeftValue.setText("");
2750 }
2751 skinToneSeekBar.setProgress(progress);
2752 Title.setText("Skin Tone Enhancement");
2753 Title.setVisibility(View.VISIBLE);
2754 RightValue.setVisibility(View.VISIBLE);
2755 LeftValue.setVisibility(View.VISIBLE);
2756 mSkinToneSeekBar = true;
2757 }
2758
2759 private void disableSkinToneSeekBar() {
2760 skinToneSeekBar.setVisibility(View.INVISIBLE);
2761 Title.setVisibility(View.INVISIBLE);
2762 RightValue.setVisibility(View.INVISIBLE);
2763 LeftValue.setVisibility(View.INVISIBLE);
2764 mskinToneValue = 0;
2765 mSkinToneSeekBar = false;
2766 Editor editor = mPreferences.edit();
2767 editor.putString(CameraSettings.KEY_SKIN_TONE_ENHANCEMENT_FACTOR,
2768 Integer.toString(mskinToneValue - MIN_SCE_FACTOR));
2769 editor.apply();
2770 if(brightnessProgressBar != null)
2771 brightnessProgressBar.setVisibility(View.VISIBLE);
2772 }
2773}
2774class JpegEncodingQualityMappings {
2775 private static final String TAG = "JpegEncodingQualityMappings";
2776 private static final int DEFAULT_QUALITY = 85;
2777 private static HashMap<String, Integer> mHashMap =
2778 new HashMap<String, Integer>();
2779
2780 static {
2781 mHashMap.put("normal", CameraProfile.QUALITY_LOW);
2782 mHashMap.put("fine", CameraProfile.QUALITY_MEDIUM);
2783 mHashMap.put("superfine", CameraProfile.QUALITY_HIGH);
2784 }
2785
2786 // Retrieve and return the Jpeg encoding quality number
2787 // for the given quality level.
2788 public static int getQualityNumber(String jpegQuality) {
2789 try{
2790 int qualityPercentile = Integer.parseInt(jpegQuality);
2791 if(qualityPercentile >= 0 && qualityPercentile <=100)
2792 return qualityPercentile;
2793 else
2794 return DEFAULT_QUALITY;
2795 } catch(NumberFormatException nfe){
2796 //chosen quality is not a number, continue
2797 }
2798 Integer quality = mHashMap.get(jpegQuality);
2799 if (quality == null) {
2800 Log.w(TAG, "Unknown Jpeg quality: " + jpegQuality);
2801 return DEFAULT_QUALITY;
2802 }
2803 return CameraProfile.getJpegEncodingQualityParameter(quality.intValue());
2804 }
2805}
2806
2807class GraphView extends View {
2808 private Bitmap mBitmap;
2809 private Paint mPaint = new Paint();
2810 private Paint mPaintRect = new Paint();
2811 private Canvas mCanvas = new Canvas();
2812 private float mScale = (float)3;
2813 private float mWidth;
2814 private float mHeight;
2815 private PhotoModule mPhotoModule;
2816 private CameraManager.CameraProxy mGraphCameraDevice;
2817 private float scaled;
2818 private static final int STATS_SIZE = 256;
2819 private static final String TAG = "GraphView";
2820
2821
2822 public GraphView(Context context, AttributeSet attrs) {
2823 super(context,attrs);
2824
2825 mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
2826 mPaintRect.setColor(0xFFFFFFFF);
2827 mPaintRect.setStyle(Paint.Style.FILL);
2828 }
2829 @Override
2830 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
2831 mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
2832 mCanvas.setBitmap(mBitmap);
2833 mWidth = w;
2834 mHeight = h;
2835 super.onSizeChanged(w, h, oldw, oldh);
2836 }
2837 @Override
2838 protected void onDraw(Canvas canvas) {
2839 Log.v(TAG, "in Camera.java ondraw");
Alok Kediya0dc64ff2013-09-27 20:22:45 +05302840 if(mPhotoModule == null || !mPhotoModule.mHiston ) {
2841 Log.e(TAG, "returning as histogram is off ");
2842 return;
2843 }
2844
2845 if (mBitmap != null) {
2846 final Paint paint = mPaint;
2847 final Canvas cavas = mCanvas;
2848 final float border = 5;
2849 float graphheight = mHeight - (2 * border);
2850 float graphwidth = mWidth - (2 * border);
2851 float left,top,right,bottom;
2852 float bargap = 0.0f;
2853 float barwidth = graphwidth/STATS_SIZE;
2854
2855 cavas.drawColor(0xFFAAAAAA);
2856 paint.setColor(Color.BLACK);
2857
2858 for (int k = 0; k <= (graphheight /32) ; k++) {
2859 float y = (float)(32 * k)+ border;
2860 cavas.drawLine(border, y, graphwidth + border , y, paint);
2861 }
2862 for (int j = 0; j <= (graphwidth /32); j++) {
2863 float x = (float)(32 * j)+ border;
2864 cavas.drawLine(x, border, x, graphheight + border, paint);
2865 }
2866 synchronized(PhotoModule.statsdata) {
2867 //Assumption: The first element contains
2868 // the maximum value.
2869 int maxValue = Integer.MIN_VALUE;
2870 if ( 0 == PhotoModule.statsdata[0] ) {
2871 for ( int i = 1 ; i <= STATS_SIZE ; i++ ) {
2872 if ( maxValue < PhotoModule.statsdata[i] ) {
2873 maxValue = PhotoModule.statsdata[i];
2874 }
2875 }
2876 } else {
2877 maxValue = PhotoModule.statsdata[0];
2878 }
2879 mScale = ( float ) maxValue;
2880 for(int i=1 ; i<=STATS_SIZE ; i++) {
2881 scaled = (PhotoModule.statsdata[i]/mScale)*STATS_SIZE;
2882 if(scaled >= (float)STATS_SIZE)
2883 scaled = (float)STATS_SIZE;
2884 left = (bargap * (i+1)) + (barwidth * i) + border;
2885 top = graphheight + border;
2886 right = left + barwidth;
2887 bottom = top - scaled;
2888 cavas.drawRect(left, top, right, bottom, mPaintRect);
2889 }
2890 }
2891 canvas.drawBitmap(mBitmap, 0, 0, null);
2892 }
2893 if (mPhotoModule.mHiston && mPhotoModule!= null) {
2894 mGraphCameraDevice = mPhotoModule.getCamera();
2895 if (mGraphCameraDevice != null){
2896 mGraphCameraDevice.sendHistogramData();
2897 }
2898 }
2899 }
2900 public void PreviewChanged() {
2901 invalidate();
2902 }
2903 public void setPhotoModuleObject(PhotoModule photoModule) {
2904 mPhotoModule = photoModule;
2905 }
Michael Kolb8872c232013-01-29 10:33:22 -08002906}