diff options
author | Jay Wang <jaywang@codeaurora.org> | 2016-03-14 15:52:45 -0700 |
---|---|---|
committer | Jay Wang <jaywang@codeaurora.org> | 2016-03-30 15:53:33 -0700 |
commit | bdabec40fc13076c07fba8bb5d04a104cab2ddce (patch) | |
tree | dc0e7799a12a36b06dbb75cfaa07f327d0bd0d8b /src/com/android/camera/CaptureModule.java | |
parent | f12aabf6cc14021a7412657a3cfb9ec089e56dde (diff) | |
download | android_packages_apps_Snap-bdabec40fc13076c07fba8bb5d04a104cab2ddce.tar.gz android_packages_apps_Snap-bdabec40fc13076c07fba8bb5d04a104cab2ddce.tar.bz2 android_packages_apps_Snap-bdabec40fc13076c07fba8bb5d04a104cab2ddce.zip |
SnapdragonCamera: create base files for camera2 API
All the new files are copied from the
commit : f3448373ef3c92b492ac65a9b4008d45a51f88ee
res/layout/capture_module.xml copied from
res/layout/photo_module.xml
src/com/android/camera/CaptureMenu.java copied from
src/com/android/camera/PhotoMenu.java
src/com/android/camera/CaptureModule.java copied from
src/com/android/camera/PhotoModule.java
src/com/android/camera/CaptureUI.java copied from
src/com/android/camera/PhotoUI.java
CRs-Fixed: 989750
Change-Id: I4a97975ed5847d9025f9ff8e8fcbcbeaedd49e16
Diffstat (limited to 'src/com/android/camera/CaptureModule.java')
-rw-r--r-- | src/com/android/camera/CaptureModule.java | 4934 |
1 files changed, 4934 insertions, 0 deletions
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java new file mode 100644 index 000000000..b4b8d33d1 --- /dev/null +++ b/src/com/android/camera/CaptureModule.java @@ -0,0 +1,4934 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences.Editor; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.Rect; +import android.hardware.Camera.CameraInfo; +import android.hardware.Camera.Parameters; +import android.hardware.Camera.Size; +import android.hardware.Camera; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.location.Location; +import android.media.AudioManager; +import android.media.CameraProfile; +import android.media.SoundPool; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Debug; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.MessageQueue; +import android.os.SystemClock; +import android.provider.MediaStore; +import android.util.Log; +import android.view.KeyEvent; +import android.view.OrientationEventListener; +import android.view.SurfaceHolder; +import android.view.View; +import android.view.WindowManager; +import android.widget.Toast; +import android.widget.ProgressBar; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.camera.CameraManager.CameraAFCallback; +import com.android.camera.CameraManager.CameraAFMoveCallback; +import com.android.camera.CameraManager.CameraPictureCallback; +import com.android.camera.CameraManager.CameraProxy; +import com.android.camera.CameraManager.CameraShutterCallback; +import com.android.camera.PhotoModule.NamedImages.NamedEntity; +import com.android.camera.TsMakeupManager.MakeupLevelListener; +import com.android.camera.exif.ExifInterface; +import com.android.camera.exif.ExifTag; +import com.android.camera.exif.Rational; +import com.android.camera.ui.CountDownView.OnCountDownFinishedListener; +import com.android.camera.ui.ModuleSwitcher; +import com.android.camera.ui.RotateTextToast; +import com.android.camera.util.ApiHelper; +import com.android.camera.util.CameraUtil; +import com.android.camera.util.GcamHelper; +import com.android.camera.util.UsageStatistics; +import org.codeaurora.snapcam.R; + +import android.widget.EditText; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.text.InputType; +import android.text.TextUtils; + +import com.android.internal.util.MemInfoReader; +import android.app.ActivityManager; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.Vector; +import java.util.HashMap; +import android.util.AttributeSet; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.SystemProperties; +import java.util.Collections; +import java.util.Formatter; + +public class PhotoModule + implements CameraModule, + PhotoController, + FocusOverlayManager.Listener, + CameraPreference.OnPreferenceChangedListener, + ShutterButton.OnShutterButtonListener, + MediaSaveService.Listener, + OnCountDownFinishedListener, + SensorEventListener, MakeupLevelListener { + + private static final String TAG = "CAM_PhotoModule"; + + //QCom data members + public static boolean mBrightnessVisible = false; + private static final int MAX_SHARPNESS_LEVEL = 6; + private boolean mRestartPreview = false; + private int mSnapshotMode; + private int mBurstSnapNum = 1; + private int mReceivedSnapNum = 0; + public boolean mFaceDetectionEnabled = false; + private DrawAutoHDR mDrawAutoHDR; + /*Histogram variables*/ + private GraphView mGraphView; + private static final int STATS_DATA = 257; + public static int statsdata[] = new int[STATS_DATA]; + public boolean mHiston = false; + // We number the request code from 1000 to avoid collision with Gallery. + private static final int REQUEST_CROP = 1000; + + private static final int SETUP_PREVIEW = 1; + private static final int FIRST_TIME_INIT = 2; + private static final int CLEAR_SCREEN_DELAY = 3; + private static final int SET_CAMERA_PARAMETERS_WHEN_IDLE = 4; + private static final int SHOW_TAP_TO_FOCUS_TOAST = 5; + private static final int SWITCH_CAMERA = 6; + private static final int SWITCH_CAMERA_START_ANIMATION = 7; + private static final int CAMERA_OPEN_DONE = 8; + private static final int OPEN_CAMERA_FAIL = 9; + private static final int CAMERA_DISABLED = 10; + private static final int SET_PHOTO_UI_PARAMS = 11; + private static final int SWITCH_TO_GCAM_MODULE = 12; + private static final int ON_PREVIEW_STARTED = 13; + + // The subset of parameters we need to update in setCameraParameters(). + private static final int UPDATE_PARAM_INITIALIZE = 1; + private static final int UPDATE_PARAM_ZOOM = 2; + private static final int UPDATE_PARAM_PREFERENCE = 4; + private static final int UPDATE_PARAM_ALL = -1; + + // This is the delay before we execute onResume tasks when coming + // from the lock screen, to allow time for onPause to execute. + private static final int ON_RESUME_TASKS_DELAY_MSEC = 20; + + private static final String DEBUG_IMAGE_PREFIX = "DEBUG_"; + + // copied from Camera hierarchy + private CameraActivity mActivity; + private CameraProxy mCameraDevice; + private int mCameraId; + private Parameters mParameters; + private boolean mPaused; + private View mRootView; + + private PhotoUI mUI; + + public boolean mAutoHdrEnable; + // The activity is going to switch to the specified camera id. This is + // needed because texture copy is done in GL thread. -1 means camera is not + // switching. + protected int mPendingSwitchCameraId = -1; + private boolean mOpenCameraFail; + private boolean mCameraDisabled; + + // When setCameraParametersWhenIdle() is called, we accumulate the subsets + // needed to be updated in mUpdateSet. + private int mUpdateSet; + + private static final int SCREEN_DELAY = 2 * 60 * 1000; + + private int mZoomValue; // The current zoom value. + + private Parameters mInitialParams; + private boolean mFocusAreaSupported; + private boolean mMeteringAreaSupported; + private boolean mAeLockSupported; + private boolean mAwbLockSupported; + private boolean mContinuousFocusSupported; + private boolean mTouchAfAecFlag; + private boolean mLongshotSave = false; + private boolean mRefocus = false; + private boolean mLastPhotoTakenWithRefocus = false; + + private int mLongShotCaptureCount; + private int mLongShotCaptureCountLimit; + + // The degrees of the device rotated clockwise from its natural orientation. + private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN; + private ComboPreferences mPreferences; + private String mPrevSavedCDS; + private boolean isTNREnabled; + + private static final String sTempCropFilename = "crop-temp"; + + private boolean mFaceDetectionStarted = false; + + private static final String PERSIST_LONG_ENABLE = "persist.camera.longshot.enable"; + private static final String PERSIST_LONG_SAVE = "persist.camera.longshot.save"; + private static final String PERSIST_PREVIEW_RESTART = "persist.camera.feature.restart"; + private static final String PERSIST_CAPTURE_ANIMATION = "persist.camera.capture.animate"; + + private static final int MINIMUM_BRIGHTNESS = 0; + private static final int MAXIMUM_BRIGHTNESS = 6; + private static final int DEFAULT_BRIGHTNESS = 3; + private int mbrightness = 3; + private int mbrightness_step = 1; + private ProgressBar brightnessProgressBar; + // Constant from android.hardware.Camera.Parameters + private static final String KEY_PICTURE_FORMAT = "picture-format"; + private static final String KEY_QC_RAW_PICUTRE_SIZE = "raw-size"; + public static final String PIXEL_FORMAT_JPEG = "jpeg"; + + private static final int MIN_SCE_FACTOR = -10; + private static final int MAX_SCE_FACTOR = +10; + private int SCE_FACTOR_STEP = 10; + + private boolean mPreviewRestartSupport = false; + + // mCropValue and mSaveUri are used only if isImageCaptureIntent() is true. + private String mCropValue; + private Uri mSaveUri; + + private Uri mDebugUri; + + // Used for check memory status for longshot mode + // Currently, this cancel threshold selection is based on test experiments, + // we can change it based on memory status or other requirements. + private static final int CHECKING_INTERVAL = 10; + private static final int LONGSHOT_CANCEL_THRESHOLD = CHECKING_INTERVAL * 40 * 1024 * 1024; + private int mRemainedMemCheckingCount; + private long mSecondaryServerMem; + private boolean mLongshotActive = false; + + // We use a queue to generated names of the images to be used later + // when the image is ready to be saved. + private NamedImages mNamedImages; + + private SoundPool mSoundPool; + private int mRefocusSound; + + private byte[] mLastJpegData; + private int mLastJpegOrientation = 0; + + private Runnable mDoSnapRunnable = new Runnable() { + @Override + public void run() { + onShutterButtonClick(); + } + }; + + private class OpenCameraThread extends Thread { + @Override + public void run() { + openCamera(); + startPreview(); + } + } + + private OpenCameraThread mOpenCameraThread = null; + /** + * An unpublished intent flag requesting to return as soon as capturing + * is completed. + * + * TODO: consider publishing by moving into MediaStore. + */ + private static final String EXTRA_QUICK_CAPTURE = + "android.intent.extra.quickCapture"; + + // The display rotation in degrees. This is only valid when mCameraState is + // not PREVIEW_STOPPED. + private int mDisplayRotation; + // The value for android.hardware.Camera.setDisplayOrientation. + private int mCameraDisplayOrientation; + // The value for UI components like indicators. + private int mDisplayOrientation; + // The value for android.hardware.Camera.Parameters.setRotation. + private int mJpegRotation; + // Indicates whether we are using front camera + private boolean mMirror; + private boolean mFirstTimeInitialized; + private boolean mIsImageCaptureIntent; + + private int mCameraState = INIT; + private boolean mSnapshotOnIdle = false; + + private ContentResolver mContentResolver; + + private LocationManager mLocationManager; + private boolean mLocationPromptTriggered = false; + + private final PostViewPictureCallback mPostViewPictureCallback = + new PostViewPictureCallback(); + private final RawPictureCallback mRawPictureCallback = + new RawPictureCallback(); + private final AutoFocusCallback mAutoFocusCallback = + new AutoFocusCallback(); + private final Object mAutoFocusMoveCallback = + ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK + ? new AutoFocusMoveCallback() + : null; + + private final CameraErrorCallback mErrorCallback = new CameraErrorCallback(); + private final StatsCallback mStatsCallback = new StatsCallback(); + private final MetaDataCallback mMetaDataCallback = new MetaDataCallback(); + private long mFocusStartTime; + private long mShutterCallbackTime; + private long mPostViewPictureCallbackTime; + private long mRawPictureCallbackTime; + private long mJpegPictureCallbackTime; + private long mOnResumeTime; + private byte[] mJpegImageData; + + // These latency time are for the CameraLatency test. + public long mAutoFocusTime; + public long mShutterLag; + public long mShutterToPictureDisplayedTime; + public long mPictureDisplayedToJpegCallbackTime; + public long mJpegCallbackFinishTime; + public long mCaptureStartTime; + + // This handles everything about focus. + private FocusOverlayManager mFocusManager; + + private String mSceneMode; + private String mCurrTouchAfAec = Parameters.TOUCH_AF_AEC_ON; + private String mSavedFlashMode = null; + + private final Handler mHandler = new MainHandler(); + private MessageQueue.IdleHandler mIdleHandler = null; + + private PreferenceGroup mPreferenceGroup; + + private boolean mQuickCapture; + private SensorManager mSensorManager; + private float[] mGData = new float[3]; + private float[] mMData = new float[3]; + private float[] mR = new float[16]; + private int mHeading = -1; + + // True if all the parameters needed to start preview is ready. + private boolean mCameraPreviewParamsReady = false; + + private int mManual3AEnabled = 0; + private static final int MANUAL_FOCUS = 1; + private static final int MANUAL_WB = 2; + private static final int MANUAL_EXPOSURE = 4; + private boolean mAnimateCapture = true; + + private int mJpegFileSizeEstimation = 0; + private int mRemainingPhotos = -1; + private static final int SELFIE_FLASH_DURATION = 680; + + private class SelfieThread extends Thread { + public void run() { + try { + Thread.sleep(SELFIE_FLASH_DURATION); + mActivity.runOnUiThread(new Runnable() { + public void run() { + mFocusManager.doSnap(); + } + }); + } catch(InterruptedException e) { + } + selfieThread = null; + } + } + private SelfieThread selfieThread; + + private class MediaSaveNotifyThread extends Thread + { + private Uri uri; + public MediaSaveNotifyThread(Uri uri) + { + this.uri = uri; + } + public void setUri(Uri uri) + { + this.uri = uri; + } + public void run() + { + while(mLongshotActive) { + try { + Thread.sleep(10); + } catch(InterruptedException e) { + } + } + mActivity.runOnUiThread(new Runnable() { + public void run() { + if (uri != null) + mActivity.notifyNewMedia(uri); + mActivity.updateStorageSpaceAndHint(); + updateRemainingPhotos(); + } + }); + mediaSaveNotifyThread = null; + } + } + + private MediaSaveNotifyThread mediaSaveNotifyThread; + private MediaSaveService.OnMediaSavedListener mOnMediaSavedListener = + new MediaSaveService.OnMediaSavedListener() { + @Override + public void onMediaSaved(Uri uri) { + if(mLongshotActive) { + if(mediaSaveNotifyThread == null) { + mediaSaveNotifyThread = new MediaSaveNotifyThread(uri); + mediaSaveNotifyThread.start(); + } + else + mediaSaveNotifyThread.setUri(uri); + } else { + if (uri != null) { + mActivity.notifyNewMedia(uri); + } + } + } + }; + + private void checkDisplayRotation() { + // Set the display orientation if display rotation has changed. + // Sometimes this happens when the device is held upside + // down and camera app is opened. Rotation animation will + // take some time and the rotation value we have got may be + // wrong. Framework does not have a callback for this now. + if (CameraUtil.getDisplayRotation(mActivity) != mDisplayRotation) { + setDisplayOrientation(); + } + if (SystemClock.uptimeMillis() - mOnResumeTime < 5000) { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + checkDisplayRotation(); + } + }, 100); + } + } + + public Parameters getParameters() + { + return mParameters; + } + + /** + * This Handler is used to post message back onto the main thread of the + * application + */ + private class MainHandler extends Handler { + public MainHandler() { + super(Looper.getMainLooper()); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case SETUP_PREVIEW: { + setupPreview(); + break; + } + + case CLEAR_SCREEN_DELAY: { + mActivity.getWindow().clearFlags( + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + break; + } + + case FIRST_TIME_INIT: { + initializeFirstTime(); + break; + } + + case SET_CAMERA_PARAMETERS_WHEN_IDLE: { + setCameraParametersWhenIdle(0); + break; + } + + case SHOW_TAP_TO_FOCUS_TOAST: { + showTapToFocusToast(); + break; + } + + case SWITCH_CAMERA: { + switchCamera(); + break; + } + + case SWITCH_CAMERA_START_ANIMATION: { + // TODO: Need to revisit + // ((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera(); + break; + } + + case CAMERA_OPEN_DONE: { + onCameraOpened(); + break; + } + + case OPEN_CAMERA_FAIL: { + mOpenCameraFail = true; + CameraUtil.showErrorAndFinish(mActivity, + R.string.cannot_connect_camera); + break; + } + + case CAMERA_DISABLED: { + mCameraDisabled = true; + CameraUtil.showErrorAndFinish(mActivity, + R.string.camera_disabled); + break; + } + + case SET_PHOTO_UI_PARAMS: { + setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE); + mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup, + mPreferences); + break; + } + + case SWITCH_TO_GCAM_MODULE: { + mActivity.onModuleSelected(ModuleSwitcher.GCAM_MODULE_INDEX); + break; + } + + case ON_PREVIEW_STARTED: { + onPreviewStarted(); + break; + } + } + } + } + + + @Override + public void init(CameraActivity activity, View parent) { + mActivity = activity; + mRootView = parent; + mPreferences = new ComboPreferences(mActivity); + CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal(), activity); + mCameraId = getPreferredCameraId(mPreferences); + + mContentResolver = mActivity.getContentResolver(); + + // Surface texture is from camera screen nail and startPreview needs it. + // This must be done before startPreview. + mIsImageCaptureIntent = isImageCaptureIntent(); + + mPreferences.setLocalId(mActivity, mCameraId); + CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); + + mUI = new PhotoUI(activity, this, parent); + if (mOpenCameraThread == null) { + mOpenCameraThread = new OpenCameraThread(); + mOpenCameraThread.start(); + } + initializeControlByIntent(); + mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false); + mLocationManager = new LocationManager(mActivity, mUI); + mSensorManager = (SensorManager)(mActivity.getSystemService(Context.SENSOR_SERVICE)); + + brightnessProgressBar = (ProgressBar)mRootView.findViewById(R.id.progress); + if (brightnessProgressBar instanceof SeekBar) { + SeekBar seeker = (SeekBar) brightnessProgressBar; + seeker.setOnSeekBarChangeListener(mSeekListener); + } + brightnessProgressBar.setMax(MAXIMUM_BRIGHTNESS); + mbrightness = mPreferences.getInt( + CameraSettings.KEY_BRIGHTNESS, + DEFAULT_BRIGHTNESS); + brightnessProgressBar.setProgress(mbrightness); + brightnessProgressBar.setVisibility(View.INVISIBLE); + Storage.setSaveSDCard( + mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1")); + } + + private void initializeControlByIntent() { + mUI.initializeControlByIntent(); + if (mIsImageCaptureIntent) { + setupCaptureParams(); + } + } + + private void onPreviewStarted() { + if (mCameraState == SNAPSHOT_IN_PROGRESS) { + return; + } + setCameraState(IDLE); + mFocusManager.onPreviewStarted(); + startFaceDetection(); + locationFirstRun(); + mUI.enableShutter(true); + } + + // Prompt the user to pick to record location for the very first run of + // camera only + private void locationFirstRun() { + /* Do not prompt if the preference is already set, this is a secure + * camera session, or the prompt has already been triggered. */ + if (RecordLocationPreference.isSet(mPreferences) || + mActivity.isSecureCamera() || mLocationPromptTriggered) { + return; + } + // Check if the back camera exists + int backCameraId = CameraHolder.instance().getBackCameraId(); + if (backCameraId == -1) { + // If there is no back camera, do not show the prompt. + return; + } + + mLocationPromptTriggered = true; + mUI.showLocationDialog(); + } + + @Override + public void enableRecordingLocation(boolean enable) { + setLocationPreference(enable ? RecordLocationPreference.VALUE_ON + : RecordLocationPreference.VALUE_OFF); + } + + @Override + public void onPreviewUIReady() { + if (mPaused || mCameraDevice == null) { + return; + } + Log.v(TAG, "onPreviewUIReady"); + if (mCameraState == PREVIEW_STOPPED) { + startPreview(); + } else { + synchronized (mCameraDevice) { + SurfaceHolder sh = mUI.getSurfaceHolder(); + if (sh == null) { + Log.w(TAG, "startPreview: holder for preview are not ready."); + return; + } + mCameraDevice.setPreviewDisplay(sh); + } + } + } + + @Override + public void onPreviewUIDestroyed() { + if (mCameraDevice == null) { + return; + } + try { + if (mOpenCameraThread != null) { + mOpenCameraThread.join(); + mOpenCameraThread = null; + } + } catch (InterruptedException ex) { + // ignore + } + mCameraDevice.setPreviewDisplay(null); + stopPreview(); + } + + private void setLocationPreference(String value) { + mPreferences.edit() + .putString(CameraSettings.KEY_RECORD_LOCATION, value) + .apply(); + // TODO: Fix this to use the actual onSharedPreferencesChanged listener + // instead of invoking manually + onSharedPreferenceChanged(); + } + + private void onCameraOpened() { + if (mPaused) { + return; + } + Log.v(TAG, "onCameraOpened"); + openCameraCommon(); + resizeForPreviewAspectRatio(); + updateFocusManager(mUI); + } + + private void switchCamera() { + if (mPaused) return; + + Log.v(TAG, "Start to switch camera. id=" + mPendingSwitchCameraId); + mCameraId = mPendingSwitchCameraId; + mPendingSwitchCameraId = -1; + setCameraId(mCameraId); + + // from onPause + try { + if (mOpenCameraThread != null) { + mOpenCameraThread.join(); + mOpenCameraThread = null; + } + } catch (InterruptedException ex) { + // ignore + } + closeCamera(); + mUI.collapseCameraControls(); + mUI.clearFaces(); + if (mFocusManager != null) mFocusManager.removeMessages(); + + // Restart the camera and initialize the UI. From onCreate. + mPreferences.setLocalId(mActivity, mCameraId); + CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); + mCameraDevice = CameraUtil.openCamera( + mActivity, mCameraId, mHandler, + mActivity.getCameraOpenErrorCallback()); + + if (mCameraDevice == null) { + Log.e(TAG, "Failed to open camera:" + mCameraId + ", aborting."); + return; + } + mParameters = mCameraDevice.getParameters(); + mInitialParams = mParameters; + initializeCapabilities(); + CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; + mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); + mFocusManager.setMirror(mMirror); + mFocusManager.setParameters(mInitialParams); + setupPreview(); + + // reset zoom value index + mZoomValue = 0; + resizeForPreviewAspectRatio(); + openCameraCommon(); + + // Start switch camera animation. Post a message because + // onFrameAvailable from the old camera may already exist. + mHandler.sendEmptyMessage(SWITCH_CAMERA_START_ANIMATION); + } + + protected void setCameraId(int cameraId) { + ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CAMERA_ID); + pref.setValue("" + cameraId); + } + + // either open a new camera or switch cameras + private void openCameraCommon() { + loadCameraPreferences(); + + mUI.onCameraOpened(mPreferenceGroup, mPreferences, mParameters, this, this); + if (mIsImageCaptureIntent) { + mUI.overrideSettings(CameraSettings.KEY_CAMERA_HDR_PLUS, + mActivity.getString(R.string.setting_off_value)); + } + updateCameraSettings(); + showTapToFocusToastIfNeeded(); + resetManual3ASettings(); + resetMiscSettings(); + } + + @Override + public void onScreenSizeChanged(int width, int height) { + if (mFocusManager != null) mFocusManager.setPreviewSize(width, height); + } + + @Override + public void onPreviewRectChanged(Rect previewRect) { + if (mFocusManager != null) mFocusManager.setPreviewRect(previewRect); + } + + private void resetExposureCompensation() { + String value = mPreferences.getString(CameraSettings.KEY_EXPOSURE, + CameraSettings.EXPOSURE_DEFAULT_VALUE); + if (!CameraSettings.EXPOSURE_DEFAULT_VALUE.equals(value)) { + Editor editor = mPreferences.edit(); + editor.putString(CameraSettings.KEY_EXPOSURE, "0"); + editor.apply(); + } + } + + private void resetManual3ASettings() { + String manualExposureDefault = mActivity.getString( + R.string.pref_camera_manual_exp_default); + String manualExposureMode = mPreferences.getString( + CameraSettings.KEY_MANUAL_EXPOSURE, manualExposureDefault); + if (!manualExposureMode.equals(manualExposureDefault)) { + mUI.setPreference( + CameraSettings.KEY_MANUAL_EXPOSURE, manualExposureDefault); + UpdateManualExposureSettings(); + } + String manualFocusDefault = mActivity.getString( + R.string.pref_camera_manual_focus_default); + String manualFocusMode = mPreferences.getString( + CameraSettings.KEY_MANUAL_FOCUS, manualFocusDefault); + if (!manualFocusMode.equals(manualFocusDefault)) { + mUI.setPreference( + CameraSettings.KEY_MANUAL_FOCUS, manualFocusDefault); + UpdateManualFocusSettings(); + } + String manualWBDefault = mActivity.getString( + R.string.pref_camera_manual_wb_default); + String manualWBMode = mPreferences.getString( + CameraSettings.KEY_MANUAL_WB, manualWBDefault); + if (!manualWBMode.equals(manualWBDefault)) { + mUI.setPreference( + CameraSettings.KEY_MANUAL_WB, manualWBDefault); + UpdateManualWBSettings(); + } + mManual3AEnabled = 0; + } + + private void resetMiscSettings() { + boolean disableQcomMiscSetting = + SystemProperties.getBoolean("camera.qcom.misc.disable", false); + if (disableQcomMiscSetting) { + mUI.setPreference(CameraSettings.KEY_ZSL, Parameters.ZSL_OFF); + mUI.setPreference(CameraSettings.KEY_FACE_DETECTION, + Parameters.FACE_DETECTION_OFF); + mUI.setPreference(CameraSettings.KEY_TOUCH_AF_AEC, + Parameters.TOUCH_AF_AEC_OFF); + mUI.setPreference(CameraSettings.KEY_FOCUS_MODE, + Parameters.FOCUS_MODE_AUTO); + mUI.setPreference(CameraSettings.KEY_FLASH_MODE, + Parameters.FLASH_MODE_OFF); + mUI.setPreference(CameraSettings.KEY_DENOISE, + Parameters.DENOISE_OFF); + onSharedPreferenceChanged(); + } + } + + void setPreviewFrameLayoutCameraOrientation(){ + CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; + //if camera mount angle is 0 or 180, we want to resize preview + if (info.orientation % 180 == 0){ + mUI.cameraOrientationPreviewResize(true); + } else{ + mUI.cameraOrientationPreviewResize(false); + } + } + + @Override + public void resizeForPreviewAspectRatio() { + if ( mCameraDevice == null || mParameters == null) { + Log.e(TAG, "Camera not yet initialized"); + return; + } + setPreviewFrameLayoutCameraOrientation(); + Size size = mParameters.getPreviewSize(); + Log.i(TAG, "Using preview width = " + size.width + "& height = " + size.height); + mUI.setAspectRatio((float) size.width / size.height); + } + + @Override + public void onSwitchSavePath() { + if (mUI.mMenuInitialized) { + mUI.setPreference(CameraSettings.KEY_CAMERA_SAVEPATH, "1"); + } else { + mPreferences.edit() + .putString(CameraSettings.KEY_CAMERA_SAVEPATH, "1") + .apply(); + } + RotateTextToast.makeText(mActivity, R.string.on_switch_save_path_to_sdcard, + Toast.LENGTH_SHORT).show(); + } + + // Snapshots can only be taken after this is called. It should be called + // once only. We could have done these things in onCreate() but we want to + // make preview screen appear as soon as possible. + private void initializeFirstTime() { + if (mFirstTimeInitialized || mPaused) { + return; + } + + // Initialize location service. + boolean recordLocation = RecordLocationPreference.get( + mPreferences, mContentResolver); + mLocationManager.recordLocation(recordLocation); + + mUI.initializeFirstTime(); + MediaSaveService s = mActivity.getMediaSaveService(); + // We set the listener only when both service and shutterbutton + // are initialized. + if (s != null) { + s.setListener(this); + } + + mNamedImages = new NamedImages(); + mGraphView = (GraphView)mRootView.findViewById(R.id.graph_view); + mDrawAutoHDR = (DrawAutoHDR )mRootView.findViewById(R.id.autohdr_view); + if (mGraphView == null || mDrawAutoHDR == null){ + Log.e(TAG, "mGraphView or mDrawAutoHDR is null"); + } else{ + mGraphView.setPhotoModuleObject(this); + mDrawAutoHDR.setPhotoModuleObject(this); + } + + mFirstTimeInitialized = true; + Log.d(TAG, "addIdleHandler in first time initialization"); + addIdleHandler(); + + } + + // If the activity is paused and resumed, this method will be called in + // onResume. + private void initializeSecondTime() { + // Start location update if needed. + boolean recordLocation = RecordLocationPreference.get( + mPreferences, mContentResolver); + mLocationManager.recordLocation(recordLocation); + MediaSaveService s = mActivity.getMediaSaveService(); + if (s != null) { + s.setListener(this); + } + mNamedImages = new NamedImages(); + if (!mIsImageCaptureIntent) { + mUI.showSwitcher(); + } + mUI.initializeSecondTime(mParameters); + } + + private void showTapToFocusToastIfNeeded() { + // Show the tap to focus toast if this is the first start. + if (mFocusAreaSupported && + mPreferences.getBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, true)) { + // Delay the toast for one second to wait for orientation. + mHandler.sendEmptyMessageDelayed(SHOW_TAP_TO_FOCUS_TOAST, 1000); + } + } + + private void addIdleHandler() { + if (mIdleHandler == null) { + mIdleHandler = new MessageQueue.IdleHandler() { + @Override + public boolean queueIdle() { + Storage.ensureOSXCompatible(); + return false; + } + }; + + MessageQueue queue = Looper.myQueue(); + queue.addIdleHandler(mIdleHandler); + } + } + + private void removeIdleHandler() { + if (mIdleHandler != null) { + MessageQueue queue = Looper.myQueue(); + queue.removeIdleHandler(mIdleHandler); + mIdleHandler = null; + } + } + + @Override + public void startFaceDetection() { + if (mCameraDevice == null) return; + + if (mFaceDetectionEnabled == false + || mFaceDetectionStarted || mCameraState != IDLE) return; + if (mParameters.getMaxNumDetectedFaces() > 0) { + mFaceDetectionStarted = true; + CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; + mUI.onStartFaceDetection(mDisplayOrientation, + (info.facing == CameraInfo.CAMERA_FACING_FRONT)); + mCameraDevice.setFaceDetectionCallback(mHandler, mUI); + mCameraDevice.startFaceDetection(); + } + } + + @Override + public void stopFaceDetection() { + if (mFaceDetectionEnabled == false || !mFaceDetectionStarted) return; + if (mParameters.getMaxNumDetectedFaces() > 0) { + mFaceDetectionStarted = false; + mCameraDevice.setFaceDetectionCallback(null, null); + mUI.pauseFaceDetection(); + mCameraDevice.stopFaceDetection(); + mUI.onStopFaceDetection(); + } + } + + // TODO: need to check cached background apps memory and longshot ION memory + private boolean isLongshotNeedCancel() { + if(mRemainedMemCheckingCount < CHECKING_INTERVAL) { + mRemainedMemCheckingCount++; + return false; + } + mRemainedMemCheckingCount = 0; + if (Storage.getAvailableSpace() <= Storage.LOW_STORAGE_THRESHOLD_BYTES * CHECKING_INTERVAL) { + Log.w(TAG, "current storage is full"); + return true; + } + if (mSecondaryServerMem == 0) { + ActivityManager am = (ActivityManager) mActivity.getSystemService( + Context.ACTIVITY_SERVICE); + ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo(); + am.getMemoryInfo(memInfo); + mSecondaryServerMem = memInfo.secondaryServerThreshold; + } + + long totalMemory = Runtime.getRuntime().totalMemory(); + long maxMemory = Runtime.getRuntime().maxMemory(); + long remainMemory = maxMemory - totalMemory; + + MemInfoReader reader = new MemInfoReader(); + reader.readMemInfo(); + long[] info = reader.getRawInfo(); + long availMem = (info[Debug.MEMINFO_FREE] + info[Debug.MEMINFO_CACHED]) * 1024; + + if (availMem <= mSecondaryServerMem || remainMemory <= LONGSHOT_CANCEL_THRESHOLD) { + Log.e(TAG, "cancel longshot: free=" + info[Debug.MEMINFO_FREE] * 1024 + + " cached=" + info[Debug.MEMINFO_CACHED] * 1024 + + " threshold=" + mSecondaryServerMem); + mLongshotActive = false; + RotateTextToast.makeText(mActivity,R.string.msg_cancel_longshot_for_limited_memory, + Toast.LENGTH_SHORT).show(); + return true; + } + + return false; + } + + private final class LongshotShutterCallback + implements CameraShutterCallback { + + @Override + public void onShutter(CameraProxy camera) { + mShutterCallbackTime = System.currentTimeMillis(); + mShutterLag = mShutterCallbackTime - mCaptureStartTime; + Log.e(TAG, "[KPI Perf] PROFILE_SHUTTER_LAG mShutterLag = " + mShutterLag + "ms"); + synchronized(mCameraDevice) { + + if (mCameraState != LONGSHOT || + !mLongshotActive) { + return; + } + + if(isLongshotNeedCancel()) { + return; + } + + if(mLongShotCaptureCount == mLongShotCaptureCountLimit) { + mLongshotActive = false; + return; + } + + mUI.doShutterAnimation(); + + Location loc = getLocationAccordPictureFormat(mParameters.get(KEY_PICTURE_FORMAT)); + + mLongShotCaptureCount++; + if (mLongshotSave) { + mCameraDevice.takePicture(mHandler, + new LongshotShutterCallback(), + mRawPictureCallback, mPostViewPictureCallback, + new LongshotPictureCallback(loc)); + } else { + mCameraDevice.takePicture(mHandler,new LongshotShutterCallback(), + mRawPictureCallback, mPostViewPictureCallback, + new JpegPictureCallback(loc)); + } + } + } + } + + private final class ShutterCallback + implements CameraShutterCallback { + + private boolean mNeedsAnimation; + + public ShutterCallback(boolean needsAnimation) { + mNeedsAnimation = needsAnimation; + } + + @Override + public void onShutter(CameraProxy camera) { + mShutterCallbackTime = System.currentTimeMillis(); + mShutterLag = mShutterCallbackTime - mCaptureStartTime; + Log.e(TAG, "[KPI Perf] PROFILE_SHUTTER_LAG mShutterLag = " + mShutterLag + "ms"); + if (mNeedsAnimation) { + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + animateAfterShutter(); + } + }); + } + if (mRefocus) { + mSoundPool.play(mRefocusSound, 1.0f, 1.0f, 0, 0, 1.0f); + } + } + } + private final class StatsCallback + implements android.hardware.Camera.CameraDataCallback { + @Override + public void onCameraData(int [] data, android.hardware.Camera camera) { + //if(!mPreviewing || !mHiston || !mFirstTimeInitialized){ + if(!mHiston || !mFirstTimeInitialized){ + return; + } + /*The first element in the array stores max hist value . Stats data begin from second value*/ + synchronized(statsdata) { + System.arraycopy(data,0,statsdata,0,STATS_DATA); + } + mActivity.runOnUiThread(new Runnable() { + public void run() { + if(mGraphView != null) + mGraphView.PreviewChanged(); + } + }); + } + } + + private final class MetaDataCallback + implements android.hardware.Camera.CameraMetaDataCallback{ + @Override + public void onCameraMetaData (byte[] data, android.hardware.Camera camera) { + int metadata[] = new int[3]; + if (data.length >= 12) { + for (int i =0;i<3;i++) { + metadata[i] = byteToInt( (byte []) data, i*4); + } + if (metadata[2] == 1) { + mAutoHdrEnable = true; + mActivity.runOnUiThread(new Runnable() { + public void run() { + if (mDrawAutoHDR != null) + mDrawAutoHDR.AutoHDR(); + } + }); + } + else { + mAutoHdrEnable = false; + mActivity.runOnUiThread(new Runnable() { + public void run() { + if (mDrawAutoHDR != null) + mDrawAutoHDR.AutoHDR(); + } + }); + } + } + } + + private int byteToInt (byte[] b, int offset) { + int value = 0; + for (int i = 0; i < 4; i++) { + int shift = (4 - 1 - i) * 8; + value += (b[(3-i) + offset] & 0x000000FF) << shift; + } + return value; + } + } + + private final class PostViewPictureCallback + implements CameraPictureCallback { + @Override + public void onPictureTaken(byte [] data, CameraProxy camera) { + mPostViewPictureCallbackTime = System.currentTimeMillis(); + Log.v(TAG, "mShutterToPostViewCallbackTime = " + + (mPostViewPictureCallbackTime - mShutterCallbackTime) + + "ms"); + } + } + + private final class RawPictureCallback + implements CameraPictureCallback { + @Override + public void onPictureTaken(byte [] rawData, CameraProxy camera) { + mRawPictureCallbackTime = System.currentTimeMillis(); + Log.v(TAG, "mShutterToRawCallbackTime = " + + (mRawPictureCallbackTime - mShutterCallbackTime) + "ms"); + } + } + + private final class LongshotPictureCallback implements CameraPictureCallback { + Location mLocation; + + public LongshotPictureCallback(Location loc) { + mLocation = loc; + } + + @Override + public void onPictureTaken(final byte [] jpegData, CameraProxy camera) { + if (mPaused) { + return; + } + + mFocusManager.updateFocusUI(); // Ensure focus indicator is hidden. + + String jpegFilePath = new String(jpegData); + mNamedImages.nameNewImage(mCaptureStartTime); + NamedEntity name = mNamedImages.getNextNameEntity(); + String title = (name == null) ? null : name.title; + long date = (name == null) ? -1 : name.date; + + if (title == null) { + Log.e(TAG, "Unbalanced name/data pair"); + return; + } + + + if (date == -1 ) { + Log.e(TAG, "Invalid filename date"); + return; + } + + String dstPath = Storage.DIRECTORY; + File sdCard = android.os.Environment.getExternalStorageDirectory(); + File dstFile = new File(dstPath); + if (dstFile == null) { + Log.e(TAG, "Destination file path invalid"); + return; + } + + File srcFile = new File(jpegFilePath); + if (srcFile == null) { + Log.e(TAG, "Source file path invalid"); + return; + } + + if ( srcFile.renameTo(dstFile) ) { + Size s = mParameters.getPictureSize(); + String pictureFormat = mParameters.get(KEY_PICTURE_FORMAT); + mActivity.getMediaSaveService().addImage( + null, title, date, mLocation, s.width, s.height, + 0, null, mOnMediaSavedListener, mContentResolver, pictureFormat); + } else { + Log.e(TAG, "Failed to move jpeg file"); + } + } + } + + private final class JpegPictureCallback + implements CameraPictureCallback { + Location mLocation; + + public JpegPictureCallback(Location loc) { + mLocation = loc; + } + + @Override + public void onPictureTaken(final byte [] jpegData, CameraProxy camera) { + mUI.stopSelfieFlash(); + mUI.enableShutter(true); + if (mPaused) { + return; + } + if (mIsImageCaptureIntent) { + if (!mRefocus) { + stopPreview(); + } + } else if (mSceneMode == CameraUtil.SCENE_MODE_HDR) { + mUI.showSwitcher(); + mUI.setSwipingEnabled(true); + } + + mReceivedSnapNum = mReceivedSnapNum + 1; + mJpegPictureCallbackTime = System.currentTimeMillis(); + if(mSnapshotMode == CameraInfo.CAMERA_SUPPORT_MODE_ZSL) { + Log.v(TAG, "JpegPictureCallback : in zslmode"); + mParameters = mCameraDevice.getParameters(); + mBurstSnapNum = mParameters.getInt("num-snaps-per-shutter"); + } + Log.v(TAG, "JpegPictureCallback: Received = " + mReceivedSnapNum + + "Burst count = " + mBurstSnapNum); + // If postview callback has arrived, the captured image is displayed + // in postview callback. If not, the captured image is displayed in + // raw picture callback. + if (mPostViewPictureCallbackTime != 0) { + mShutterToPictureDisplayedTime = + mPostViewPictureCallbackTime - mShutterCallbackTime; + mPictureDisplayedToJpegCallbackTime = + mJpegPictureCallbackTime - mPostViewPictureCallbackTime; + } else { + mShutterToPictureDisplayedTime = + mRawPictureCallbackTime - mShutterCallbackTime; + mPictureDisplayedToJpegCallbackTime = + mJpegPictureCallbackTime - mRawPictureCallbackTime; + } + Log.v(TAG, "mPictureDisplayedToJpegCallbackTime = " + + mPictureDisplayedToJpegCallbackTime + "ms"); + + mFocusManager.updateFocusUI(); // Ensure focus indicator is hidden. + + boolean needRestartPreview = !mIsImageCaptureIntent + && !mPreviewRestartSupport + && (mCameraState != LONGSHOT) + && (mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_ZSL) + && (mReceivedSnapNum == mBurstSnapNum); + if (needRestartPreview) { + setupPreview(); + if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals( + mFocusManager.getFocusMode())) { + mCameraDevice.cancelAutoFocus(); + } + } else if ((mReceivedSnapNum == mBurstSnapNum) + && (mCameraState != LONGSHOT)){ + mFocusManager.resetTouchFocus(); + if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals( + mFocusManager.getFocusMode())) { + mCameraDevice.cancelAutoFocus(); + } + mUI.resumeFaceDetection(); + if (!mIsImageCaptureIntent) { + setCameraState(IDLE); + } + startFaceDetection(); + } + + mLastPhotoTakenWithRefocus = mRefocus; + if (mRefocus) { + final String[] NAMES = { "00.jpg", "01.jpg", "02.jpg", "03.jpg", + "04.jpg", "DepthMapImage.y", "AllFocusImage.jpg" }; + try { + FileOutputStream out = mActivity.openFileOutput(NAMES[mReceivedSnapNum - 1], + Context.MODE_PRIVATE); + out.write(jpegData, 0, jpegData.length); + out.close(); + } catch (Exception e) { + } + } + if (!mRefocus || (mRefocus && mReceivedSnapNum == 7)) { + ExifInterface exif = Exif.getExif(jpegData); + int orientation = Exif.getOrientation(exif); + if (!mIsImageCaptureIntent) { + // Burst snapshot. Generate new image name. + if (mReceivedSnapNum > 1) { + mNamedImages.nameNewImage(mCaptureStartTime, mRefocus); + } + // Calculate the width and the height of the jpeg. + Size s = mParameters.getPictureSize(); + int width, height; + if ((mJpegRotation + orientation) % 180 == 0) { + width = s.width; + height = s.height; + } else { + width = s.height; + height = s.width; + } + String pictureFormat = mParameters.get(KEY_PICTURE_FORMAT); + if (pictureFormat != null && !pictureFormat.equalsIgnoreCase(PIXEL_FORMAT_JPEG)) { + // overwrite width and height if raw picture + String pair = mParameters.get(KEY_QC_RAW_PICUTRE_SIZE); + if (pair != null) { + int pos = pair.indexOf('x'); + if (pos != -1) { + width = Integer.parseInt(pair.substring(0, pos)); + height = Integer.parseInt(pair.substring(pos + 1)); + } + } + } + NamedEntity name = mNamedImages.getNextNameEntity(); + String title = (name == null) ? null : name.title; + long date = (name == null) ? -1 : name.date; + // Handle debug mode outputs + if (mDebugUri != null) { + // If using a debug uri, save jpeg there. + saveToDebugUri(jpegData); + // Adjust the title of the debug image shown in mediastore. + if (title != null) { + title = DEBUG_IMAGE_PREFIX + title; + } + } + if (title == null) { + Log.e(TAG, "Unbalanced name/data pair"); + } else { + if (date == -1) { + date = mCaptureStartTime; + } + if (mHeading >= 0) { + // heading direction has been updated by the sensor. + ExifTag directionRefTag = exif.buildTag( + ExifInterface.TAG_GPS_IMG_DIRECTION_REF, + ExifInterface.GpsTrackRef.MAGNETIC_DIRECTION); + ExifTag directionTag = exif.buildTag( + ExifInterface.TAG_GPS_IMG_DIRECTION, + new Rational(mHeading, 1)); + exif.setTag(directionRefTag); + exif.setTag(directionTag); + } + String mPictureFormat = mParameters.get(KEY_PICTURE_FORMAT); + mActivity.getMediaSaveService().addImage( + jpegData, title, date, mLocation, width, height, + orientation, exif, mOnMediaSavedListener, + mContentResolver, mPictureFormat); + if (mRefocus && mReceivedSnapNum == 7) { + mUI.showRefocusToast(mRefocus); + } + } + // Animate capture with real jpeg data instead of a preview frame. + if (mCameraState != LONGSHOT) { + Size pic_size = mParameters.getPictureSize(); + if ((pic_size.width <= 352) && (pic_size.height<= 288)) { + mUI.setDownFactor(2); //Downsample by 2 for CIF & below + } else { + mUI.setDownFactor(4); + } + if (mAnimateCapture) { + mUI.animateCapture(jpegData, orientation, mMirror); + } + } else { + // In long shot mode, we do not want to update the preview thumbnail + // for each snapshot, instead, keep the last jpeg data and orientation, + // use it to show the final one at the end of long shot. + mLastJpegData = jpegData; + mLastJpegOrientation = orientation; + } + + } else { + stopPreview(); + mJpegImageData = jpegData; + if (!mQuickCapture) { + mUI.showCapturedImageForReview(jpegData, orientation, mMirror); + } else { + onCaptureDone(); + } + } + if(!mLongshotActive) + mActivity.updateStorageSpaceAndHint(); + mUI.updateRemainingPhotos(--mRemainingPhotos); + long now = System.currentTimeMillis(); + mJpegCallbackFinishTime = now - mJpegPictureCallbackTime; + Log.v(TAG, "mJpegCallbackFinishTime = " + + mJpegCallbackFinishTime + "ms"); + + if (mReceivedSnapNum == mBurstSnapNum) { + mJpegPictureCallbackTime = 0; + } + + if (mHiston && (mSnapshotMode ==CameraInfo.CAMERA_SUPPORT_MODE_ZSL)) { + mActivity.runOnUiThread(new Runnable() { + public void run() { + if (mGraphView != null) { + mGraphView.setVisibility(View.VISIBLE); + mGraphView.PreviewChanged(); + } + } + }); + } + if (mSnapshotMode == CameraInfo.CAMERA_SUPPORT_MODE_ZSL && + mCameraState != LONGSHOT && + mReceivedSnapNum == mBurstSnapNum && + !mIsImageCaptureIntent) { + cancelAutoFocus(); + } + } + } + } + + private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() { + public void onStartTrackingTouch(SeekBar bar) { + // no support + } + public void onProgressChanged(SeekBar bar, int progress, boolean fromtouch) { + } + public void onStopTrackingTouch(SeekBar bar) { + } + }; + + private final class AutoFocusCallback implements CameraAFCallback { + @Override + public void onAutoFocus( + boolean focused, CameraProxy camera) { + if (mPaused) return; + + mAutoFocusTime = System.currentTimeMillis() - mFocusStartTime; + Log.v(TAG, "mAutoFocusTime = " + mAutoFocusTime + "ms"); + //don't reset the camera state while capture is in progress + //otherwise, it might result in another takepicture + switch (mCameraState) { + case PhotoController.LONGSHOT: + case SNAPSHOT_IN_PROGRESS: + break; + default: + setCameraState(IDLE); + break; + } + mFocusManager.onAutoFocus(focused, mUI.isShutterPressed()); + } + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + private final class AutoFocusMoveCallback + implements CameraAFMoveCallback { + @Override + public void onAutoFocusMoving( + boolean moving, CameraProxy camera) { + mFocusManager.onAutoFocusMoving(moving); + } + } + + /** + * This class is just a thread-safe queue for name,date holder objects. + */ + public static class NamedImages { + private Vector<NamedEntity> mQueue; + + public NamedImages() { + mQueue = new Vector<NamedEntity>(); + } + + public void nameNewImage(long date) { + NamedEntity r = new NamedEntity(); + r.title = CameraUtil.createJpegName(date); + r.date = date; + mQueue.add(r); + } + + public void nameNewImage(long date, boolean refocus) { + NamedEntity r = new NamedEntity(); + r.title = CameraUtil.createJpegName(date, refocus); + r.date = date; + mQueue.add(r); + } + + public NamedEntity getNextNameEntity() { + synchronized(mQueue) { + if (!mQueue.isEmpty()) { + return mQueue.remove(0); + } + } + return null; + } + + public static class NamedEntity { + public String title; + public long date; + } + } + + private void setCameraState(int state) { + mCameraState = state; + switch (state) { + case PhotoController.PREVIEW_STOPPED: + case PhotoController.SNAPSHOT_IN_PROGRESS: + case PhotoController.LONGSHOT: + case PhotoController.SWITCHING_CAMERA: + mUI.enableGestures(false); + break; + case PhotoController.IDLE: + mUI.enableGestures(true); + break; + } + } + + private void animateAfterShutter() { + // Only animate when in full screen capture mode + // i.e. If monkey/a user swipes to the gallery during picture taking, + // don't show animation + if (!mIsImageCaptureIntent) { + mUI.animateFlash(); + } + } + + @Override + public boolean capture() { + // If we are already in the middle of taking a snapshot or the image save request + // is full then ignore. + if (mCameraDevice == null || mCameraState == SNAPSHOT_IN_PROGRESS + || mCameraState == SWITCHING_CAMERA + || mActivity.getMediaSaveService() == null + || mActivity.getMediaSaveService().isQueueFull()) { + return false; + } + mCaptureStartTime = System.currentTimeMillis(); + mPostViewPictureCallbackTime = 0; + mJpegImageData = null; + + final boolean animateBefore = (mSceneMode == CameraUtil.SCENE_MODE_HDR); + if(mHiston) { + if (mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_ZSL) { + mHiston = false; + mCameraDevice.setHistogramMode(null); + } + mActivity.runOnUiThread(new Runnable() { + public void run() { + if(mGraphView != null) + mGraphView.setVisibility(View.INVISIBLE); + } + }); + } + + if (animateBefore) { + animateAfterShutter(); + } + + if (mCameraState == LONGSHOT) { + mCameraDevice.setLongshot(true); + } + + // Set rotation and gps data. + int orientation = mOrientation; + mJpegRotation = CameraUtil.getJpegRotation(mCameraId, orientation); + String pictureFormat = mParameters.get(KEY_PICTURE_FORMAT); + Location loc = getLocationAccordPictureFormat(pictureFormat); + + synchronized (mCameraDevice) { + mParameters.setRotation(mJpegRotation); + CameraUtil.setGpsParameters(mParameters, loc); + + if (mRefocus) { + mParameters.set(CameraSettings.KEY_QC_LEGACY_BURST, + CameraSettings.KEY_QC_RE_FOCUS_COUNT); + } else { + mParameters.remove(CameraSettings.KEY_QC_LEGACY_BURST); + } + + // Unlock AE&AWB, if they continue + // to be locked during snapshot, then + // side effects could be triggered w.r.t. + // flash. + mFocusManager.setAeAwbLock(false); + setAutoExposureLockIfSupported(); + setAutoWhiteBalanceLockIfSupported(); + + mCameraDevice.setParameters(mParameters); + mParameters = mCameraDevice.getParameters(); + } + + mBurstSnapNum = mParameters.getInt("num-snaps-per-shutter"); + mReceivedSnapNum = 0; + mPreviewRestartSupport = SystemProperties.getBoolean( + PERSIST_PREVIEW_RESTART, false); + mPreviewRestartSupport &= CameraSettings.isInternalPreviewSupported( + mParameters); + mPreviewRestartSupport &= (mBurstSnapNum == 1); + // Restart is needed if HDR is enabled + mPreviewRestartSupport &= !CameraUtil.SCENE_MODE_HDR.equals(mSceneMode); + mPreviewRestartSupport &= PIXEL_FORMAT_JPEG.equalsIgnoreCase( + pictureFormat); + + // We don't want user to press the button again while taking a + // multi-second HDR photo. For longshot, no need to disable. + if (mCameraState != LONGSHOT) { + mUI.enableShutter(false); + } + + if (mCameraState == LONGSHOT) { + mLongShotCaptureCountLimit = SystemProperties.getInt( + "persist.camera.longshot.shotnum", 0); + mLongShotCaptureCount = 1; + if(mLongshotSave) { + mCameraDevice.takePicture(mHandler, + new LongshotShutterCallback(), + mRawPictureCallback, mPostViewPictureCallback, + new LongshotPictureCallback(loc)); + } else { + mCameraDevice.takePicture(mHandler, + new LongshotShutterCallback(), + mRawPictureCallback, mPostViewPictureCallback, + new JpegPictureCallback(loc)); + } + } else { + mCameraDevice.enableShutterSound(!mRefocus); + mCameraDevice.takePicture(mHandler, + new ShutterCallback(!animateBefore), + mRawPictureCallback, mPostViewPictureCallback, + new JpegPictureCallback(loc)); + setCameraState(SNAPSHOT_IN_PROGRESS); + } + + mNamedImages.nameNewImage(mCaptureStartTime, mRefocus); + + if (mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_ZSL) { + mFaceDetectionStarted = false; + } + UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA, + UsageStatistics.ACTION_CAPTURE_DONE, "Photo", 0, + UsageStatistics.hashFileName(mNamedImages.mQueue.lastElement().title + ".jpg")); + return true; + } + + @Override + public void setFocusParameters() { + setCameraParameters(UPDATE_PARAM_PREFERENCE); + } + + private Location getLocationAccordPictureFormat(String pictureFormat) { + if (pictureFormat != null && + PIXEL_FORMAT_JPEG.equalsIgnoreCase(pictureFormat)) { + return mLocationManager.getCurrentLocation(); + } + return null; + } + + private int getPreferredCameraId(ComboPreferences preferences) { + int intentCameraId = CameraUtil.getCameraFacingIntentExtras(mActivity); + if (intentCameraId != -1) { + // Testing purpose. Launch a specific camera through the intent + // extras. + return intentCameraId; + } else { + return CameraSettings.readPreferredCameraId(preferences); + } + } + + private void updateCommonManual3ASettings() { + String touchAfAec = mParameters.TOUCH_AF_AEC_OFF; + mSceneMode = Parameters.SCENE_MODE_AUTO; + String flashMode = Parameters.FLASH_MODE_OFF; + String redeyeReduction = mActivity.getString(R.string. + pref_camera_redeyereduction_entry_disable); + String aeBracketing = mActivity.getString(R.string. + pref_camera_ae_bracket_hdr_entry_off); + String colorEffect = mActivity.getString(R.string. + pref_camera_coloreffect_default); + String exposureCompensation = CameraSettings.EXPOSURE_DEFAULT_VALUE; + + if (mManual3AEnabled > 0) { + overrideCameraSettings(flashMode, null, null, + exposureCompensation, touchAfAec, + mParameters.getAutoExposure(), + Integer.toString(mParameters.getSaturation()), + Integer.toString(mParameters.getContrast()), + Integer.toString(mParameters.getSharpness()), + colorEffect, + mSceneMode, redeyeReduction, aeBracketing); + mUI.overrideSettings(CameraSettings.KEY_LONGSHOT, + mActivity.getString(R.string.setting_off_value)); + } else { + //enable all + touchAfAec = mActivity.getString( + R.string.pref_camera_touchafaec_default); + overrideCameraSettings(null, null, null, + null, touchAfAec, null, + null, null, null, null, + null, null, null); + mUI.overrideSettings(CameraSettings.KEY_LONGSHOT, null); + } + + String isoMode = mParameters.getISOValue(); + final String isoManual = CameraSettings.KEY_MANUAL_ISO; + if (isoMode.equals(isoManual)) { + final String isoPref = mPreferences.getString( + CameraSettings.KEY_ISO, + mActivity.getString(R.string.pref_camera_iso_default)); + mUI.overrideSettings(CameraSettings.KEY_ISO, isoPref); + } + if ((mManual3AEnabled & MANUAL_WB) != 0) { + String whiteBalance = mPreferences.getString( + CameraSettings.KEY_WHITE_BALANCE, + mActivity.getString(R.string.pref_camera_whitebalance_default)); + mUI.overrideSettings(CameraSettings.KEY_WHITE_BALANCE, whiteBalance); + } + if ((mManual3AEnabled & MANUAL_FOCUS) != 0) { + mUI.overrideSettings(CameraSettings.KEY_FOCUS_MODE, + mFocusManager.getFocusMode()); + } + } + + private void updateCameraSettings() { + String sceneMode = null; + String flashMode = null; + String redeyeReduction = null; + String aeBracketing = null; + String focusMode = null; + String colorEffect = null; + String exposureCompensation = null; + String touchAfAec = null; + boolean disableLongShot = false; + + String ubiFocusOn = mActivity.getString(R.string. + pref_camera_advanced_feature_value_ubifocus_on); + String continuousShotOn = + mActivity.getString(R.string.setting_on_value); + String reFocusOn = mActivity.getString(R.string. + pref_camera_advanced_feature_value_refocus_on); + String chromaFlashOn = mActivity.getString(R.string. + pref_camera_advanced_feature_value_chromaflash_on); + String optiZoomOn = mActivity.getString(R.string. + pref_camera_advanced_feature_value_optizoom_on); + String fssrOn = mActivity.getString(R.string. + pref_camera_advanced_feature_value_FSSR_on); + String truPortraitOn = mActivity.getString(R.string. + pref_camera_advanced_feature_value_trueportrait_on); + String multiTouchFocusOn = mActivity.getString(R.string. + pref_camera_advanced_feature_value_multi_touch_focus_on); + String optiZoom = + mParameters.get(CameraSettings.KEY_QC_OPTI_ZOOM); + String chromaFlash = + mParameters.get(CameraSettings.KEY_QC_CHROMA_FLASH); + String ubiFocus = + mParameters.get(CameraSettings.KEY_QC_AF_BRACKETING); + String fssr = + mParameters.get(CameraSettings.KEY_QC_FSSR); + String truePortrait = + mParameters.get(CameraSettings.KEY_QC_TP); + String multiTouchFocus = + mParameters.get(CameraSettings.KEY_QC_MULTI_TOUCH_FOCUS); + String stillMoreOn = mActivity.getString(R.string. + pref_camera_advanced_feature_value_stillmore_on); + String stillMore = + mParameters.get(CameraSettings.KEY_QC_STILL_MORE); + String continuousShot = + mParameters.get("long-shot"); + + if (mManual3AEnabled > 0) { + disableLongShot = true; + } + + if ((continuousShot != null) && continuousShot.equals(continuousShotOn)) { + String pictureFormat = mActivity.getString(R.string. + pref_camera_picture_format_value_jpeg); + mUI.overrideSettings(CameraSettings.KEY_PICTURE_FORMAT, pictureFormat); + } else { + mUI.overrideSettings(CameraSettings.KEY_PICTURE_FORMAT, null); + } + String reFocus = + mParameters.get(CameraSettings.KEY_QC_RE_FOCUS); + + if (mFocusManager.isZslEnabled()) { + String pictureFormat = mActivity.getString(R.string. + pref_camera_picture_format_value_jpeg); + mUI.overrideSettings(CameraSettings.KEY_PICTURE_FORMAT, pictureFormat); + } else { + mUI.overrideSettings(CameraSettings.KEY_PICTURE_FORMAT, null); + } + if ((multiTouchFocus != null && multiTouchFocus.equals(multiTouchFocusOn)) || + (chromaFlash != null && chromaFlash.equals(chromaFlashOn)) || + (optiZoom != null && optiZoom.equals(optiZoomOn)) || + (fssr != null && fssr.equals(fssrOn)) || + (truePortrait != null && truePortrait.equals(truPortraitOn)) || + (stillMore != null && stillMore.equals(stillMoreOn))) { + if (optiZoom != null && optiZoom.equals(optiZoomOn)) { + sceneMode = null; + } else { + mSceneMode = sceneMode = Parameters.SCENE_MODE_AUTO; + } + flashMode = Parameters.FLASH_MODE_OFF; + focusMode = Parameters.FOCUS_MODE_INFINITY; + redeyeReduction = mActivity.getString(R.string. + pref_camera_redeyereduction_entry_disable); + aeBracketing = mActivity.getString(R.string. + pref_camera_ae_bracket_hdr_entry_off); + colorEffect = mActivity.getString(R.string. + pref_camera_coloreffect_default); + exposureCompensation = CameraSettings.EXPOSURE_DEFAULT_VALUE; + + overrideCameraSettings(null, null, focusMode, + exposureCompensation, touchAfAec, null, + null, null, null, colorEffect, + sceneMode, redeyeReduction, aeBracketing); + disableLongShot = true; + } + + // If scene mode is set, for white balance and focus mode + // read settings from preferences so we retain user preferences. + if (!Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) { + flashMode = mParameters.FLASH_MODE_OFF; + String whiteBalance = Parameters.WHITE_BALANCE_AUTO; + focusMode = mFocusManager.getFocusMode(); + colorEffect = mParameters.getColorEffect(); + String defaultEffect = mActivity.getString(R.string.pref_camera_coloreffect_default); + if (CameraUtil.SCENE_MODE_HDR.equals(mSceneMode) + && colorEffect != null & !colorEffect.equals(defaultEffect)) { + disableLongShot = true; + // Change the colorEffect to default(None effect) when HDR ON. + colorEffect = defaultEffect; + mUI.setPreference(CameraSettings.KEY_COLOR_EFFECT, colorEffect); + mParameters.setColorEffect(colorEffect); + mCameraDevice.setParameters(mParameters); + mParameters = mCameraDevice.getParameters(); + } + exposureCompensation = + Integer.toString(mParameters.getExposureCompensation()); + touchAfAec = mCurrTouchAfAec; + + overrideCameraSettings(null, whiteBalance, focusMode, + exposureCompensation, touchAfAec, + mParameters.getAutoExposure(), + Integer.toString(mParameters.getSaturation()), + Integer.toString(mParameters.getContrast()), + Integer.toString(mParameters.getSharpness()), + colorEffect, + sceneMode, redeyeReduction, aeBracketing); + } else if (mFocusManager.isZslEnabled()) { + focusMode = mParameters.getFocusMode(); + overrideCameraSettings(null, null, focusMode, + exposureCompensation, touchAfAec, null, + null, null, null, colorEffect, + sceneMode, redeyeReduction, aeBracketing); + } else { + if (mManual3AEnabled > 0) { + updateCommonManual3ASettings(); + } else { + overrideCameraSettings(null, null, focusMode, + exposureCompensation, touchAfAec, null, + null, null, null, colorEffect, + sceneMode, redeyeReduction, aeBracketing); + } + } + /* Disable focus if aebracket is ON */ + String aeBracket = mParameters.get(CameraSettings.KEY_QC_AE_BRACKETING); + if (!aeBracket.equalsIgnoreCase("off")) { + flashMode = Parameters.FLASH_MODE_OFF; + mParameters.setFlashMode(flashMode); + } + if (disableLongShot) { + mUI.overrideSettings(CameraSettings.KEY_LONGSHOT, + mActivity.getString(R.string.setting_off_value)); + } else { + mUI.overrideSettings(CameraSettings.KEY_LONGSHOT, null); + } + + if (flashMode == null) { + // Restore saved flash mode or default mode + if (mSavedFlashMode == null) { + mSavedFlashMode = mPreferences.getString( + CameraSettings.KEY_FLASH_MODE, + mActivity.getString(R.string.pref_camera_flashmode_default)); + } + mUI.setPreference(CameraSettings.KEY_FLASH_MODE, mSavedFlashMode); + mSavedFlashMode = null; + } else { + // Save the current flash mode + if (mSavedFlashMode == null) { + mSavedFlashMode = mPreferences.getString( + CameraSettings.KEY_FLASH_MODE, + mActivity.getString(R.string.pref_camera_flashmode_default)); + } + mUI.overrideSettings(CameraSettings.KEY_FLASH_MODE, flashMode); + } + + if(mCameraId != CameraHolder.instance().getFrontCameraId()) + CameraSettings.removePreferenceFromScreen(mPreferenceGroup, CameraSettings.KEY_SELFIE_FLASH); + } + + private void overrideCameraSettings(final String flashMode, + final String whiteBalance, final String focusMode, + final String exposureMode, final String touchMode, + final String autoExposure, final String saturation, + final String contrast, final String sharpness, + final String coloreffect, final String sceneMode, + final String redeyeReduction, final String aeBracketing) { + mUI.overrideSettings( + CameraSettings.KEY_FLASH_MODE, flashMode, + CameraSettings.KEY_WHITE_BALANCE, whiteBalance, + CameraSettings.KEY_FOCUS_MODE, focusMode, + CameraSettings.KEY_EXPOSURE, exposureMode, + CameraSettings.KEY_TOUCH_AF_AEC, touchMode, + CameraSettings.KEY_AUTOEXPOSURE, autoExposure, + CameraSettings.KEY_SATURATION, saturation, + CameraSettings.KEY_CONTRAST, contrast, + CameraSettings.KEY_SHARPNESS, sharpness, + CameraSettings.KEY_COLOR_EFFECT, coloreffect, + CameraSettings.KEY_SCENE_MODE, sceneMode, + CameraSettings.KEY_REDEYE_REDUCTION, redeyeReduction, + CameraSettings.KEY_AE_BRACKET_HDR, aeBracketing); + } + + private void loadCameraPreferences() { + CameraSettings settings = new CameraSettings(mActivity, mInitialParams, + mCameraId, CameraHolder.instance().getCameraInfo()); + mPreferenceGroup = settings.getPreferenceGroup(R.xml.camera_preferences); + + int numOfCams = Camera.getNumberOfCameras(); + + Log.e(TAG,"loadCameraPreferences() updating camera_id pref"); + + IconListPreference switchIconPref = + (IconListPreference)mPreferenceGroup.findPreference( + CameraSettings.KEY_CAMERA_ID); + + //if numOfCams < 2 then switchIconPref will be null as there is no switch icon in this case + if (switchIconPref == null) + return; + + int[] iconIds = new int[numOfCams]; + String[] entries = new String[numOfCams]; + String[] labels = new String[numOfCams]; + int[] largeIconIds = new int[numOfCams]; + + for(int i=0;i<numOfCams;i++) { + CameraInfo info = CameraHolder.instance().getCameraInfo()[i]; + if(info.facing == CameraInfo.CAMERA_FACING_BACK) { + iconIds[i] = R.drawable.ic_switch_back; + entries[i] = mActivity.getResources().getString(R.string.pref_camera_id_entry_back); + labels[i] = mActivity.getResources().getString(R.string.pref_camera_id_label_back); + largeIconIds[i] = R.drawable.ic_switch_back; + } else { + iconIds[i] = R.drawable.ic_switch_front; + entries[i] = mActivity.getResources().getString(R.string.pref_camera_id_entry_front); + labels[i] = mActivity.getResources().getString(R.string.pref_camera_id_label_front); + largeIconIds[i] = R.drawable.ic_switch_front; + } + } + + switchIconPref.setIconIds(iconIds); + switchIconPref.setEntries(entries); + switchIconPref.setLabels(labels); + switchIconPref.setLargeIconIds(largeIconIds); + + } + + @Override + public void onOrientationChanged(int orientation) { + // We keep the last known orientation. So if the user first orient + // the camera then point the camera to floor or sky, we still have + // the correct orientation. + if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) return; + int oldOrientation = mOrientation; + mOrientation = CameraUtil.roundOrientation(orientation, mOrientation); + if (oldOrientation != mOrientation) { + if (mParameters != null && mCameraDevice != null && mCameraState == IDLE) { + Log.v(TAG, "onOrientationChanged, update parameters"); + synchronized (mCameraDevice) { + setFlipValue(); + mCameraDevice.setParameters(mParameters); + } + } + mUI.setOrientation(mOrientation, true); + if (mGraphView != null) { + mGraphView.setRotation(-mOrientation); + } + } + + // Show the toast after getting the first orientation changed. + if (mHandler.hasMessages(SHOW_TAP_TO_FOCUS_TOAST)) { + mHandler.removeMessages(SHOW_TAP_TO_FOCUS_TOAST); + showTapToFocusToast(); + } + + // need to re-initialize mGraphView to show histogram on rotate + mGraphView = (GraphView)mRootView.findViewById(R.id.graph_view); + if(mGraphView != null){ + mGraphView.setAlpha(0.75f); + mGraphView.setPhotoModuleObject(this); + mGraphView.PreviewChanged(); + } + } + + @Override + public void onStop() {} + + @Override + public void onCaptureCancelled() { + mActivity.setResultEx(Activity.RESULT_CANCELED, new Intent()); + mActivity.finish(); + } + + @Override + public void onCaptureRetake() { + if (mPaused) + return; + mUI.hidePostCaptureAlert(); + setupPreview(); + } + + @Override + public void onCaptureDone() { + if (mPaused) { + return; + } + + byte[] data = mJpegImageData; + + if (mCropValue == null) { + // First handle the no crop case -- just return the value. If the + // caller specifies a "save uri" then write the data to its + // stream. Otherwise, pass back a scaled down version of the bitmap + // directly in the extras. + if (mSaveUri != null) { + OutputStream outputStream = null; + try { + outputStream = mContentResolver.openOutputStream(mSaveUri); + outputStream.write(data); + outputStream.close(); + + mActivity.setResultEx(Activity.RESULT_OK); + mActivity.finish(); + } catch (IOException ex) { + // ignore exception + } finally { + CameraUtil.closeSilently(outputStream); + } + } else { + ExifInterface exif = Exif.getExif(data); + int orientation = Exif.getOrientation(exif); + Bitmap bitmap = CameraUtil.makeBitmap(data, 50 * 1024); + bitmap = CameraUtil.rotate(bitmap, orientation); + mActivity.setResultEx(Activity.RESULT_OK, + new Intent("inline-data").putExtra("data", bitmap)); + mActivity.finish(); + } + } else { + // Save the image to a temp file and invoke the cropper + Uri tempUri = null; + FileOutputStream tempStream = null; + try { + File path = mActivity.getFileStreamPath(sTempCropFilename); + path.delete(); + tempStream = mActivity.openFileOutput(sTempCropFilename, 0); + tempStream.write(data); + tempStream.close(); + tempUri = Uri.fromFile(path); + } catch (FileNotFoundException ex) { + mActivity.setResultEx(Activity.RESULT_CANCELED); + mActivity.finish(); + return; + } catch (IOException ex) { + mActivity.setResultEx(Activity.RESULT_CANCELED); + mActivity.finish(); + return; + } finally { + CameraUtil.closeSilently(tempStream); + } + + Bundle newExtras = new Bundle(); + if (mCropValue.equals("circle")) { + newExtras.putString("circleCrop", "true"); + } + if (mSaveUri != null) { + newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, mSaveUri); + } else { + newExtras.putBoolean(CameraUtil.KEY_RETURN_DATA, true); + } + if (mActivity.isSecureCamera()) { + newExtras.putBoolean(CameraUtil.KEY_SHOW_WHEN_LOCKED, true); + } + + // TODO: Share this constant. + final String CROP_ACTION = "com.android.camera.action.CROP"; + Intent cropIntent = new Intent(CROP_ACTION); + + cropIntent.setData(tempUri); + cropIntent.putExtras(newExtras); + + mActivity.startActivityForResult(cropIntent, REQUEST_CROP); + } + } + + @Override + public void onShutterButtonFocus(boolean pressed) { + if (mCameraDevice == null + || mPaused || mUI.collapseCameraControls() + || (mCameraState == SNAPSHOT_IN_PROGRESS) + || (mCameraState == PREVIEW_STOPPED) + || (null == mFocusManager)) { + Log.v(TAG, "onShutterButtonFocus error case mCameraState = " + mCameraState + + "mCameraDevice = " + mCameraDevice + "mPaused =" + mPaused); + return; + } + + synchronized(mCameraDevice) { + if (mCameraState == LONGSHOT) { + mLongshotActive = false; + mCameraDevice.setLongshot(false); + mUI.animateCapture(mLastJpegData, mLastJpegOrientation, mMirror); + mLastJpegData = null; + if (!mFocusManager.isZslEnabled()) { + setupPreview(); + } else { + setCameraState(IDLE); + mFocusManager.resetTouchFocus(); + if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals( + mFocusManager.getFocusMode())) { + mCameraDevice.cancelAutoFocus(); + } + mUI.resumeFaceDetection(); + } + } + } + + // Do not do focus if there is not enough storage. + if (pressed && !canTakePicture()) return; + + if (pressed) { + mFocusManager.onShutterDown(); + } else { + // for countdown mode, we need to postpone the shutter release + // i.e. lock the focus during countdown. + if (!mUI.isCountingDown()) { + mFocusManager.onShutterUp(); + } + } + } + + @Override + public synchronized void onShutterButtonClick() { + if ((mCameraDevice == null) + || mPaused || mUI.collapseCameraControls() + || (mCameraState == SWITCHING_CAMERA) + || (mCameraState == PREVIEW_STOPPED) + || (mCameraState == LONGSHOT) + || (null == mFocusManager)) return; + + // Do not take the picture if there is not enough storage. + if (mActivity.getStorageSpaceBytes() <= Storage.LOW_STORAGE_THRESHOLD_BYTES) { + Log.i(TAG, "Not enough space or storage not ready. remaining=" + + mActivity.getStorageSpaceBytes()); + return; + } + Log.v(TAG, "onShutterButtonClick: mCameraState=" + mCameraState); + + if (mSceneMode == CameraUtil.SCENE_MODE_HDR) { + mUI.hideSwitcher(); + mUI.setSwipingEnabled(false); + } + + //Need to disable focus for ZSL mode + if (mFocusManager != null) { + if (mSnapshotMode == CameraInfo.CAMERA_SUPPORT_MODE_ZSL) { + mFocusManager.setZslEnable(true); + } else { + mFocusManager.setZslEnable(false); + } + } + + // If the user wants to do a snapshot while the previous one is still + // in progress, remember the fact and do it after we finish the previous + // one and re-start the preview. Snapshot in progress also includes the + // state that autofocus is focusing and a picture will be taken when + // focus callback arrives. + if ((((mFocusManager != null) && mFocusManager.isFocusingSnapOnFinish()) + || mCameraState == SNAPSHOT_IN_PROGRESS) + && !mIsImageCaptureIntent) { + mSnapshotOnIdle = true; + return; + } + + String timer = mPreferences.getString( + CameraSettings.KEY_TIMER, + mActivity.getString(R.string.pref_camera_timer_default)); + boolean playSound = mPreferences.getString(CameraSettings.KEY_TIMER_SOUND_EFFECTS, + mActivity.getString(R.string.pref_camera_timer_sound_default)) + .equals(mActivity.getString(R.string.setting_on_value)); + + int seconds = Integer.parseInt(timer); + // When shutter button is pressed, check whether the previous countdown is + // finished. If not, cancel the previous countdown and start a new one. + if (mUI.isCountingDown()) { + mUI.cancelCountDown(); + } + if (seconds > 0) { + String zsl = mPreferences.getString(CameraSettings.KEY_ZSL, + mActivity.getString(R.string.pref_camera_zsl_default)); + mUI.overrideSettings(CameraSettings.KEY_ZSL, zsl); + mUI.startCountDown(seconds, playSound); + + } else { + mSnapshotOnIdle = false; + initiateSnap(); + } + } + + private void initiateSnap() + { + if(mPreferences.getString(CameraSettings.KEY_SELFIE_FLASH, + mActivity.getString(R.string.pref_selfie_flash_default)) + .equalsIgnoreCase("on") && + mCameraId == CameraHolder.instance().getFrontCameraId()) { + mUI.startSelfieFlash(); + if(selfieThread == null) { + selfieThread = new SelfieThread(); + selfieThread.start(); + } + } else { + mFocusManager.doSnap(); + } + } + + @Override + public void onShutterButtonLongClick() { + // Do not take the picture if there is not enough storage. + if (mActivity.getStorageSpaceBytes() <= Storage.LOW_STORAGE_THRESHOLD_BYTES) { + Log.i(TAG, "Not enough space or storage not ready. remaining=" + + mActivity.getStorageSpaceBytes()); + return; + } + + if ((null != mCameraDevice) && ((mCameraState == IDLE) || (mCameraState == FOCUSING))) { + //Add on/off Menu for longshot + String longshot_enable = mPreferences.getString( + CameraSettings.KEY_LONGSHOT, + mActivity.getString(R.string.pref_camera_longshot_default)); + + Log.d(TAG, "longshot_enable = " + longshot_enable); + if (longshot_enable.equals("on")) { + boolean enable = SystemProperties.getBoolean(PERSIST_LONG_SAVE, false); + mLongshotSave = enable; + + //Cancel the previous countdown when long press shutter button for longshot. + if (mUI.isCountingDown()) { + mUI.cancelCountDown(); + } + //check whether current memory is enough for longshot. + mRemainedMemCheckingCount = 0; + if(isLongshotNeedCancel()) { + return; + } + mLongshotActive = true; + setCameraState(PhotoController.LONGSHOT); + mFocusManager.doSnap(); + } + } + } + + @Override + public void installIntentFilter() { + // Do nothing. + } + + @Override + public boolean updateStorageHintOnResume() { + return mFirstTimeInitialized; + } + + @Override + public void onResumeBeforeSuper() { + mPaused = false; + mPreferences = new ComboPreferences(mActivity); + CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal(), mActivity); + mCameraId = getPreferredCameraId(mPreferences); + mPreferences.setLocalId(mActivity, mCameraId); + CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); + } + + private void openCamera() { + // We need to check whether the activity is paused before long + // operations to ensure that onPause() can be done ASAP. + if (mPaused) { + return; + } + Log.v(TAG, "Open camera device."); + mCameraDevice = CameraUtil.openCamera( + mActivity, mCameraId, mHandler, + mActivity.getCameraOpenErrorCallback()); + if (mCameraDevice == null) { + Log.e(TAG, "Failed to open camera:" + mCameraId); + mHandler.sendEmptyMessage(OPEN_CAMERA_FAIL); + return; + } + mParameters = mCameraDevice.getParameters(); + mCameraPreviewParamsReady = true; + mInitialParams = mParameters; + if (mFocusManager == null) initializeFocusManager(); + initializeCapabilities(); + mHandler.sendEmptyMessageDelayed(CAMERA_OPEN_DONE,100); + return; + } + + @Override + public void onResumeAfterSuper() { + mLastPhotoTakenWithRefocus = false; + // Add delay on resume from lock screen only, in order to to speed up + // the onResume --> onPause --> onResume cycle from lock screen. + // Don't do always because letting go of thread can cause delay. + String action = mActivity.getIntent().getAction(); + if (MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA.equals(action) + || MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action)) { + Log.v(TAG, "On resume, from lock screen."); + // Note: onPauseAfterSuper() will delete this runnable, so we will + // at most have 1 copy queued up. + mHandler.postDelayed(new Runnable() { + public void run() { + onResumeTasks(); + } + }, ON_RESUME_TASKS_DELAY_MSEC); + } else { + Log.v(TAG, "On resume."); + onResumeTasks(); + } + + mUI.setSwitcherIndex(); + if (mSoundPool == null) { + mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); + mRefocusSound = mSoundPool.load(mActivity, R.raw.camera_click_x5, 1); + } + + mHandler.post(new Runnable(){ + @Override + public void run(){ + mActivity.updateStorageSpaceAndHint(); + updateRemainingPhotos(); + } + }); + } + + private void updateRemainingPhotos() { + if (mJpegFileSizeEstimation != 0) { + mRemainingPhotos = (int) + ((mActivity.getStorageSpaceBytes() - Storage.LOW_STORAGE_THRESHOLD_BYTES) + / mJpegFileSizeEstimation); + } else { + mRemainingPhotos = -1; + } + mUI.updateRemainingPhotos(mRemainingPhotos); + } + + private void onResumeTasks() { + Log.v(TAG, "Executing onResumeTasks."); + if (mOpenCameraFail || mCameraDisabled) return; + + if (mOpenCameraThread == null) { + mOpenCameraThread = new OpenCameraThread(); + mOpenCameraThread.start(); + } + + mJpegPictureCallbackTime = 0; + mZoomValue = 0; + + // If first time initialization is not finished, put it in the + // message queue. + if (!mFirstTimeInitialized) { + mHandler.sendEmptyMessage(FIRST_TIME_INIT); + } else { + initializeSecondTime(); + } + mUI.initDisplayChangeListener(); + keepScreenOnAwhile(); + mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup, + mPreferences); + + UsageStatistics.onContentViewChanged( + UsageStatistics.COMPONENT_CAMERA, "PhotoModule"); + + Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + if (gsensor != null) { + mSensorManager.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_NORMAL); + } + + Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); + if (msensor != null) { + mSensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_NORMAL); + } + + mOnResumeTime = SystemClock.uptimeMillis(); + checkDisplayRotation(); + + mAnimateCapture = SystemProperties.getBoolean( + PERSIST_CAPTURE_ANIMATION, true); + } + + @Override + public void onPauseBeforeSuper() { + mPaused = true; + Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + if (gsensor != null) { + mSensorManager.unregisterListener(this, gsensor); + } + + Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); + if (msensor != null) { + mSensorManager.unregisterListener(this, msensor); + } + + if (mSoundPool != null) { + mSoundPool.release(); + mSoundPool = null; + } + + if(selfieThread != null) { + selfieThread.interrupt(); + } + mUI.stopSelfieFlash(); + + Log.d(TAG, "remove idle handleer in onPause"); + removeIdleHandler(); + } + + @Override + public void onPauseAfterSuper() { + Log.v(TAG, "On pause."); + mUI.showPreviewCover(); + + try { + if (mOpenCameraThread != null) { + mOpenCameraThread.join(); + } + } catch (InterruptedException ex) { + // ignore + } + mOpenCameraThread = null; + // Reset the focus first. Camera CTS does not guarantee that + // cancelAutoFocus is allowed after preview stops. + if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) { + mCameraDevice.cancelAutoFocus(); + } + resetManual3ASettings(); + // If the camera has not been opened asynchronously yet, + // and startPreview hasn't been called, then this is a no-op. + // (e.g. onResume -> onPause -> onResume). + stopPreview(); + + mNamedImages = null; + + if (mLocationManager != null) mLocationManager.recordLocation(false); + + // If we are in an image capture intent and has taken + // a picture, we just clear it in onPause. + mJpegImageData = null; + + // Remove the messages and runnables in the queue. + mHandler.removeCallbacksAndMessages(null); + + closeCamera(); + + resetScreenOn(); + mUI.onPause(); + + mPendingSwitchCameraId = -1; + if (mFocusManager != null) mFocusManager.removeMessages(); + MediaSaveService s = mActivity.getMediaSaveService(); + if (s != null) { + s.setListener(null); + } + mUI.removeDisplayChangeListener(); + } + + /** + * The focus manager is the first UI related element to get initialized, + * and it requires the RenderOverlay, so initialize it here + */ + private void initializeFocusManager() { + // Create FocusManager object. startPreview needs it. + // if mFocusManager not null, reuse it + // otherwise create a new instance + if (mFocusManager != null) { + mFocusManager.removeMessages(); + } else { + CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; + mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); + String[] defaultFocusModes = mActivity.getResources().getStringArray( + R.array.pref_camera_focusmode_default_array); + mFocusManager = new FocusOverlayManager(mPreferences, defaultFocusModes, + mInitialParams, this, mMirror, + mActivity.getMainLooper(), mUI); + } + } + + private void updateFocusManager(PhotoUI mUI) { + // Idea here is to let focus manager create in camera open thread + // (in initializeFocusManager) even if photoUI is null by that time so + // as to not block start preview process. Once UI creation is done, + // we will update focus manager with proper UI. + if (mFocusManager != null && mUI != null) { + mFocusManager.setPhotoUI(mUI); + + View root = mUI.getRootView(); + // These depend on camera parameters. + int width = root.getWidth(); + int height = root.getHeight(); + mFocusManager.setPreviewSize(width, height); + } + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + Log.v(TAG, "onConfigurationChanged"); + setDisplayOrientation(); + resizeForPreviewAspectRatio(); + } + + @Override + public void updateCameraOrientation() { + if (mDisplayRotation != CameraUtil.getDisplayRotation(mActivity)) { + setDisplayOrientation(); + } + } + + @Override + public void onActivityResult( + int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case REQUEST_CROP: { + Intent intent = new Intent(); + if (data != null) { + Bundle extras = data.getExtras(); + if (extras != null) { + intent.putExtras(extras); + } + } + mActivity.setResultEx(resultCode, intent); + mActivity.finish(); + + File path = mActivity.getFileStreamPath(sTempCropFilename); + path.delete(); + + break; + } + } + } + + protected CameraManager.CameraProxy getCamera() { + return mCameraDevice; + } + + private boolean canTakePicture() { + return isCameraIdle() && (mActivity.getStorageSpaceBytes() > Storage.LOW_STORAGE_THRESHOLD_BYTES); + } + + @Override + public void autoFocus() { + mFocusStartTime = System.currentTimeMillis(); + mCameraDevice.autoFocus(mHandler, mAutoFocusCallback); + setCameraState(FOCUSING); + } + + @Override + public void cancelAutoFocus() { + if (null != mCameraDevice ) { + mCameraDevice.cancelAutoFocus(); + setCameraState(IDLE); + setCameraParameters(UPDATE_PARAM_PREFERENCE); + } + } + + // Preview area is touched. Handle touch focus. + @Override + public void onSingleTapUp(View view, int x, int y) { + if (mPaused || mCameraDevice == null || !mFirstTimeInitialized + || mCameraState == SNAPSHOT_IN_PROGRESS + || mCameraState == SWITCHING_CAMERA + || mCameraState == PREVIEW_STOPPED) { + return; + } + //If Touch AF/AEC is disabled in UI, return + if(this.mTouchAfAecFlag == false) { + return; + } + // Check if metering area or focus area is supported. + if (!mFocusAreaSupported && !mMeteringAreaSupported) return; + if (! mFocusManager.getPreviewRect().contains(x, y)) return; + mFocusManager.onSingleTapUp(x, y); + } + + @Override + public boolean onBackPressed() { + return mUI.onBackPressed(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_DOWN: + if (CameraUtil.volumeKeyShutterDisable(mActivity)) { + return false; + } + case KeyEvent.KEYCODE_FOCUS: + if (/*TODO: mActivity.isInCameraApp() &&*/ mFirstTimeInitialized) { + if (event.getRepeatCount() == 0) { + onShutterButtonFocus(true); + } + return true; + } + return false; + case KeyEvent.KEYCODE_CAMERA: + if (mFirstTimeInitialized && event.getRepeatCount() == 0) { + onShutterButtonClick(); + } + return true; + case KeyEvent.KEYCODE_DPAD_LEFT: + if ( (mCameraState != PREVIEW_STOPPED) && (mFocusManager != null) && + (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING) && + (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING_SNAP_ON_FINISH) ) { + if (mbrightness > MINIMUM_BRIGHTNESS) { + mbrightness-=mbrightness_step; + synchronized (mCameraDevice) { + /* Set the "luma-adaptation" parameter */ + mParameters = mCameraDevice.getParameters(); + mParameters.set("luma-adaptation", String.valueOf(mbrightness)); + mCameraDevice.setParameters(mParameters); + } + } + brightnessProgressBar.setProgress(mbrightness); + Editor editor = mPreferences.edit(); + editor.putInt(CameraSettings.KEY_BRIGHTNESS, mbrightness); + editor.apply(); + brightnessProgressBar.setVisibility(View.INVISIBLE); + mBrightnessVisible = true; + } + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + if ( (mCameraState != PREVIEW_STOPPED) && (mFocusManager != null) && + (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING) && + (mFocusManager.getCurrentFocusState() != mFocusManager.STATE_FOCUSING_SNAP_ON_FINISH) ) { + if (mbrightness < MAXIMUM_BRIGHTNESS) { + mbrightness+=mbrightness_step; + synchronized (mCameraDevice) { + /* Set the "luma-adaptation" parameter */ + mParameters = mCameraDevice.getParameters(); + mParameters.set("luma-adaptation", String.valueOf(mbrightness)); + mCameraDevice.setParameters(mParameters); + } + } + brightnessProgressBar.setProgress(mbrightness); + Editor editor = mPreferences.edit(); + editor.putInt(CameraSettings.KEY_BRIGHTNESS, mbrightness); + editor.apply(); + brightnessProgressBar.setVisibility(View.INVISIBLE); + mBrightnessVisible = true; + } + break; + case KeyEvent.KEYCODE_DPAD_CENTER: + // If we get a dpad center event without any focused view, move + // the focus to the shutter button and press it. + if (mFirstTimeInitialized && event.getRepeatCount() == 0) { + // Start auto-focus immediately to reduce shutter lag. After + // the shutter button gets the focus, onShutterButtonFocus() + // will be called again but it is fine. + onShutterButtonFocus(true); + mUI.pressShutterButton(); + } + return true; + } + return false; + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_DOWN: + if (/*mActivity.isInCameraApp() && */ mFirstTimeInitialized + && !CameraUtil.volumeKeyShutterDisable(mActivity)) { + onShutterButtonClick(); + return true; + } + return false; + case KeyEvent.KEYCODE_FOCUS: + if (mFirstTimeInitialized) { + onShutterButtonFocus(false); + } + return true; + } + return false; + } + + private void closeCamera() { + Log.v(TAG, "Close camera device."); + if (mCameraDevice != null) { + mCameraDevice.setZoomChangeListener(null); + mCameraDevice.setFaceDetectionCallback(null, null); + mCameraDevice.setErrorCallback(null); + + if (mActivity.isSecureCamera()) { + // Blocks until camera is actually released. + CameraHolder.instance().strongRelease(); + } else { + CameraHolder.instance().release(); + } + + mFaceDetectionStarted = false; + mCameraDevice = null; + setCameraState(PREVIEW_STOPPED); + if (mFocusManager != null) { + mFocusManager.onCameraReleased(); + } + } + } + + private void setDisplayOrientation() { + mDisplayRotation = CameraUtil.getDisplayRotation(mActivity); + mDisplayOrientation = CameraUtil.getDisplayOrientation(mDisplayRotation, mCameraId); + mCameraDisplayOrientation = mDisplayOrientation; + // This will be called again in checkDisplayRotation(), so there + // should not be any problem even if mUI is null. + if (mUI != null) { + mUI.setDisplayOrientation(mDisplayOrientation); + } + if (mFocusManager != null) { + mFocusManager.setDisplayOrientation(mDisplayOrientation); + } + // Change the camera display orientation + if (mCameraDevice != null) { + mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation); + } + } + + /** Only called by UI thread. */ + private void setupPreview() { + mFocusManager.resetTouchFocus(); + startPreview(); + } + + /** This can run on a background thread, so don't do UI updates here. Post any + view updates to MainHandler or do it on onPreviewStarted() . */ + private void startPreview() { + if (mPaused || mCameraDevice == null || mParameters == null) { + return; + } + + synchronized (mCameraDevice) { + SurfaceHolder sh = null; + Log.v(TAG, "startPreview: SurfaceHolder (MDP path)"); + if (mUI != null) { + sh = mUI.getSurfaceHolder(); + } + + // Let UI set its expected aspect ratio + mCameraDevice.setPreviewDisplay(sh); + } + + if (!mCameraPreviewParamsReady) { + Log.w(TAG, "startPreview: parameters for preview are not ready."); + return; + } + mErrorCallback.setActivity(mActivity); + mCameraDevice.setErrorCallback(mErrorCallback); + // ICS camera frameworks has a bug. Face detection state is not cleared 1589 + // after taking a picture. Stop the preview to work around it. The bug + // was fixed in JB. + if (mCameraState != PREVIEW_STOPPED && mCameraState != INIT) { + stopPreview(); + } + + if (!mSnapshotOnIdle) { + mFocusManager.setAeAwbLock(false); // Unlock AE and AWB. + } + + setCameraParameters(UPDATE_PARAM_ALL); + mCameraDevice.setOneShotPreviewCallback(mHandler, + new CameraManager.CameraPreviewDataCallback() { + @Override + public void onPreviewFrame(byte[] data, CameraProxy camera) { + mUI.hidePreviewCover(); + } + }); + mCameraDevice.startPreview(); + + mHandler.sendEmptyMessage(ON_PREVIEW_STARTED); + + setDisplayOrientation(); + + if (!mSnapshotOnIdle) { + // If the focus mode is continuous autofocus, call cancelAutoFocus to + // resume it because it may have been paused by autoFocus call. + if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode())) { + mCameraDevice.cancelAutoFocus(); + } + } else { + mHandler.post(mDoSnapRunnable); + } + } + + @Override + public void stopPreview() { + if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) { + Log.v(TAG, "stopPreview"); + mCameraDevice.stopPreview(); + } + setCameraState(PREVIEW_STOPPED); + if (mFocusManager != null) mFocusManager.onPreviewStopped(); + stopFaceDetection(); + } + + @SuppressWarnings("deprecation") + private void updateCameraParametersInitialize() { + // Reset preview frame rate to the maximum because it may be lowered by + // video camera application. + int[] fpsRange = CameraUtil.getPhotoPreviewFpsRange(mParameters); + if (fpsRange != null && fpsRange.length > 0) { + mParameters.setPreviewFpsRange( + fpsRange[Parameters.PREVIEW_FPS_MIN_INDEX], + fpsRange[Parameters.PREVIEW_FPS_MAX_INDEX]); + } + + mParameters.set(CameraUtil.RECORDING_HINT, CameraUtil.FALSE); + + // Disable video stabilization. Convenience methods not available in API + // level <= 14 + String vstabSupported = mParameters.get("video-stabilization-supported"); + if ("true".equals(vstabSupported)) { + mParameters.set("video-stabilization", "false"); + } + } + + private void updateCameraParametersZoom() { + // Set zoom. + if (mParameters.isZoomSupported()) { + Parameters p = mCameraDevice.getParameters(); + mZoomValue = p.getZoom(); + mParameters.setZoom(mZoomValue); + } + } + private boolean needRestart() { + mRestartPreview = false; + String zsl = mPreferences.getString(CameraSettings.KEY_ZSL, + mActivity.getString(R.string.pref_camera_zsl_default)); + if(zsl.equals("on") && mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_ZSL + && mCameraState != PREVIEW_STOPPED) { + //Switch on ZSL Camera mode + Log.v(TAG, "Switching to ZSL Camera Mode. Restart Preview"); + mRestartPreview = true; + return mRestartPreview; + } + if(zsl.equals("off") && mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_NONZSL + && mCameraState != PREVIEW_STOPPED) { + //Switch on Normal Camera mode + Log.v(TAG, "Switching to Normal Camera Mode. Restart Preview"); + mRestartPreview = true; + return mRestartPreview; + } + return mRestartPreview; + } + + private void qcomUpdateAdvancedFeatures(String ubiFocus, + String chromaFlash, + String reFocus, + String optiZoom, + String fssr, + String truePortrait, + String multiTouchFocus, + String stillMore) { + if (CameraUtil.isSupported(ubiFocus, + CameraSettings.getSupportedAFBracketingModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_AF_BRACKETING, ubiFocus); + } + if (CameraUtil.isSupported(chromaFlash, + CameraSettings.getSupportedChromaFlashModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_CHROMA_FLASH, chromaFlash); + } + if (CameraUtil.isSupported(optiZoom, + CameraSettings.getSupportedOptiZoomModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_OPTI_ZOOM, optiZoom); + } + if (CameraUtil.isSupported(reFocus, + CameraSettings.getSupportedRefocusModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_RE_FOCUS, reFocus); + } + if (CameraUtil.isSupported(fssr, + CameraSettings.getSupportedFSSRModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_FSSR, fssr); + } + if (CameraUtil.isSupported(truePortrait, + CameraSettings.getSupportedTruePortraitModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_TP, truePortrait); + } + if(CameraUtil.isSupported(multiTouchFocus, + CameraSettings.getSupportedMultiTouchFocusModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_MULTI_TOUCH_FOCUS, multiTouchFocus); + } + if (CameraUtil.isSupported(stillMore, + CameraSettings.getSupportedStillMoreModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_STILL_MORE, stillMore); + } + } + + /** This can run on a background thread, so don't do UI updates here.*/ + private void qcomUpdateCameraParametersPreference() { + //qcom Related Parameter update + //Set Brightness. + mParameters.set("luma-adaptation", String.valueOf(mbrightness)); + + String longshot_enable = mPreferences.getString( + CameraSettings.KEY_LONGSHOT, + mActivity.getString(R.string.pref_camera_longshot_default)); + mParameters.set("long-shot", longshot_enable); + String optizoomOn = mActivity.getString(R.string + .pref_camera_advanced_feature_value_optizoom_on); + + if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode) || + CameraUtil.SCENE_MODE_HDR.equals(mSceneMode) || + optizoomOn.equals(mSceneMode)) { + // Set Touch AF/AEC parameter. + String touchAfAec = mPreferences.getString( + CameraSettings.KEY_TOUCH_AF_AEC, + mActivity.getString(R.string.pref_camera_touchafaec_default)); + if (CameraUtil.isSupported(touchAfAec, mParameters.getSupportedTouchAfAec())) { + mCurrTouchAfAec = touchAfAec; + mParameters.setTouchAfAec(touchAfAec); + } + } else { + mParameters.setTouchAfAec(mParameters.TOUCH_AF_AEC_OFF); + mFocusManager.resetTouchFocus(); + } + try { + if(mParameters.getTouchAfAec().equals(mParameters.TOUCH_AF_AEC_ON)) + this.mTouchAfAecFlag = true; + else + this.mTouchAfAecFlag = false; + } catch(Exception e){ + Log.e(TAG, "Handled NULL pointer Exception"); + } + + // Set Picture Format + // Picture Formats specified in UI should be consistent with + // PIXEL_FORMAT_JPEG and PIXEL_FORMAT_RAW constants + String pictureFormat = mPreferences.getString( + CameraSettings.KEY_PICTURE_FORMAT, + mActivity.getString(R.string.pref_camera_picture_format_default)); + + //Change picture format to JPEG if camera is start from other APK by intent. + if (mIsImageCaptureIntent && !pictureFormat.equals(PIXEL_FORMAT_JPEG)) { + pictureFormat = PIXEL_FORMAT_JPEG; + Editor editor = mPreferences.edit(); + editor.putString(CameraSettings.KEY_PICTURE_FORMAT, + mActivity.getString(R.string.pref_camera_picture_format_value_jpeg)); + editor.apply(); + } + Log.v(TAG, "Picture format value =" + pictureFormat); + mParameters.set(KEY_PICTURE_FORMAT, pictureFormat); + + // Set JPEG quality. + String jpegQuality = mPreferences.getString( + CameraSettings.KEY_JPEG_QUALITY, + mActivity.getString(R.string.pref_camera_jpegquality_default)); + //mUnsupportedJpegQuality = false; + Size pic_size = mParameters.getPictureSize(); + if (pic_size == null) { + Log.e(TAG, "error getPictureSize: size is null"); + } + else{ + if("100".equals(jpegQuality) && (pic_size.width >= 3200)){ + //mUnsupportedJpegQuality = true; + }else { + mParameters.setJpegQuality(JpegEncodingQualityMappings.getQualityNumber(jpegQuality)); + int jpegFileSize = estimateJpegFileSize(pic_size, jpegQuality); + if (jpegFileSize != mJpegFileSizeEstimation) { + mJpegFileSizeEstimation = jpegFileSize; + mHandler.post(new Runnable() { + @Override + public void run() { + updateRemainingPhotos(); + } + }); + } + } + } + + // Set Selectable Zone Af parameter. + String selectableZoneAf = mPreferences.getString( + CameraSettings.KEY_SELECTABLE_ZONE_AF, + mActivity.getString(R.string.pref_camera_selectablezoneaf_default)); + List<String> str = mParameters.getSupportedSelectableZoneAf(); + if (CameraUtil.isSupported(selectableZoneAf, mParameters.getSupportedSelectableZoneAf())) { + mParameters.setSelectableZoneAf(selectableZoneAf); + } + + // Set wavelet denoise mode + if (mParameters.getSupportedDenoiseModes() != null) { + String Denoise = mPreferences.getString( CameraSettings.KEY_DENOISE, + mActivity.getString(R.string.pref_camera_denoise_default)); + mParameters.setDenoise(Denoise); + } + // Set Redeye Reduction + String redeyeReduction = mPreferences.getString( + CameraSettings.KEY_REDEYE_REDUCTION, + mActivity.getString(R.string.pref_camera_redeyereduction_default)); + if (CameraUtil.isSupported(redeyeReduction, + mParameters.getSupportedRedeyeReductionModes())) { + mParameters.setRedeyeReductionMode(redeyeReduction); + } + // Set ISO parameter + if ((mManual3AEnabled & MANUAL_EXPOSURE) == 0) { + String iso = mPreferences.getString( + CameraSettings.KEY_ISO, + mActivity.getString(R.string.pref_camera_iso_default)); + if (CameraUtil.isSupported(iso, + mParameters.getSupportedIsoValues())) { + mParameters.setISOValue(iso); + } + } + // Set color effect parameter. + String colorEffect = mPreferences.getString( + CameraSettings.KEY_COLOR_EFFECT, + mActivity.getString(R.string.pref_camera_coloreffect_default)); + Log.v(TAG, "Color effect value =" + colorEffect); + if (CameraUtil.isSupported(colorEffect, mParameters.getSupportedColorEffects())) { + mParameters.setColorEffect(colorEffect); + } + + //Set Saturation + String saturationStr = mPreferences.getString( + CameraSettings.KEY_SATURATION, + mActivity.getString(R.string.pref_camera_saturation_default)); + int saturation = Integer.parseInt(saturationStr); + Log.v(TAG, "Saturation value =" + saturation); + if((0 <= saturation) && (saturation <= mParameters.getMaxSaturation())){ + mParameters.setSaturation(saturation); + } + // Set contrast parameter. + String contrastStr = mPreferences.getString( + CameraSettings.KEY_CONTRAST, + mActivity.getString(R.string.pref_camera_contrast_default)); + int contrast = Integer.parseInt(contrastStr); + Log.v(TAG, "Contrast value =" +contrast); + if((0 <= contrast) && (contrast <= mParameters.getMaxContrast())){ + mParameters.setContrast(contrast); + } + // Set sharpness parameter + String sharpnessStr = mPreferences.getString( + CameraSettings.KEY_SHARPNESS, + mActivity.getString(R.string.pref_camera_sharpness_default)); + int sharpness = Integer.parseInt(sharpnessStr) * + (mParameters.getMaxSharpness()/MAX_SHARPNESS_LEVEL); + Log.v(TAG, "Sharpness value =" + sharpness); + if((0 <= sharpness) && (sharpness <= mParameters.getMaxSharpness())){ + mParameters.setSharpness(sharpness); + } + // Set Face Recognition + String faceRC = mPreferences.getString( + CameraSettings.KEY_FACE_RECOGNITION, + mActivity.getString(R.string.pref_camera_facerc_default)); + Log.v(TAG, "Face Recognition value = " + faceRC); + if (CameraUtil.isSupported(faceRC, + CameraSettings.getSupportedFaceRecognitionModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_FACE_RECOGNITION, faceRC); + } + // Set AE Bracketing + String aeBracketing = mPreferences.getString( + CameraSettings.KEY_AE_BRACKET_HDR, + mActivity.getString(R.string.pref_camera_ae_bracket_hdr_default)); + Log.v(TAG, "AE Bracketing value =" + aeBracketing); + if (CameraUtil.isSupported(aeBracketing, + CameraSettings.getSupportedAEBracketingModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_AE_BRACKETING, aeBracketing); + } + + // Set CDS + String cds = mPreferences.getString( + CameraSettings.KEY_CDS_MODE, + mActivity.getString(R.string.pref_camera_cds_default)); + if ((mPrevSavedCDS == null) && (cds != null)) { + mPrevSavedCDS = cds; + } + if (CameraUtil.isSupported(cds, + CameraSettings.getSupportedCDSModes(mParameters))) { + mParameters.set(CameraSettings.KEY_QC_CDS_MODE, cds); + } + + // Set TNR + String tnr = mPreferences.getString( + CameraSettings.KEY_TNR_MODE, + mActivity.getString(R.string.pref_camera_tnr_default)); + if (CameraUtil.isSupported(tnr, + CameraSettings.getSupportedTNRModes(mParameters))) { + if (!tnr.equals(mActivity.getString(R.string. + pref_camera_tnr_value_off))) { + mParameters.set(CameraSettings.KEY_QC_CDS_MODE, + mActivity.getString(R.string.pref_camera_cds_value_off)); + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + mUI.overrideSettings(CameraSettings.KEY_QC_CDS_MODE, + mActivity.getString(R.string.pref_camera_cds_value_off)); + } + }); + if (cds != null) { + mPrevSavedCDS = cds; + } + isTNREnabled = true; + } else if (isTNREnabled) { + mParameters.set(CameraSettings.KEY_QC_CDS_MODE, mPrevSavedCDS); + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + mUI.overrideSettings(CameraSettings.KEY_QC_CDS_MODE, + mPrevSavedCDS); + } + }); + isTNREnabled = false; + } + mParameters.set(CameraSettings.KEY_QC_TNR_MODE, tnr); + } + + // Set hdr mode + String hdrMode = mPreferences.getString( + CameraSettings.KEY_HDR_MODE, + mActivity.getString(R.string.pref_camera_hdr_mode_default)); + Log.v(TAG, "HDR Mode value =" + hdrMode); + if (CameraUtil.isSupported(hdrMode, + CameraSettings.getSupportedHDRModes(mParameters))) { + mParameters.set(CameraSettings.KEY_SNAPCAM_HDR_MODE, hdrMode); + } + + // Set hdr need 1x + String hdrNeed1x = mPreferences.getString( + CameraSettings.KEY_HDR_NEED_1X, + mActivity.getString(R.string.pref_camera_hdr_need_1x_default)); + Log.v(TAG, "HDR need 1x value =" + hdrNeed1x); + if (CameraUtil.isSupported(hdrNeed1x, + CameraSettings.getSupportedHDRNeed1x(mParameters))) { + mParameters.set(CameraSettings.KEY_SNAPCAM_HDR_NEED_1X, hdrNeed1x); + } + + // Set Advanced features. + String advancedFeature = mPreferences.getString( + CameraSettings.KEY_ADVANCED_FEATURES, + mActivity.getString(R.string.pref_camera_advanced_feature_default)); + Log.e(TAG, " advancedFeature value =" + advancedFeature); + + mRefocus = false; + if(advancedFeature != null) { + String ubiFocusOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_ubifocus_off); + String chromaFlashOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_chromaflash_off); + String optiZoomOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_optizoom_off); + String reFocusOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_refocus_off); + String fssrOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_FSSR_off); + String truePortraitOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_trueportrait_off); + String multiTouchFocusOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_multi_touch_focus_off); + String stillMoreOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_stillmore_off); + + if (advancedFeature.equals(mActivity.getString(R.string. + pref_camera_advanced_feature_value_ubifocus_on))) { + qcomUpdateAdvancedFeatures(advancedFeature, + chromaFlashOff, + reFocusOff, + optiZoomOff, + fssrOff, + truePortraitOff, + multiTouchFocusOff, + stillMoreOff); + } else if (advancedFeature.equals(mActivity.getString(R.string. + pref_camera_advanced_feature_value_chromaflash_on))) { + qcomUpdateAdvancedFeatures(ubiFocusOff, + advancedFeature, + reFocusOff, + optiZoomOff, + fssrOff, + truePortraitOff, + multiTouchFocusOff, + stillMoreOff); + } else if (advancedFeature.equals(mActivity.getString(R.string. + pref_camera_advanced_feature_value_refocus_on))) { + qcomUpdateAdvancedFeatures(ubiFocusOff, + chromaFlashOff, + advancedFeature, + optiZoomOff, + fssrOff, + truePortraitOff, + multiTouchFocusOff, + stillMoreOff); + mRefocus = true; + } else if (advancedFeature.equals(mActivity.getString(R.string. + pref_camera_advanced_feature_value_optizoom_on))) { + qcomUpdateAdvancedFeatures(ubiFocusOff, + chromaFlashOff, + reFocusOff, + advancedFeature, + fssrOff, + truePortraitOff, + multiTouchFocusOff, + stillMoreOff); + } else if (advancedFeature.equals(mActivity.getString(R.string. + pref_camera_advanced_feature_value_FSSR_on))) { + qcomUpdateAdvancedFeatures(ubiFocusOff, + chromaFlashOff, + reFocusOff, + optiZoomOff, + advancedFeature, + truePortraitOff, + multiTouchFocusOff, + stillMoreOff); + } else if (advancedFeature.equals(mActivity.getString(R.string. + pref_camera_advanced_feature_value_trueportrait_on))) { + qcomUpdateAdvancedFeatures(ubiFocusOff, + chromaFlashOff, + reFocusOff, + optiZoomOff, + fssrOff, + advancedFeature, + multiTouchFocusOff, + stillMoreOff); + } else if (advancedFeature.equals(mActivity.getString(R.string. + pref_camera_advanced_feature_value_multi_touch_focus_on))) { + qcomUpdateAdvancedFeatures(ubiFocusOff, + chromaFlashOff, + reFocusOff, + optiZoomOff, + fssrOff, + truePortraitOff, + advancedFeature, + stillMoreOff); + } else if (advancedFeature.equals(mActivity.getString(R.string. + pref_camera_advanced_feature_value_stillmore_on))) { + qcomUpdateAdvancedFeatures(ubiFocusOff, + chromaFlashOff, + reFocusOff, + optiZoomOff, + fssrOff, + truePortraitOff, + multiTouchFocusOff, + advancedFeature); + } else { + qcomUpdateAdvancedFeatures(ubiFocusOff, + chromaFlashOff, + reFocusOff, + optiZoomOff, + fssrOff, + truePortraitOff, + multiTouchFocusOff, + stillMoreOff); + } + } + + if (mActivity.getString(R.string.pref_camera_advanced_feature_value_trueportrait_on) + .equals(advancedFeature)) { + // face detection must always be on for truePortrait + if (CameraUtil.isSupported(Parameters.FACE_DETECTION_ON, mParameters.getSupportedFaceDetectionModes())) { + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + mUI.overrideSettings(CameraSettings.KEY_FACE_DETECTION, Parameters.FACE_DETECTION_ON); + } + }); + + mParameters.setFaceDetectionMode(Parameters.FACE_DETECTION_ON); + if(mFaceDetectionEnabled == false) { + mFaceDetectionEnabled = true; + startFaceDetection(); + } + } + } else { + // Set face detetction parameter. + // clear override to re-enable setting if true portrait is off. + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + mUI.overrideSettings(CameraSettings.KEY_FACE_DETECTION, null); + } + }); + + String faceDetection = mPreferences.getString( + CameraSettings.KEY_FACE_DETECTION, + mActivity.getString(R.string.pref_camera_facedetection_default)); + + if (CameraUtil.isSupported(faceDetection, mParameters.getSupportedFaceDetectionModes())) { + mParameters.setFaceDetectionMode(faceDetection); + if(faceDetection.equals("on") && mFaceDetectionEnabled == false) { + mFaceDetectionEnabled = true; + startFaceDetection(); + } + if(faceDetection.equals("off") && mFaceDetectionEnabled == true) { + stopFaceDetection(); + mFaceDetectionEnabled = false; + } + } + } + + // Set auto exposure parameter. + String autoExposure = mPreferences.getString( + CameraSettings.KEY_AUTOEXPOSURE, + mActivity.getString(R.string.pref_camera_autoexposure_default)); + Log.v(TAG, "autoExposure value =" + autoExposure); + if (CameraUtil.isSupported(autoExposure, mParameters.getSupportedAutoexposure())) { + mParameters.setAutoExposure(autoExposure); + } + + // Set anti banding parameter. + String antiBanding = mPreferences.getString( + CameraSettings.KEY_ANTIBANDING, + mActivity.getString(R.string.pref_camera_antibanding_default)); + Log.v(TAG, "antiBanding value =" + antiBanding); + if (CameraUtil.isSupported(antiBanding, mParameters.getSupportedAntibanding())) { + mParameters.setAntibanding(antiBanding); + } + + String zsl = mPreferences.getString(CameraSettings.KEY_ZSL, + mActivity.getString(R.string.pref_camera_zsl_default)); + String auto_hdr = mPreferences.getString(CameraSettings.KEY_AUTO_HDR, + mActivity.getString(R.string.pref_camera_hdr_default)); + if (CameraUtil.isAutoHDRSupported(mParameters)) { + mParameters.set("auto-hdr-enable",auto_hdr); + if (auto_hdr.equals("enable")) { + mActivity.runOnUiThread(new Runnable() { + public void run() { + if (mDrawAutoHDR != null) { + mDrawAutoHDR.setVisibility(View.VISIBLE); + } + } + }); + mParameters.setSceneMode("asd"); + mCameraDevice.setMetadataCb(mMetaDataCallback); + } + else { + mAutoHdrEnable = false; + mActivity.runOnUiThread( new Runnable() { + public void run () { + if (mDrawAutoHDR != null) { + mDrawAutoHDR.setVisibility (View.INVISIBLE); + } + } + }); + } + } + mParameters.setZSLMode(zsl); + if(zsl.equals("on")) { + //Switch on ZSL Camera mode + mSnapshotMode = CameraInfo.CAMERA_SUPPORT_MODE_ZSL; + mParameters.setCameraMode(1); + mFocusManager.setZslEnable(true); + + //Raw picture format is not supported under ZSL mode + mParameters.set(KEY_PICTURE_FORMAT, PIXEL_FORMAT_JPEG); + + //Try to set CAF for ZSL + if(CameraUtil.isSupported(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE, + mParameters.getSupportedFocusModes()) && !mFocusManager.isTouch()) { + mFocusManager.overrideFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + mParameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + } else if (mFocusManager.isTouch()) { + mFocusManager.overrideFocusMode(null); + mParameters.setFocusMode(mFocusManager.getFocusMode()); + } else { + // If not supported use the current mode + mFocusManager.overrideFocusMode(mFocusManager.getFocusMode()); + } + + if (!pictureFormat.equals(PIXEL_FORMAT_JPEG)) { + mActivity.runOnUiThread(new Runnable() { + public void run() { + RotateTextToast.makeText(mActivity, R.string.error_app_unsupported_raw, + Toast.LENGTH_SHORT).show(); + } + }); + } + } else if(zsl.equals("off")) { + mSnapshotMode = CameraInfo.CAMERA_SUPPORT_MODE_NONZSL; + mParameters.setCameraMode(0); + mFocusManager.setZslEnable(false); + if ((mManual3AEnabled & MANUAL_FOCUS) == 0) { + mFocusManager.overrideFocusMode(null); + mParameters.setFocusMode(mFocusManager.getFocusMode()); + } + } + + //Set Histogram + String histogram = mPreferences.getString( + CameraSettings.KEY_HISTOGRAM, + mActivity.getString(R.string.pref_camera_histogram_default)); + if (CameraUtil.isSupported(histogram, + mParameters.getSupportedHistogramModes()) && mCameraDevice != null) { + // Call for histogram + if(histogram.equals("enable")) { + mActivity.runOnUiThread(new Runnable() { + public void run() { + if(mGraphView != null) { + mGraphView.setVisibility(View.VISIBLE); + mGraphView.PreviewChanged(); + } + } + }); + mCameraDevice.setHistogramMode(mStatsCallback); + mHiston = true; + } else { + mHiston = false; + mActivity.runOnUiThread(new Runnable() { + public void run() { + if (mGraphView != null) + mGraphView.setVisibility(View.INVISIBLE); + } + }); + mCameraDevice.setHistogramMode(null); + } + } + + setFlipValue(); + + /* Disable focus if aebracket is ON */ + String aeBracket = mParameters.get(CameraSettings.KEY_QC_AE_BRACKETING); + if (!aeBracket.equalsIgnoreCase("off")) { + String fMode = Parameters.FLASH_MODE_OFF; + mParameters.setFlashMode(fMode); + } + + if(!mFocusManager.getFocusMode().equals(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) && + !mFocusManager.isFocusCompleted()) { + mUI.clearFocus(); + } + } + + private int estimateJpegFileSize(final Size size, final String quality) { + int[] ratios = mActivity.getResources().getIntArray(R.array.jpegquality_compression_ratio); + String[] qualities = mActivity.getResources().getStringArray( + R.array.pref_camera_jpegquality_entryvalues); + int ratio = 0; + for (int i = ratios.length - 1; i >= 0; --i) { + if (qualities[i].equals(quality)) { + ratio = ratios[i]; + break; + } + } + + if (ratio == 0) { + return 0; + } else { + return size.width * size.height * 3 / ratio; + } + } + + private void setFlipValue() { + // Read Flip mode from adb command + //value: 0(default) - FLIP_MODE_OFF + //value: 1 - FLIP_MODE_H + //value: 2 - FLIP_MODE_V + //value: 3 - FLIP_MODE_VH + int preview_flip_value = SystemProperties.getInt("debug.camera.preview.flip", 0); + int video_flip_value = SystemProperties.getInt("debug.camera.video.flip", 0); + int picture_flip_value = SystemProperties.getInt("debug.camera.picture.flip", 0); + int rotation = CameraUtil.getJpegRotation(mCameraId, mOrientation); + mParameters.setRotation(rotation); + if (rotation == 90 || rotation == 270) { + // in case of 90 or 270 degree, V/H flip should reverse + if (preview_flip_value == 1) { + preview_flip_value = 2; + } else if (preview_flip_value == 2) { + preview_flip_value = 1; + } + if (video_flip_value == 1) { + video_flip_value = 2; + } else if (video_flip_value == 2) { + video_flip_value = 1; + } + if (picture_flip_value == 1) { + picture_flip_value = 2; + } else if (picture_flip_value == 2) { + picture_flip_value = 1; + } + } + String preview_flip = CameraUtil.getFilpModeString(preview_flip_value); + String video_flip = CameraUtil.getFilpModeString(video_flip_value); + String picture_flip = CameraUtil.getFilpModeString(picture_flip_value); + if(CameraUtil.isSupported(preview_flip, CameraSettings.getSupportedFlipMode(mParameters))){ + mParameters.set(CameraSettings.KEY_QC_PREVIEW_FLIP, preview_flip); + } + if(CameraUtil.isSupported(video_flip, CameraSettings.getSupportedFlipMode(mParameters))){ + mParameters.set(CameraSettings.KEY_QC_VIDEO_FLIP, video_flip); + } + if(CameraUtil.isSupported(picture_flip, CameraSettings.getSupportedFlipMode(mParameters))){ + mParameters.set(CameraSettings.KEY_QC_SNAPSHOT_PICTURE_FLIP, picture_flip); + } + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + private void setAutoExposureLockIfSupported() { + if (mAeLockSupported) { + mParameters.setAutoExposureLock(mFocusManager.getAeAwbLock()); + } + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + private void setAutoWhiteBalanceLockIfSupported() { + if (mAwbLockSupported) { + mParameters.setAutoWhiteBalanceLock(mFocusManager.getAeAwbLock()); + } + } + + private void setFocusAreasIfSupported() { + if (mFocusAreaSupported) { + mParameters.setFocusAreas(mFocusManager.getFocusAreas()); + } + } + + private void setMeteringAreasIfSupported() { + if (mMeteringAreaSupported) { + mParameters.setMeteringAreas(mFocusManager.getMeteringAreas()); + } + } + + /** This can run on a background thread, so don't do UI updates here.*/ + private boolean updateCameraParametersPreference() { + setAutoExposureLockIfSupported(); + setAutoWhiteBalanceLockIfSupported(); + setFocusAreasIfSupported(); + setMeteringAreasIfSupported(); + + // initialize focus mode + if ((mManual3AEnabled & MANUAL_FOCUS) == 0) { + mFocusManager.overrideFocusMode(null); + mParameters.setFocusMode(mFocusManager.getFocusMode()); + } + + // Set picture size. + String pictureSize = mPreferences.getString( + CameraSettings.KEY_PICTURE_SIZE, null); + if (pictureSize == null) { + CameraSettings.initialCameraPictureSize(mActivity, mParameters); + } else { + Size old_size = mParameters.getPictureSize(); + Log.v(TAG, "old picture_size = " + old_size.width + " x " + old_size.height); + List<Size> supported = mParameters.getSupportedPictureSizes(); + CameraSettings.setCameraPictureSize( + pictureSize, supported, mParameters); + Size size = mParameters.getPictureSize(); + Log.v(TAG, "new picture_size = " + size.width + " x " + size.height); + if (old_size != null && size != null) { + if(!size.equals(old_size) && mCameraState != PREVIEW_STOPPED) { + Log.v(TAG, "Picture Size changed. Restart Preview"); + mRestartPreview = true; + } + } + } + Size size = mParameters.getPictureSize(); + + // Set a preview size that is closest to the viewfinder height and has + // the right aspect ratio. + List<Size> sizes = mParameters.getSupportedPreviewSizes(); + Size optimalSize = CameraUtil.getOptimalPreviewSize(mActivity, sizes, + (double) size.width / size.height); + + //Read Preview Resolution from adb command + //value: 0(default) - Default value as per snapshot aspect ratio + //value: 1 - 640x480 + //value: 2 - 720x480 + //value: 3 - 1280x720 + //value: 4 - 1920x1080 + int preview_resolution = SystemProperties.getInt("persist.camera.preview.size", 0); + switch (preview_resolution) { + case 1: { + optimalSize.width = 640; + optimalSize.height = 480; + Log.v(TAG, "Preview resolution hardcoded to 640x480"); + break; + } + case 2: { + optimalSize.width = 720; + optimalSize.height = 480; + Log.v(TAG, "Preview resolution hardcoded to 720x480"); + break; + } + case 3: { + optimalSize.width = 1280; + optimalSize.height = 720; + Log.v(TAG, "Preview resolution hardcoded to 1280x720"); + break; + } + case 4: { + optimalSize.width = 1920; + optimalSize.height = 1080; + Log.v(TAG, "Preview resolution hardcoded to 1920x1080"); + break; + } + default: { + Log.v(TAG, "Preview resolution as per Snapshot aspect ratio"); + break; + } + } + + Size original = mParameters.getPreviewSize(); + if (!original.equals(optimalSize)) { + mParameters.setPreviewSize(optimalSize.width, optimalSize.height); + + // Zoom related settings will be changed for different preview + // sizes, so set and read the parameters to get latest values + if (mHandler.getLooper() == Looper.myLooper()) { + // On UI thread only, not when camera starts up + setupPreview(); + } else { + mCameraDevice.setParameters(mParameters); + } + mParameters = mCameraDevice.getParameters(); + Log.v(TAG, "Preview Size changed. Restart Preview"); + mRestartPreview = true; + } + + Log.v(TAG, "Preview size is " + optimalSize.width + "x" + optimalSize.height); + size = mParameters.getPictureSize(); + + // Set jpegthumbnail size + // Set a jpegthumbnail size that is closest to the Picture height and has + // the right aspect ratio. + List<Size> supported = mParameters.getSupportedJpegThumbnailSizes(); + optimalSize = CameraUtil.getOptimalJpegThumbnailSize(supported, + (double) size.width / size.height); + original = mParameters.getJpegThumbnailSize(); + if (!original.equals(optimalSize)) { + mParameters.setJpegThumbnailSize(optimalSize.width, optimalSize.height); + } + + Log.v(TAG, "Thumbnail size is " + optimalSize.width + "x" + optimalSize.height); + + // Since changing scene mode may change supported values, set scene mode + // first. HDR is a scene mode. To promote it in UI, it is stored in a + // separate preference. + String onValue = mActivity.getString(R.string.setting_on_value); + String hdr = mPreferences.getString(CameraSettings.KEY_CAMERA_HDR, + mActivity.getString(R.string.pref_camera_hdr_default)); + String hdrPlus = mPreferences.getString(CameraSettings.KEY_CAMERA_HDR_PLUS, + mActivity.getString(R.string.pref_camera_hdr_plus_default)); + boolean hdrOn = onValue.equals(hdr); + boolean hdrPlusOn = onValue.equals(hdrPlus); + + boolean doGcamModeSwitch = false; + if (hdrPlusOn && GcamHelper.hasGcamCapture()) { + // Kick off mode switch to gcam. + doGcamModeSwitch = true; + } else { + if (hdrOn) { + mSceneMode = CameraUtil.SCENE_MODE_HDR; + if (!(Parameters.SCENE_MODE_AUTO).equals(mParameters.getSceneMode()) + && !(Parameters.SCENE_MODE_HDR).equals(mParameters.getSceneMode())) { + mParameters.setSceneMode(Parameters.SCENE_MODE_AUTO); + mCameraDevice.setParameters(mParameters); + mParameters = mCameraDevice.getParameters(); + } + } else { + mSceneMode = mPreferences.getString( + CameraSettings.KEY_SCENE_MODE, + mActivity.getString(R.string.pref_camera_scenemode_default)); + } + } + + String refocusOn = mActivity.getString(R.string + .pref_camera_advanced_feature_value_refocus_on); + String optizoomOn = mActivity.getString(R.string + .pref_camera_advanced_feature_value_optizoom_on); + if (refocusOn.equals(mSceneMode)) { + try { + mSceneMode = Parameters.SCENE_MODE_AUTO; + mUI.setPreference(CameraSettings.KEY_ADVANCED_FEATURES, refocusOn); + mUI.showRefocusDialog(); + } catch (NullPointerException e) { + } + } else if (optizoomOn.equals(mSceneMode)) { + try { + mSceneMode = Parameters.SCENE_MODE_AUTO; + mUI.setPreference(CameraSettings.KEY_ADVANCED_FEATURES, optizoomOn); + } catch (NullPointerException e) { + } + } else if (mSceneMode == null) { + mSceneMode = Parameters.SCENE_MODE_AUTO; + } + + if (CameraUtil.isSupported(mSceneMode, mParameters.getSupportedSceneModes())) { + if (!mParameters.getSceneMode().equals(mSceneMode)) { + mParameters.setSceneMode(mSceneMode); + + // Setting scene mode will change the settings of flash mode, + // white balance, and focus mode. Here we read back the + // parameters, so we can know those settings. + mCameraDevice.setParameters(mParameters); + mParameters = mCameraDevice.getParameters(); + } + } + + // Set JPEG quality. + int jpegQuality; + if(mCameraId>1) { + jpegQuality=95; //Temproray Solution for camera ids greater than 1. Proper fix TBD. + } else { + jpegQuality = CameraProfile.getJpegEncodingQualityParameter(mCameraId, + CameraProfile.QUALITY_HIGH); + } + + mParameters.setJpegQuality(jpegQuality); + + // For the following settings, we need to check if the settings are + // still supported by latest driver, if not, ignore the settings. + + // Set exposure compensation + int value = CameraSettings.readExposure(mPreferences); + int max = mParameters.getMaxExposureCompensation(); + int min = mParameters.getMinExposureCompensation(); + if (value >= min && value <= max) { + mParameters.setExposureCompensation(value); + } else { + Log.w(TAG, "invalid exposure range: " + value); + } + + if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) { + // Set flash mode. + String flashMode; + if (mSavedFlashMode == null) { + flashMode = mPreferences.getString( + CameraSettings.KEY_FLASH_MODE, + mActivity.getString(R.string.pref_camera_flashmode_default)); + } else { + flashMode = mSavedFlashMode; + } + + List<String> supportedFlash = mParameters.getSupportedFlashModes(); + if (CameraUtil.isSupported(flashMode, supportedFlash)) { + mParameters.setFlashMode(flashMode); + } else { + flashMode = mParameters.getFlashMode(); + if (flashMode == null) { + flashMode = mActivity.getString( + R.string.pref_camera_flashmode_no_flash); + } + } + + // Set white balance parameter. + if ((mManual3AEnabled & MANUAL_WB) == 0) { + String whiteBalance = mPreferences.getString( + CameraSettings.KEY_WHITE_BALANCE, + mActivity.getString(R.string.pref_camera_whitebalance_default)); + if (CameraUtil.isSupported(whiteBalance, + mParameters.getSupportedWhiteBalance())) { + mParameters.setWhiteBalance(whiteBalance); + } else { + whiteBalance = mParameters.getWhiteBalance(); + if (whiteBalance == null) { + whiteBalance = Parameters.WHITE_BALANCE_AUTO; + } + } + } + + // Set focus mode. + if ((mManual3AEnabled & MANUAL_FOCUS) == 0) { + mFocusManager.overrideFocusMode(null); + mParameters.setFocusMode(mFocusManager.getFocusMode()); + } + } else { + mFocusManager.overrideFocusMode(mParameters.getFocusMode()); + if (CameraUtil.isSupported(Parameters.FLASH_MODE_OFF, + mParameters.getSupportedFlashModes())) { + mParameters.setFlashMode(Parameters.FLASH_MODE_OFF); + } + if (CameraUtil.isSupported(Parameters.WHITE_BALANCE_AUTO, + mParameters.getSupportedWhiteBalance())) { + mParameters.setWhiteBalance(Parameters.WHITE_BALANCE_AUTO); + } + } + + if (mContinuousFocusSupported && ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK) { + updateAutoFocusMoveCallback(); + } + + String makeupParamValue = mPreferences.getString(CameraSettings.KEY_TS_MAKEUP_UILABLE, + mActivity.getString(R.string.pref_camera_tsmakeup_default)); + mParameters.set(CameraSettings.KEY_TS_MAKEUP_PARAM, makeupParamValue); + Log.v(TAG,"updateCameraParametersPreference(): TSMakeup " + CameraSettings.KEY_TS_MAKEUP_PARAM +" value = " + makeupParamValue); + + if(TsMakeupManager.MAKEUP_ON.equals(makeupParamValue)) { + String makeupWhitenValue = mPreferences.getString(CameraSettings.KEY_TS_MAKEUP_LEVEL_WHITEN, + mActivity.getString(R.string.pref_camera_tsmakeup_level_default)); + String makeupCleanValue = mPreferences.getString(CameraSettings.KEY_TS_MAKEUP_LEVEL_CLEAN, + mActivity.getString(R.string.pref_camera_tsmakeup_level_default)); + mParameters.set(CameraSettings.KEY_TS_MAKEUP_PARAM_WHITEN, makeupWhitenValue); + mParameters.set(CameraSettings.KEY_TS_MAKEUP_PARAM_CLEAN, makeupCleanValue); + } + + //QCom related parameters updated here. + qcomUpdateCameraParametersPreference(); + return doGcamModeSwitch; + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + private void updateAutoFocusMoveCallback() { + if (mParameters.getFocusMode().equals(CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE)) { + mCameraDevice.setAutoFocusMoveCallback(mHandler, + (CameraAFMoveCallback) mAutoFocusMoveCallback); + } else { + mCameraDevice.setAutoFocusMoveCallback(null, null); + } + } + + // We separate the parameters into several subsets, so we can update only + // the subsets actually need updating. The PREFERENCE set needs extra + // locking because the preference can be changed from GLThread as well. + private void setCameraParameters(int updateSet) { + if (mCameraDevice == null) { + return; + } + synchronized (mCameraDevice) { + boolean doModeSwitch = false; + + if ((updateSet & UPDATE_PARAM_INITIALIZE) != 0) { + updateCameraParametersInitialize(); + } + + if ((updateSet & UPDATE_PARAM_ZOOM) != 0) { + updateCameraParametersZoom(); + } + + if ((updateSet & UPDATE_PARAM_PREFERENCE) != 0) { + doModeSwitch = updateCameraParametersPreference(); + } + + mCameraDevice.setParameters(mParameters); + + // Switch to gcam module if HDR+ was selected + if (doModeSwitch && !mIsImageCaptureIntent) { + mHandler.sendEmptyMessage(SWITCH_TO_GCAM_MODULE); + } + } + } + + // If the Camera is idle, update the parameters immediately, otherwise + // accumulate them in mUpdateSet and update later. + private void setCameraParametersWhenIdle(int additionalUpdateSet) { + mUpdateSet |= additionalUpdateSet; + if (mCameraDevice == null) { + // We will update all the parameters when we open the device, so + // we don't need to do anything now. + mUpdateSet = 0; + return; + } else if (isCameraIdle()) { + setCameraParameters(mUpdateSet); + if(mRestartPreview && mCameraState != PREVIEW_STOPPED) { + Log.v(TAG, "Restarting Preview..."); + stopPreview(); + resizeForPreviewAspectRatio(); + startPreview(); + setCameraState(IDLE); + } + mRestartPreview = false; + updateCameraSettings(); + mUpdateSet = 0; + } else { + if (!mHandler.hasMessages(SET_CAMERA_PARAMETERS_WHEN_IDLE)) { + mHandler.sendEmptyMessageDelayed( + SET_CAMERA_PARAMETERS_WHEN_IDLE, 1000); + } + } + } + + @Override + public boolean isCameraIdle() { + return (mCameraState == IDLE) || + (mCameraState == PREVIEW_STOPPED) || + ((mFocusManager != null) && mFocusManager.isFocusCompleted() + && (mCameraState != SWITCHING_CAMERA)); + } + + @Override + public boolean isImageCaptureIntent() { + String action = mActivity.getIntent().getAction(); + return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action) + || CameraActivity.ACTION_IMAGE_CAPTURE_SECURE.equals(action)); + } + + private void setupCaptureParams() { + Bundle myExtras = mActivity.getIntent().getExtras(); + if (myExtras != null) { + mSaveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT); + mCropValue = myExtras.getString("crop"); + } + } + + private void UpdateManualFocusSettings() { + //dismiss all popups first, because we need to show edit dialog + mUI.collapseCameraControls(); + final AlertDialog.Builder alert = new AlertDialog.Builder(mActivity); + LinearLayout linear = new LinearLayout(mActivity); + linear.setOrientation(1); + alert.setTitle("Manual Focus Settings"); + alert.setNegativeButton("Cancel",new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog,int id) + { + dialog.cancel(); + } + }); + final TextView focusPositionText = new TextView(mActivity); + String scaleMode = mActivity.getString( + R.string.pref_camera_manual_focus_value_scale_mode); + String diopterMode = mActivity.getString( + R.string.pref_camera_manual_focus_value_diopter_mode); + String manualFocusMode = mPreferences.getString( + CameraSettings.KEY_MANUAL_FOCUS, + mActivity.getString(R.string.pref_camera_manual_focus_default)); + + Log.v(TAG, "manualFocusMode selected = " + manualFocusMode); + if (manualFocusMode.equals(scaleMode)) { + final SeekBar focusbar = new SeekBar(mActivity); + final int minFocusPos = mParameters.getInt(CameraSettings.KEY_MIN_FOCUS_SCALE); + final int maxFocusPos = mParameters.getInt(CameraSettings.KEY_MAX_FOCUS_SCALE); + //update mparameters to fetch latest focus position + mParameters = mCameraDevice.getParameters(); + final int CurFocusPos = mParameters.getInt(CameraSettings.KEY_MANUAL_FOCUS_SCALE); + focusbar.setProgress(CurFocusPos); + focusPositionText.setText("Current focus position is " + CurFocusPos); + + alert.setMessage("Enter focus position in the range of " + minFocusPos + + " to " + maxFocusPos); + + focusbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) { + focusPositionText.setText("Current focus position is " + progress); + } + }); + linear.addView(focusbar); + linear.addView(focusPositionText); + alert.setView(linear); + alert.setPositiveButton("Ok",new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog,int id) + { + int focusPos = focusbar.getProgress(); + Log.v(TAG, "Setting focus position : " + focusPos); + mManual3AEnabled |= MANUAL_FOCUS; + mParameters.setFocusMode(Parameters.FOCUS_MODE_MANUAL_POSITION); + mParameters.set(CameraSettings.KEY_MANUAL_FOCUS_TYPE, 2); // 2 for scale mode + mParameters.set(CameraSettings.KEY_MANUAL_FOCUS_POSITION, focusPos); + updateCommonManual3ASettings(); + onSharedPreferenceChanged(); + } + }); + alert.show(); + } else if (manualFocusMode.equals(diopterMode)) { + String minFocusStr = mParameters.get(CameraSettings.KEY_MIN_FOCUS_DIOPTER); + String maxFocusStr = mParameters.get(CameraSettings.KEY_MAX_FOCUS_DIOPTER); + final double minFocusPos = Double.parseDouble(minFocusStr); + final double maxFocusPos = Double.parseDouble(maxFocusStr); + final EditText input = new EditText(mActivity); + int floatType = InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_CLASS_NUMBER; + input.setInputType(floatType); + alert.setMessage("Enter focus position in the range of " + minFocusPos + + " to " + maxFocusPos); + //update mparameters to fetch latest focus position + mParameters = mCameraDevice.getParameters(); + final String CurFocusPos = mParameters.get(CameraSettings.KEY_MANUAL_FOCUS_DIOPTER); + focusPositionText.setText("Current focus position is " + CurFocusPos); + linear.addView(input); + linear.addView(focusPositionText); + alert.setView(linear); + alert.setPositiveButton("Ok",new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog,int id) + { + double focuspos = 0; + String focusStr = input.getText().toString(); + if (focusStr.length() > 0) { + try { + focuspos = Double.parseDouble(focusStr); + } catch (NumberFormatException e) { + Log.w(TAG, "Input foucspos " + focuspos + " is invalid"); + focuspos = maxFocusPos + 1f; + } + + } else { + RotateTextToast.makeText(mActivity, "Invalid focus position", + Toast.LENGTH_SHORT).show(); + return; + } + if (focuspos >= minFocusPos && focuspos <= maxFocusPos) { + Log.v(TAG, "Setting focus position : " + focusStr); + mManual3AEnabled |= MANUAL_FOCUS; + mParameters.setFocusMode(Parameters.FOCUS_MODE_MANUAL_POSITION); + //focus type 3 is diopter mode + mParameters.set(CameraSettings.KEY_MANUAL_FOCUS_TYPE, 3); + mParameters.set(CameraSettings.KEY_MANUAL_FOCUS_POSITION, focusStr); + updateCommonManual3ASettings(); + onSharedPreferenceChanged(); + } else { + RotateTextToast.makeText(mActivity, "Invalid focus position", + Toast.LENGTH_SHORT).show(); + } + } + }); + alert.show(); + } else { + mManual3AEnabled &= ~MANUAL_FOCUS; + mParameters.setFocusMode(mFocusManager.getFocusMode()); + mUI.overrideSettings(CameraSettings.KEY_FOCUS_MODE, null); + updateCommonManual3ASettings(); + onSharedPreferenceChanged(); + } + } + + private void UpdateManualWBSettings() { + //dismiss all popups first, because we need to show edit dialog + mUI.collapseCameraControls(); + final AlertDialog.Builder alert = new AlertDialog.Builder(mActivity); + LinearLayout linear = new LinearLayout(mActivity); + linear.setOrientation(1); + alert.setTitle("Manual White Balance Settings"); + alert.setNegativeButton("Cancel",new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog,int id) + { + dialog.cancel(); + } + }); + + String cctMode = mActivity.getString( + R.string.pref_camera_manual_wb_value_color_temperature); + String rgbGainMode = mActivity.getString( + R.string.pref_camera_manual_wb_value_rbgb_gains); + String manualWBMode = mPreferences.getString( + CameraSettings.KEY_MANUAL_WB, + mActivity.getString(R.string.pref_camera_manual_wb_default)); + final String wbPref = mPreferences.getString( + CameraSettings.KEY_WHITE_BALANCE, + mActivity.getString(R.string.pref_camera_whitebalance_default)); + Log.v(TAG, "manualWBMode selected = " + manualWBMode); + if (manualWBMode.equals(cctMode)) { + final TextView CCTtext = new TextView(mActivity); + final EditText CCTinput = new EditText(mActivity); + CCTinput.setInputType(InputType.TYPE_CLASS_NUMBER); + final int minCCT = mParameters.getInt(CameraSettings.KEY_MIN_WB_CCT); + final int maxCCT = mParameters.getInt(CameraSettings.KEY_MAX_WB_CCT); + + //refresh camera parameters to get latest CCT value + mParameters = mCameraDevice.getParameters(); + String currentCCT = mParameters.get(CameraSettings.KEY_MANUAL_WB_CCT); + if (currentCCT != null) { + CCTtext.setText("Current CCT is " + currentCCT); + } + alert.setMessage("Enter CCT value in the range of " + minCCT+ " to " + maxCCT); + linear.addView(CCTinput); + linear.addView(CCTtext); + alert.setView(linear); + alert.setPositiveButton("Ok",new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog,int id) + { + int newCCT = -1; + String cct = CCTinput.getText().toString(); + if (cct.length() > 0) { + newCCT = Integer.parseInt(cct); + } + if (newCCT <= maxCCT && newCCT >= minCCT) { + mManual3AEnabled |= MANUAL_WB; + Log.v(TAG, "Setting CCT value : " + newCCT); + mParameters.setWhiteBalance(CameraSettings.KEY_MANUAL_WHITE_BALANCE); + //0 corresponds to manual CCT mode + mParameters.set(CameraSettings.KEY_MANUAL_WB_TYPE, 0); + mParameters.set(CameraSettings.KEY_MANUAL_WB_VALUE, newCCT); + updateCommonManual3ASettings(); + onSharedPreferenceChanged(); + } else { + RotateTextToast.makeText(mActivity, "Invalid CCT", Toast.LENGTH_SHORT) + .show(); + } + } + }); + alert.show(); + } else if (manualWBMode.equals(rgbGainMode)) { + final TextView RGBtext = new TextView(mActivity); + final EditText Rinput = new EditText(mActivity); + Rinput.setHint("Enter R gain here"); + final EditText Ginput = new EditText(mActivity); + Ginput.setHint("Enter G gain here"); + final EditText Binput = new EditText(mActivity); + Binput.setHint("Enter B gain here"); + + int floatType = InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_CLASS_NUMBER; + Rinput.setInputType(floatType); + Ginput.setInputType(floatType); + Binput.setInputType(floatType); + + String minGainStr = mParameters.get(CameraSettings.KEY_MIN_WB_GAIN); + final double minGain = Double.parseDouble(minGainStr); + String maxGainStr = mParameters.get(CameraSettings.KEY_MAX_WB_GAIN); + final double maxGain = Double.parseDouble(maxGainStr); + + //refresh camera parameters to get latest WB gains + mParameters = mCameraDevice.getParameters(); + String currentGains = mParameters.get(CameraSettings.KEY_MANUAL_WB_GAINS); + if (currentGains != null) { + RGBtext.setText("Current RGB gains are " + currentGains); + } + + alert.setMessage("Enter RGB gains in the range of " + minGain + + " to " + maxGain); + linear.addView(Rinput); + linear.addView(Ginput); + linear.addView(Binput); + linear.addView(RGBtext); + alert.setView(linear); + alert.setPositiveButton("Ok",new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog,int id) + { + String Rgain = Rinput.getText().toString(); + String Ggain = Ginput.getText().toString(); + String Bgain = Binput.getText().toString(); + double Rgainf = -1; + double Ggainf = -1; + double Bgainf = -1; + if (Rgain.length() > 0 && Ggain.length() > 0 && Bgain.length() > 0) { + try { + Rgainf = Double.parseDouble(Rgain); + Ggainf = Double.parseDouble(Ggain); + Bgainf = Double.parseDouble(Bgain); + } catch (NumberFormatException e) { + Log.w(TAG, "Input RGB gain is invalid"); + Rgainf = maxGain + 1f; + Ggainf = maxGain + 1f; + Bgainf = maxGain + 1f; + } + String RGBGain = Rgain + "," + Ggain + "," + Bgain; + if (Rgainf <= maxGain && Rgainf >= minGain && + Ggainf <= maxGain && Ggainf >= minGain && + Bgainf <= maxGain && Bgainf >= minGain) { + Log.v(TAG, "Setting RGB gains : " + RGBGain); + mManual3AEnabled |= MANUAL_WB; + mParameters.setWhiteBalance(CameraSettings.KEY_MANUAL_WHITE_BALANCE); + // 1 corresponds to manual WB gain mode + mParameters.set(CameraSettings.KEY_MANUAL_WB_TYPE, 1); + mParameters.set(CameraSettings.KEY_MANUAL_WB_VALUE, RGBGain); + updateCommonManual3ASettings(); + onSharedPreferenceChanged(); + } else { + RotateTextToast.makeText(mActivity, "Invalid RGB gains", + Toast.LENGTH_SHORT).show(); + } + } else { + RotateTextToast.makeText(mActivity, "Invalid RGB gains", + Toast.LENGTH_SHORT).show(); + } + } + }); + alert.show(); + } else { + //reset white balance + mManual3AEnabled &= ~MANUAL_WB; + mUI.overrideSettings(CameraSettings.KEY_WHITE_BALANCE, null); + updateCommonManual3ASettings(); + onSharedPreferenceChanged(); + } + } + + private void UpdateManualExposureSettings() { + //dismiss all popups first, because we need to show edit dialog + mUI.collapseCameraControls(); + final AlertDialog.Builder alert = new AlertDialog.Builder(mActivity); + LinearLayout linear = new LinearLayout(mActivity); + linear.setOrientation(1); + final TextView ISOtext = new TextView(mActivity); + final EditText ISOinput = new EditText(mActivity); + final TextView ExpTimeText = new TextView(mActivity); + final EditText ExpTimeInput = new EditText(mActivity); + ISOinput.setInputType(InputType.TYPE_CLASS_NUMBER); + int floatType = InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_CLASS_NUMBER; + ExpTimeInput.setInputType(floatType); + alert.setTitle("Manual Exposure Settings"); + alert.setNegativeButton("Cancel",new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog,int id) + { + dialog.cancel(); + } + }); + + mParameters = mCameraDevice.getParameters(); + final int minISO = mParameters.getInt(CameraSettings.KEY_MIN_ISO); + final int maxISO = mParameters.getInt(CameraSettings.KEY_MAX_ISO); + String isoMode = mParameters.getISOValue(); + final String isoManual = CameraSettings.KEY_MANUAL_ISO; + String currentISO = mParameters.get(CameraSettings.KEY_CURRENT_ISO); + if (currentISO != null) { + ISOtext.setText("Current ISO is " + currentISO); + } + + final String minExpTime = mParameters.get(CameraSettings.KEY_MIN_EXPOSURE_TIME); + final String maxExpTime = mParameters.get(CameraSettings.KEY_MAX_EXPOSURE_TIME); + String currentExpTime = mParameters.get(CameraSettings.KEY_CURRENT_EXPOSURE_TIME); + if (currentExpTime != null) { + ExpTimeText.setText("Current exposure time is " + currentExpTime); + } + + String isoPriority = mActivity.getString( + R.string.pref_camera_manual_exp_value_ISO_priority); + String expTimePriority = mActivity.getString( + R.string.pref_camera_manual_exp_value_exptime_priority); + String userSetting = mActivity.getString( + R.string.pref_camera_manual_exp_value_user_setting); + String manualExposureMode = mPreferences.getString( + CameraSettings.KEY_MANUAL_EXPOSURE, + mActivity.getString(R.string.pref_camera_manual_exp_default)); + Log.v(TAG, "manual Exposure Mode selected = " + manualExposureMode); + if (manualExposureMode.equals(isoPriority)) { + alert.setMessage("Enter ISO in the range of " + minISO + " to " + maxISO); + linear.addView(ISOinput); + linear.addView(ISOtext); + alert.setView(linear); + alert.setPositiveButton("Ok",new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog,int id) + { + int newISO = -1; + String iso = ISOinput.getText().toString(); + Log.v(TAG, "string iso length " + iso.length()); + if (iso.length() > 0) { + newISO = Integer.parseInt(iso); + } + if (newISO <= maxISO && newISO >= minISO) { + Log.v(TAG, "Setting ISO : " + newISO); + mManual3AEnabled |= MANUAL_EXPOSURE; + mParameters.setISOValue(isoManual); + mParameters.set(CameraSettings.KEY_CONTINUOUS_ISO, newISO); + mParameters.set(CameraSettings.KEY_EXPOSURE_TIME, "0"); + updateCommonManual3ASettings(); + onSharedPreferenceChanged(); + } else { + RotateTextToast.makeText(mActivity, "Invalid ISO", Toast.LENGTH_SHORT).show(); + } + } + }); + alert.show(); + } else if (manualExposureMode.equals(expTimePriority)) { + alert.setMessage("Enter exposure time in the range of " + minExpTime + + "ms to " + maxExpTime + "ms"); + linear.addView(ExpTimeInput); + linear.addView(ExpTimeText); + alert.setView(linear); + alert.setPositiveButton("Ok",new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog,int id) + { + double newExpTime = -1; + String expTime = ExpTimeInput.getText().toString(); + if (expTime.length() > 0) { + try { + newExpTime = Double.parseDouble(expTime); + } catch (NumberFormatException e) { + Log.w(TAG, "Input expTime " + expTime + " is invalid"); + newExpTime = Double.parseDouble(maxExpTime) + 1f; + } + } + if (newExpTime <= Double.parseDouble(maxExpTime) && + newExpTime >= Double.parseDouble(minExpTime)) { + Log.v(TAG, "Setting Exposure time : " + newExpTime); + mManual3AEnabled |= MANUAL_EXPOSURE; + mParameters.set(CameraSettings.KEY_EXPOSURE_TIME, expTime); + mParameters.setISOValue(Parameters.ISO_AUTO); + mUI.setPreference(CameraSettings.KEY_ISO, Parameters.ISO_AUTO); + mUI.overrideSettings(CameraSettings.KEY_ISO, null); + updateCommonManual3ASettings(); + onSharedPreferenceChanged(); + } else { + RotateTextToast.makeText(mActivity, "Invalid exposure time", + Toast.LENGTH_SHORT).show(); + } + } + }); + alert.show(); + } else if (manualExposureMode.equals(userSetting)) { + alert.setMessage("Full manual mode - Enter both ISO and Exposure Time"); + final TextView ISORangeText = new TextView(mActivity); + final TextView ExpTimeRangeText = new TextView(mActivity); + ISORangeText.setText("Enter ISO in the range of " + minISO + " to " + maxISO); + ExpTimeRangeText.setText("Enter exposure time in the range of " + minExpTime + + "ms to " + maxExpTime + "ms"); + linear.addView(ISORangeText); + linear.addView(ISOinput); + linear.addView(ISOtext); + linear.addView(ExpTimeRangeText); + linear.addView(ExpTimeInput); + linear.addView(ExpTimeText); + alert.setView(linear); + alert.setPositiveButton("Ok",new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog,int id) + { + int newISO = -1; + String iso = ISOinput.getText().toString(); + Log.v(TAG, "string iso length " + iso.length()); + if (iso.length() > 0) { + newISO = Integer.parseInt(iso); + } + double newExpTime = -1; + String expTime = ExpTimeInput.getText().toString(); + if (expTime.length() > 0) { + try { + newExpTime = Double.parseDouble(expTime); + } catch (NumberFormatException e) { + Log.w(TAG, "input newExpTime " + newExpTime + " is invalid"); + newExpTime = Double.parseDouble(maxExpTime) + 1f; + } + + } + if (newISO <= maxISO && newISO >= minISO && + newExpTime <= Double.parseDouble(maxExpTime) && + newExpTime >= Double.parseDouble(minExpTime)) { + mManual3AEnabled |= MANUAL_EXPOSURE; + Log.v(TAG, "Setting ISO : " + newISO); + mParameters.setISOValue(isoManual); + mParameters.set(CameraSettings.KEY_CONTINUOUS_ISO, newISO); + Log.v(TAG, "Setting Exposure time : " + newExpTime); + mParameters.set(CameraSettings.KEY_EXPOSURE_TIME, expTime); + updateCommonManual3ASettings(); + onSharedPreferenceChanged(); + } else { + RotateTextToast.makeText(mActivity, "Invalid input", Toast.LENGTH_SHORT) + .show(); + } + } + }); + alert.show(); + } else { + mManual3AEnabled &= ~MANUAL_EXPOSURE; + //auto exposure mode - reset both exposure time and ISO + mParameters.set(CameraSettings.KEY_EXPOSURE_TIME, "0"); + mUI.overrideSettings(CameraSettings.KEY_ISO, null); + updateCommonManual3ASettings(); + onSharedPreferenceChanged(); + } + } + + // Return true if the preference has the specified key but not the value. + private static boolean notSame(ListPreference pref, String key, String value) { + return (key.equals(pref.getKey()) && !value.equals(pref.getValue())); + } + + @Override + public void onSharedPreferenceChanged(ListPreference pref) { + // ignore the events after "onPause()" + if (mPaused) return; + + //filter off unsupported settings + final String settingOff = mActivity.getString(R.string.setting_off_value); + if (!CameraSettings.isZSLHDRSupported(mParameters)) { + //HDR internally uses AE-bracketing. Disable both if not supported. + if (notSame(pref, CameraSettings.KEY_CAMERA_HDR, settingOff) || + notSame(pref, CameraSettings.KEY_AE_BRACKET_HDR, settingOff)) { + mUI.setPreference(CameraSettings.KEY_ZSL,settingOff); + } else if (notSame(pref,CameraSettings.KEY_ZSL,settingOff)) { + mUI.setPreference(CameraSettings.KEY_CAMERA_HDR, settingOff); + mUI.setPreference(CameraSettings.KEY_AE_BRACKET_HDR, settingOff); + } + } + + if(CameraSettings.KEY_MANUAL_EXPOSURE.equals(pref.getKey())) { + UpdateManualExposureSettings(); + return; + } + if (CameraSettings.KEY_MANUAL_WB.equals(pref.getKey())) { + UpdateManualWBSettings(); + return; + } + if (CameraSettings.KEY_MANUAL_FOCUS.equals(pref.getKey())) { + UpdateManualFocusSettings(); + return; + } + + if (CameraSettings.KEY_CAMERA_SAVEPATH.equals(pref.getKey())) { + Storage.setSaveSDCard( + mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1")); + mActivity.updateStorageSpaceAndHint(); + updateRemainingPhotos(); + } + + if (CameraSettings.KEY_QC_CHROMA_FLASH.equals(pref.getKey())) { + mUI.setPreference(CameraSettings.KEY_ADVANCED_FEATURES, pref.getValue()); + } + + String ubiFocusOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_ubifocus_off); + String chromaFlashOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_chromaflash_off); + String optiZoomOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_optizoom_off); + String reFocusOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_refocus_off); + String fssrOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_FSSR_off); + String truePortraitOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_trueportrait_off); + String multiTouchFocusOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_multi_touch_focus_off); + String stillMoreOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_stillmore_off); + String advancedFeatureOff = mActivity.getString(R.string. + pref_camera_advanced_feature_value_none); + if (notSame(pref, CameraSettings.KEY_QC_OPTI_ZOOM, optiZoomOff) || + notSame(pref, CameraSettings.KEY_QC_AF_BRACKETING, ubiFocusOff) || + notSame(pref, CameraSettings.KEY_QC_FSSR, fssrOff) || + notSame(pref, CameraSettings.KEY_QC_TP, truePortraitOff) || + notSame(pref, CameraSettings.KEY_QC_MULTI_TOUCH_FOCUS, multiTouchFocusOff) || + notSame(pref, CameraSettings.KEY_QC_STILL_MORE, stillMoreOff) || + notSame(pref, CameraSettings.KEY_QC_RE_FOCUS, reFocusOff) || + notSame(pref, CameraSettings.KEY_ADVANCED_FEATURES, advancedFeatureOff)) { + RotateTextToast.makeText(mActivity, R.string.advanced_capture_disable_continuous_shot, + Toast.LENGTH_LONG).show(); + } + //call generic onSharedPreferenceChanged + onSharedPreferenceChanged(); + } + + @Override + public void onSharedPreferenceChanged() { + // ignore the events after "onPause()" + if (mPaused) return; + + boolean recordLocation = RecordLocationPreference.get( + mPreferences, mContentResolver); + mLocationManager.recordLocation(recordLocation); + if(needRestart()){ + Log.v(TAG, "Restarting Preview... Camera Mode Changed"); + stopPreview(); + startPreview(); + setCameraState(IDLE); + mRestartPreview = false; + } + /* Check if the PhotoUI Menu is initialized or not. This + * should be initialized during onCameraOpen() which should + * have been called by now. But for some reason that is not + * executed till now, then schedule these functionality for + * later by posting a message to the handler */ + if (mUI.mMenuInitialized) { + setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE); + mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup, + mPreferences); + } else { + mHandler.sendEmptyMessage(SET_PHOTO_UI_PARAMS); + } + resizeForPreviewAspectRatio(); + } + + @Override + public void onCameraPickerClicked(int cameraId) { + if (mPaused || mPendingSwitchCameraId != -1) return; + + mPendingSwitchCameraId = cameraId; + + Log.v(TAG, "Start to switch camera. cameraId=" + cameraId); + // We need to keep a preview frame for the animation before + // releasing the camera. This will trigger onPreviewTextureCopied. + //TODO: Need to animate the camera switch + switchCamera(); + } + + // Preview texture has been copied. Now camera can be released and the + // animation can be started. + @Override + public void onPreviewTextureCopied() { + mHandler.sendEmptyMessage(SWITCH_CAMERA); + } + + @Override + public void onCaptureTextureCopied() { + } + + @Override + public void onUserInteraction() { + if (!mActivity.isFinishing()) keepScreenOnAwhile(); + } + + private void resetScreenOn() { + mHandler.removeMessages(CLEAR_SCREEN_DELAY); + mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + + private void keepScreenOnAwhile() { + mHandler.removeMessages(CLEAR_SCREEN_DELAY); + mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY); + } + + @Override + public void onOverriddenPreferencesClicked() { + if (mPaused) return; + mUI.showPreferencesToast(); + } + + private void showTapToFocusToast() { + // TODO: Use a toast? + new RotateTextToast(mActivity, R.string.tap_to_focus, 0).show(); + // Clear the preference. + Editor editor = mPreferences.edit(); + editor.putBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, false); + editor.apply(); + } + + private void initializeCapabilities() { + mFocusAreaSupported = CameraUtil.isFocusAreaSupported(mInitialParams); + mMeteringAreaSupported = CameraUtil.isMeteringAreaSupported(mInitialParams); + mAeLockSupported = CameraUtil.isAutoExposureLockSupported(mInitialParams); + mAwbLockSupported = CameraUtil.isAutoWhiteBalanceLockSupported(mInitialParams); + mContinuousFocusSupported = mInitialParams.getSupportedFocusModes().contains( + CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE); + } + + @Override + public void onCountDownFinished() { + mSnapshotOnIdle = false; + initiateSnap(); + mFocusManager.onShutterUp(); + mUI.overrideSettings(CameraSettings.KEY_ZSL, null); + mUI.showUIAfterCountDown(); + } + + @Override + public void onShowSwitcherPopup() { + mUI.onShowSwitcherPopup(); + } + + @Override + public int onZoomChanged(int index) { + // Not useful to change zoom value when the activity is paused. + if (mPaused) return index; + mZoomValue = index; + if (mParameters == null || mCameraDevice == null) return index; + // Set zoom parameters asynchronously + synchronized (mCameraDevice) { + mParameters.setZoom(mZoomValue); + mCameraDevice.setParameters(mParameters); + Parameters p = mCameraDevice.getParameters(); + if (p != null) return p.getZoom(); + } + return index; + } + + @Override + public int getCameraState() { + return mCameraState; + } + + @Override + public void onQueueStatus(boolean full) { + mUI.enableShutter(!full); + } + + @Override + public void onMediaSaveServiceConnected(MediaSaveService s) { + // We set the listener only when both service and shutterbutton + // are initialized. + if (mFirstTimeInitialized) { + s.setListener(this); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + + @Override + public void onSensorChanged(SensorEvent event) { + int type = event.sensor.getType(); + float[] data; + if (type == Sensor.TYPE_ACCELEROMETER) { + data = mGData; + } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { + data = mMData; + } else { + // we should not be here. + return; + } + for (int i = 0; i < 3 ; i++) { + data[i] = event.values[i]; + } + float[] orientation = new float[3]; + SensorManager.getRotationMatrix(mR, null, mGData, mMData); + SensorManager.getOrientation(mR, orientation); + mHeading = (int) (orientation[0] * 180f / Math.PI) % 360; + if (mHeading < 0) { + mHeading += 360; + } + } + @Override + public void onPreviewFocusChanged(boolean previewFocused) { + mUI.onPreviewFocusChanged(previewFocused); + } + // TODO: Delete this function after old camera code is removed + @Override + public void onRestorePreferencesClicked() {} + +/* + * Provide a mapping for Jpeg encoding quality levels + * from String representation to numeric representation. + */ + @Override + public boolean arePreviewControlsVisible() { + return mUI.arePreviewControlsVisible(); + } + + // For debugging only. + public void setDebugUri(Uri uri) { + mDebugUri = uri; + } + + // For debugging only. + private void saveToDebugUri(byte[] data) { + if (mDebugUri != null) { + OutputStream outputStream = null; + try { + outputStream = mContentResolver.openOutputStream(mDebugUri); + outputStream.write(data); + outputStream.close(); + } catch (IOException e) { + Log.e(TAG, "Exception while writing debug jpeg file", e); + } finally { + CameraUtil.closeSilently(outputStream); + } + } + } + + public boolean isRefocus() { + return mLastPhotoTakenWithRefocus; + } + + @Override + public void onMakeupLevel(String key, String value) { + synchronized (mCameraDevice) { + onMakeupLevelSync(key, value); + } + } + + public void onMakeupLevelSync(String key, String value) { + Log.d(TAG, "PhotoModule.onMakeupLevel(): key is " + key + ", value is " + value); + + if(TextUtils.isEmpty(value)) { + return; + } + + String prefValue = TsMakeupManager.MAKEUP_ON; + if(TsMakeupManager.MAKEUP_OFF.equals(value)) { + prefValue = TsMakeupManager.MAKEUP_OFF; + } + + Log.d(TAG, "onMakeupLevel(): prefValue is " + prefValue); + mParameters.set(CameraSettings.KEY_TS_MAKEUP_PARAM, prefValue); + + if(!TextUtils.isDigitsOnly(value)) { + if(TsMakeupManager.MAKEUP_NONE.equals(value)) { + ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_TS_MAKEUP_LEVEL_WHITEN); + if(pref != null) { + String whitenValue = pref.getValue(); + if(TextUtils.isEmpty(whitenValue)) { + whitenValue = mActivity.getString(R.string.pref_camera_tsmakeup_level_default); + } + pref.setMakeupSeekBarValue(whitenValue); + mParameters.set(CameraSettings.KEY_TS_MAKEUP_PARAM_WHITEN, Integer.parseInt(whitenValue)); + } + + pref = mPreferenceGroup.findPreference(CameraSettings.KEY_TS_MAKEUP_LEVEL_CLEAN); + if(pref != null) { + String cleanValue = pref.getValue(); + if(TextUtils.isEmpty(cleanValue)) { + cleanValue = mActivity.getString(R.string.pref_camera_tsmakeup_level_default); + } + pref.setMakeupSeekBarValue(cleanValue); + mParameters.set(CameraSettings.KEY_TS_MAKEUP_PARAM_CLEAN, Integer.parseInt(cleanValue)); + } + } + } else { + if(CameraSettings.KEY_TS_MAKEUP_LEVEL.equals(key)) { + if(mParameters != null) { + mParameters.set(CameraSettings.KEY_TS_MAKEUP_PARAM_WHITEN, Integer.parseInt(value)); + mParameters.set(CameraSettings.KEY_TS_MAKEUP_PARAM_CLEAN, Integer.parseInt(value)); + } + ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_TS_MAKEUP_LEVEL_WHITEN); + if(pref != null) { + pref.setMakeupSeekBarValue(value); + } + pref = mPreferenceGroup.findPreference(CameraSettings.KEY_TS_MAKEUP_LEVEL_CLEAN); + if(pref != null) { + pref.setMakeupSeekBarValue(value); + } + } else if(CameraSettings.KEY_TS_MAKEUP_LEVEL_WHITEN.equals(key)) { + if(mParameters != null) { + mParameters.set(CameraSettings.KEY_TS_MAKEUP_PARAM_WHITEN, Integer.parseInt(value)); + } + } else if(CameraSettings.KEY_TS_MAKEUP_LEVEL_CLEAN.equals(key)) { + if(mParameters != null) { + mParameters.set(CameraSettings.KEY_TS_MAKEUP_PARAM_CLEAN, Integer.parseInt(value)); + } + } + } + + mCameraDevice.setParameters(mParameters); + mParameters = mCameraDevice.getParameters(); + } +} + +/* Below is no longer needed, except to get rid of compile error + * TODO: Remove these + */ +class JpegEncodingQualityMappings { + private static final String TAG = "JpegEncodingQualityMappings"; + private static final int DEFAULT_QUALITY = 85; + private static HashMap<String, Integer> mHashMap = + new HashMap<String, Integer>(); + + static { + mHashMap.put("normal", CameraProfile.QUALITY_LOW); + mHashMap.put("fine", CameraProfile.QUALITY_MEDIUM); + mHashMap.put("superfine", CameraProfile.QUALITY_HIGH); + } + + // Retrieve and return the Jpeg encoding quality number + // for the given quality level. + public static int getQualityNumber(String jpegQuality) { + try{ + int qualityPercentile = Integer.parseInt(jpegQuality); + if(qualityPercentile >= 0 && qualityPercentile <=100) + return qualityPercentile; + else + return DEFAULT_QUALITY; + } catch(NumberFormatException nfe){ + //chosen quality is not a number, continue + } + Integer quality = mHashMap.get(jpegQuality); + if (quality == null) { + Log.w(TAG, "Unknown Jpeg quality: " + jpegQuality); + return DEFAULT_QUALITY; + } + return CameraProfile.getJpegEncodingQualityParameter(quality.intValue()); + } +} + +class GraphView extends View { + private Bitmap mBitmap; + private Paint mPaint = new Paint(); + private Paint mPaintRect = new Paint(); + private Canvas mCanvas = new Canvas(); + private float mScale = (float)3; + private float mWidth; + private float mHeight; + private PhotoModule mPhotoModule; + private CameraManager.CameraProxy mGraphCameraDevice; + private float scaled; + private static final int STATS_SIZE = 256; + private static final String TAG = "GraphView"; + + + public GraphView(Context context, AttributeSet attrs) { + super(context,attrs); + + mPaint.setFlags(Paint.ANTI_ALIAS_FLAG); + mPaintRect.setColor(0xFFFFFFFF); + mPaintRect.setStyle(Paint.Style.FILL); + } + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565); + mCanvas.setBitmap(mBitmap); + mWidth = w; + mHeight = h; + super.onSizeChanged(w, h, oldw, oldh); + } + @Override + protected void onDraw(Canvas canvas) { + Log.v(TAG, "in Camera.java ondraw"); + if(mPhotoModule == null || !mPhotoModule.mHiston ) { + Log.e(TAG, "returning as histogram is off "); + return; + } + + if (mBitmap != null) { + final Paint paint = mPaint; + final Canvas cavas = mCanvas; + final float border = 5; + float graphheight = mHeight - (2 * border); + float graphwidth = mWidth - (2 * border); + float left,top,right,bottom; + float bargap = 0.0f; + float barwidth = graphwidth/STATS_SIZE; + + cavas.drawColor(0xFFAAAAAA); + paint.setColor(Color.BLACK); + + for (int k = 0; k <= (graphheight /32) ; k++) { + float y = (float)(32 * k)+ border; + cavas.drawLine(border, y, graphwidth + border , y, paint); + } + for (int j = 0; j <= (graphwidth /32); j++) { + float x = (float)(32 * j)+ border; + cavas.drawLine(x, border, x, graphheight + border, paint); + } + synchronized(PhotoModule.statsdata) { + //Assumption: The first element contains + // the maximum value. + int maxValue = Integer.MIN_VALUE; + if ( 0 == PhotoModule.statsdata[0] ) { + for ( int i = 1 ; i <= STATS_SIZE ; i++ ) { + if ( maxValue < PhotoModule.statsdata[i] ) { + maxValue = PhotoModule.statsdata[i]; + } + } + } else { + maxValue = PhotoModule.statsdata[0]; + } + mScale = ( float ) maxValue; + for(int i=1 ; i<=STATS_SIZE ; i++) { + scaled = (PhotoModule.statsdata[i]/mScale)*STATS_SIZE; + if(scaled >= (float)STATS_SIZE) + scaled = (float)STATS_SIZE; + left = (bargap * (i+1)) + (barwidth * i) + border; + top = graphheight + border; + right = left + barwidth; + bottom = top - scaled; + cavas.drawRect(left, top, right, bottom, mPaintRect); + } + } + canvas.drawBitmap(mBitmap, 0, 0, null); + } + if (mPhotoModule.mHiston && mPhotoModule!= null) { + mGraphCameraDevice = mPhotoModule.getCamera(); + if (mGraphCameraDevice != null){ + mGraphCameraDevice.sendHistogramData(); + } + } + } + public void PreviewChanged() { + invalidate(); + } + public void setPhotoModuleObject(PhotoModule photoModule) { + mPhotoModule = photoModule; + } +} + +class DrawAutoHDR extends View{ + + private static final String TAG = "AutoHdrView"; + private PhotoModule mPhotoModule; + + public DrawAutoHDR (Context context, AttributeSet attrs) { + super(context,attrs); + } + + @Override + protected void onDraw (Canvas canvas) { + if (mPhotoModule == null) + return; + if (mPhotoModule.mAutoHdrEnable) { + Paint AutoHDRPaint = new Paint(); + AutoHDRPaint.setColor(Color.WHITE); + AutoHDRPaint.setAlpha (0); + canvas.drawPaint(AutoHDRPaint); + AutoHDRPaint.setStyle(Paint.Style.STROKE); + AutoHDRPaint.setColor(Color.MAGENTA); + AutoHDRPaint.setStrokeWidth(1); + AutoHDRPaint.setTextSize(16); + AutoHDRPaint.setAlpha (255); + canvas.drawText("HDR On",200,100,AutoHDRPaint); + } + else { + super.onDraw(canvas); + return; + } + } + + public void AutoHDR () { + invalidate(); + } + + public void setPhotoModuleObject (PhotoModule photoModule) { + mPhotoModule = photoModule; + } +} |