/*
* 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.ContentProviderClient;
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.graphics.SurfaceTexture;
import android.graphics.drawable.Drawable;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.hardware.Camera.Area; // SPRD: add for multi-focus
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.media.CameraProfile;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
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.View;
import android.view.WindowManager;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.FrameLayout;
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.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 com.android.camera2.R;
import com.sprd.camera.ZSLController;
import com.android.camera.util.Tuple; // SPRD: porting multi-focus
import com.android.camera.ui.FreezeFrameDisplayView;
import com.android.camera.ui.Rotatable;
import com.sprd.camera.AlertDialogPopup; // SPRD: for restore preferences
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import java.util.ArrayList;
public class PhotoModule
implements CameraModule,
PhotoController,
FocusOverlayManager.Listener,
CameraPreference.OnPreferenceChangedListener,
ShutterButton.OnShutterButtonListener,
MediaSaveService.Listener,
OnCountDownFinishedListener,
SensorEventListener {
private static final boolean DEBUG = true;
private static final String TAG = "CAM_PhotoModule";
// 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 SWITCH_TO_GCAM_MODULE = 11;
// 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 PhotoUI mUI;
// SPRD: bug 260858
private boolean mEnableTopButton;
private boolean mEnableCameraSet;
// 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;
// The degrees of the device rotated clockwise from its natural orientation.
private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
// @{ SPRD: fix bug 255774 start
// The orientation compensation for icons and thumbnails. Ex: if the value
// is 90, the UI components should be rotated 90 degrees counter-clockwise.
private int mOrientationCompensation = 0;
// fix bug 255774 end @}
private ComboPreferences mPreferences;
private RotateDialogController mRotateDialog;
private static final String sTempCropFilename = "crop-temp";
private ContentProviderClient mMediaProviderClient;
private boolean mFaceDetectionStarted = false;
// SPRD: It is flag for taking picture.
private boolean mIsTakingPicture = false;
// mCropValue and mSaveUri are used only if isImageCaptureIntent() is true.
private String mCropValue;
private Uri mSaveUri;
// SPRD:ZSLController.
private ZSLController mZSLController;
private Uri mDebugUri;
// 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 int mContinuousCaptureCount;
private Runnable mDoSnapRunnable = new Runnable() {
@Override
public void run() {
onShutterButtonClick();
}
};
/**
* 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 = PREVIEW_STOPPED;
private boolean mSnapshotOnIdle = false;
private ContentResolver mContentResolver;
private LocationManager mLocationManager;
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 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 final Handler mHandler = new MainHandler();
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;
private static final int VAL_DEFAULT_CAPTURE_COUNT = 1;
private int mContinueTakePictureCount;
// True if all the parameters needed to start preview is ready.
private boolean mCameraPreviewParamsReady = false;
private MediaSaveService.OnMediaSavedListener mOnMediaSavedListener =
new MediaSaveService.OnMediaSavedListener() {
@Override
public void onMediaSaved(Uri uri) {
// @{ SPRD: Dont notifyNewMedia if FreezeFrame display begin
// if (uri != null) {
// mActivity.notifyNewMedia(uri);
// }
if ((sFreezeFrameControl != null
&& sFreezeFrameControl.isFreezeFrame()) || mIsImageCaptureIntent) {
if (uri != null) {
sFreezeFrameControl.proxyRunLoadProxy(uri);
} else {
sFreezeFrameControl.proxyDoneClicked();
}
} else {
if (uri != null) {
mActivity.notifyNewMedia(uri);
} // @{ SPRD: Dont notifyNewMedia if FreezeFrame display end
}
}
};
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);
}
}
/**
* 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;
/* SPRD :add VideoCall check toast @{ */
if (mActivity.checkTelephoneVideoCall()) {
CameraUtil.showErrorAndFinish(mActivity,
R.string.in_video_call_is_running);
} else {
CameraUtil.showErrorAndFinish(mActivity,
R.string.cannot_connect_camera);
}
/* }@ */
break;
}
case CAMERA_DISABLED: {
mCameraDisabled = true;
CameraUtil.showErrorAndFinish(mActivity,
R.string.camera_disabled);
break;
}
case SWITCH_TO_GCAM_MODULE: {
mActivity.onModuleSelected(ModuleSwitcher.GCAM_MODULE_INDEX);
}
}
}
}
@Override
public void init(CameraActivity activity, View parent) {
mActivity = activity;
mUI = new PhotoUI(activity, this, parent);
mPreferences = new ComboPreferences(mActivity);
CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal());
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();
// @{ SPRD: bug 258455 begin
// if (mIsImageCaptureIntent) {
// mActivity.setModuleVisble(View.INVISIBLE);
// } // SPRD: bug 258455 end @}
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
// we need to reset exposure for the preview
resetExposureCompensation();
initializeControlByIntent();
mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false);
mLocationManager = new LocationManager(mActivity, mUI);
mSensorManager = (SensorManager)(mActivity.getSystemService(Context.SENSOR_SERVICE));
// SPRD initialize mJpegQualityController.
mJpegQualityController = new JpegQualityController();
//SPRD:Add for freeze_display
mRotateDialog = new RotateDialogController(mActivity, R.layout.rotate_dialog);
sFreezeFrameControl = new FreezeFrameDisplayControl();
}
private void initializeControlByIntent() {
mUI.initializeControlByIntent();
if (mIsImageCaptureIntent) {
setupCaptureParams();
}
// SPRD:initialize CustomController, HDR,ZSL etc.
initializeCustomController();
// SPRD: bug 260858
mEnableTopButton = true;
mEnableCameraSet = true;
}
private void onPreviewStarted() {
setCameraState(IDLE);
startFaceDetection();
locationFirstRun();
}
// Prompt the user to pick to record location for the very first run of
// camera only
private void locationFirstRun() {
if (RecordLocationPreference.isSet(mPreferences)) {
return;
}
if (mActivity.isSecureCamera()) 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;
}
// SPRD: hide GPS item on the 7715
if (!CameraUtil.isSupportedGps()) {
mPreferences.edit().putString(
CameraSettings.KEY_RECORD_LOCATION, RecordLocationPreference.VALUE_OFF)
.apply();
return;
}
mUI.showLocationDialog();
}
@Override
public void enableRecordingLocation(boolean enable) {
setLocationPreference(enable ? RecordLocationPreference.VALUE_ON
: RecordLocationPreference.VALUE_OFF);
}
@Override
public void onPreviewUIReady() {
startPreview();
}
@Override
public void onPreviewUIDestroyed() {
if (mCameraDevice == null) {
return;
}
stopPreview();
mCameraDevice.setPreviewTexture(null);
}
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() {
View root = mUI.getRootView();
// These depend on camera parameters.
int width = root.getWidth();
int height = root.getHeight();
mFocusManager.setPreviewSize(width, height);
openCameraCommon();
}
private void switchCamera() {
if (mPaused) return;
Log.v(TAG, "Start to switch camera. id=" + mPendingSwitchCameraId);
mCameraId = mPendingSwitchCameraId;
mPendingSwitchCameraId = -1;
setCameraId(mCameraId);
// from onPause
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();
initializeCapabilities();
CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
mFocusManager.setMirror(mMirror);
mFocusManager.setParameters(mInitialParams);
setupPreview();
/*SPRD: Add for ZSL HDR and FREEZE @{ */
sFreezeFrameControl.proxySharedPreferenceChanged();
//mHDRController.proxyResetSwitcherEnforcement(mPreferences, mParameters);
mUI.enableSwitchCameraButton(true);//add by sprd for bug456
mZSLController.proxyResetSwitcherEnforcement(
mPreferences, mParameters, isHdrOn());
/* @} */
// reset zoom value index
// mZoomValue = 0;
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);
if (mIsImageCaptureIntent) {
mUI.overrideSettings(CameraSettings.KEY_CAMERA_HDR_PLUS,
mActivity.getString(R.string.setting_off_value));
}
//orig
//updateSceneMode();
updateSettingsMutex();
showTapToFocusToastIfNeeded();
}
@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 keepMediaProviderInstance() {
// We want to keep a reference to MediaProvider in camera's lifecycle.
// TODO: Utilize mMediaProviderClient instance to replace
// ContentResolver calls.
if (mMediaProviderClient == null) {
mMediaProviderClient = mContentResolver
.acquireContentProviderClient(MediaStore.AUTHORITY);
}
}
// 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);
keepMediaProviderInstance();
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();
mFirstTimeInitialized = true;
addIdleHandler();
/* SPRD: Initialize ZSL controller */
if (mZSLController != null) {
mZSLController.proxyResetSwitcherValue(mPreferences);
}
mActivity.updateStorageSpaceAndHint();
}
// 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();
mUI.initializeSecondTime(mParameters);
keepMediaProviderInstance();
/* SPRD: Add for ZSL @{*/
if (mZSLController != null) {
mZSLController.proxyResetSwitcherValue(mPreferences);
}
/* @} */
}
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)
// SPRD: AOB, check current is camera preview state
&& (mActivity != null && mActivity.proxyIsCameraPreview())) {
// Delay the toast for one second to wait for orientation.
mHandler.sendEmptyMessageDelayed(SHOW_TAP_TO_FOCUS_TOAST, 1000);
}
}
private void addIdleHandler() {
MessageQueue queue = Looper.myQueue();
queue.addIdleHandler(new MessageQueue.IdleHandler() {
@Override
public boolean queueIdle() {
Storage.ensureOSXCompatible();
return false;
}
});
}
@Override
public void startFaceDetection() {
if (mFaceDetectionStarted) 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 (!mFaceDetectionStarted) return;
if (mParameters.getMaxNumDetectedFaces() > 0) {
mFaceDetectionStarted = false;
mCameraDevice.setFaceDetectionCallback(null, null);
mCameraDevice.stopFaceDetection();
mUI.clearFaces();
}
}
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.v(TAG, "mShutterLag = " + mShutterLag + "ms");
if (mNeedsAnimation) {
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
animateAfterShutter();
}
});
}
}
}
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 JpegPictureCallback
implements CameraPictureCallback {
Location mLocation;
public JpegPictureCallback(Location loc) {
mLocation = loc;
Log.d(TAG, "JpegPictureCallback continuous capture count=" + mContinuousCaptureCount);
}
@Override
public void onPictureTaken(final byte [] jpegData, CameraProxy camera) {
mNamedImages.nameNewImage(mCaptureStartTime);
// SPRD: HDR screen hint supported
if (mUI != null) {
mUI.enableHdrScreenHint(false, mPreferences);
}
if (mPaused || --mContinuousCaptureCount < 0) {
return;
}
if (mIsImageCaptureIntent) {
stopPreview();
}
ExifInterface exif = Exif.getExif(jpegData);
int orientation = Exif.getOrientation(exif);
if (!mIsImageCaptureIntent && mContinuousCaptureCount == 0) {
mUI.animateCapture(jpegData, orientation, false);
}
// @{ SPRD: bug 262395 hide module switcher view be not expect hdr begin
//showSwitcher();
mUI.setSwipingEnabled(true);
/* if (mSceneMode == CameraUtil.SCENE_MODE_HDR) {
mUI.showSwitcher();
mUI.setSwipingEnabled(true);
} SPRD: hide module switcher view be not expect hdr end*/
// Check this in advance of each shot so we don't add to shutter
// latency. It's true that someone else could write to the SD card in
// the mean time and fill it, but that could have happened between the
// shutter press and saving the JPEG too.
mActivity.updateStorageSpaceAndHint();
mJpegPictureCallbackTime = System.currentTimeMillis();
// 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");
// @{ SPRD: bug 251198
//if (mIsImageCaptureIntent) {
// sFreezeFrameControl.proxyRunLoadProxy(jpegData);
//}// @}
mFocusManager.updateFocusUI(); // Ensure focus indicator is hidden.
/* @origin
if (!mIsImageCaptureIntent) {
setupPreview();
}*/
/* SPRD:Add for HDR ZSL @{ */
//if (mHDRController != null)
// mHDRController.proxyDismissWaiting();
Log.v(TAG, "mContinuousCaptureCount = "+ mContinuousCaptureCount);
if (!mIsImageCaptureIntent) {
if ((mZSLController.switchOff() || isHdrOn()) && mContinuousCaptureCount <= 0) {
setupPreview();
} else if (mZSLController.switchOn()) {
setCameraState(IDLE);
startPreview(CameraActivity.KEY_MODE_ZSL);
} else {
// Camera HAL of some devices have a bug. Starting preview
// immediately after taking a picture will fail. Wait some
// time before starting the preview.
if (!isContinueTakePicture()) {
mHandler.sendEmptyMessageDelayed(SETUP_PREVIEW, 300);
}
}
}
/* @} add for HDR ZSL end */
// 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;
}
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);
}
mActivity.getMediaSaveService().addImage(
jpegData, title, date, mLocation, width, height,
orientation, exif, mOnMediaSavedListener, mContentResolver, CameraUtil.MODE_CAMERA);
}
// SPRD: If mIsImageCaptureIntent is true use freezeframe show picture
if(mIsImageCaptureIntent) {
mJpegImageData = jpegData;
if(!mQuickCapture) {
sFreezeFrameControl.proxyAnimation(true);
} else {
onCaptureDone();
}
} else {
if (sFreezeFrameControl != null &&
sFreezeFrameControl.isFreezeFrame()) {
sFreezeFrameControl.proxyAnimation(true);
}
// Animate capture with real jpeg data instead of a preview frame.
}
if (mContinuousCaptureCount <=0 && !isContinueTakePicture()) {
updateCameraControls();
mIsTakingPicture = false;
} else {
mIsTakingPicture = true;
}
long now = System.currentTimeMillis();
mJpegCallbackFinishTime = now - mJpegPictureCallbackTime;
Log.v(TAG, "mJpegCallbackFinishTime = "
+ mJpegCallbackFinishTime + "ms");
mJpegPictureCallbackTime = 0;
}
}
/* SPRD: Add for ZSL @{ */
private void startPreview(int mode) {
Log.d(TAG, "startPreview in ZSL mode");
if (mPaused) {
return;
}
mFocusManager.resetTouchFocus();
mCameraDevice.setErrorCallback(mErrorCallback);
setDisplayOrientation();
mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation);
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();
}
mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
}
setCameraParameters(UPDATE_PARAM_ALL);
// Let UI set its expected aspect ratio
mFocusManager.onPreviewStarted();
if (mSnapshotOnIdle || mActivity.isAutoCapture()) {
mHandler.post(mDoSnapRunnable);
}
}
/* @} */
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");
setCameraState(IDLE);
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 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.SWITCHING_CAMERA:
case PhotoController.FOCUSING:
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
// SPRD: remove animation from customer requirement
// if (!mIsImageCaptureIntent) {
// mUI.animateFlash();
// }
}
@Override
public boolean capture() {
mEnableTopButton = false;
// 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()) {
Log.i(TAG, "Capture is rerurn !");
return false;
}
mCaptureStartTime = System.currentTimeMillis();
mPostViewPictureCallbackTime = 0;
mJpegImageData = null;
final boolean animateBefore = (mSceneMode == CameraUtil.SCENE_MODE_HDR);
if (animateBefore) {
animateAfterShutter();
}
// Set rotation and gps data.
int orientation;
// We need to be consistent with the framework orientation (i.e. the
// orientation of the UI.) when the auto-rotate screen setting is on.
if (mActivity.isAutoRotateScreen()) {
orientation = (360 - mDisplayRotation) % 360;
} else {
orientation = mOrientation;
}
mJpegRotation = CameraUtil.getJpegRotation(mCameraId, orientation);
mParameters.setRotation(mJpegRotation);
Location loc = mLocationManager.getCurrentLocation();
CameraUtil.setGpsParameters(mParameters, loc);
mParameters.set(CameraSettings.KEY_CAPTURE_MODE, mContinuousCaptureCount);
Log.v(TAG, "take pictrue starting mParameters =" +mParameters.flatten());
mCameraDevice.setParameters(mParameters);
// We don't want user to press the button again while taking a
// multi-second HDR photo.
mUI.enableShutter(false);
mCameraDevice.takePicture(mHandler,
new ShutterCallback(!animateBefore),
mRawPictureCallback, mPostViewPictureCallback,
new JpegPictureCallback(loc));
mNamedImages.nameNewImage(mCaptureStartTime);
mFaceDetectionStarted = false;
setCameraState(SNAPSHOT_IN_PROGRESS);
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 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 updateSceneMode() {
// If scene mode is set, we cannot set flash mode, white balance, and
// focus mode, instead, we read it from driver
if (!Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) {
overrideCameraSettings(mParameters.getFlashMode(),
mParameters.getWhiteBalance(), mParameters.getFocusMode());
} else {
overrideCameraSettings(null, null, null);
}
}
private void overrideCameraSettings(final String flashMode,
final String whiteBalance, final String focusMode) {
mUI.overrideSettings(
CameraSettings.KEY_FLASH_MODE, flashMode,
CameraSettings.KEY_WHITE_BALANCE, whiteBalance,
CameraSettings.KEY_FOCUS_MODE, focusMode);
}
/*
* SPRD: added 20140109 of 256391 HDR, SceneMode Setting Mutex @{
* Describe:
* Use a Bit-like array named overrideIndex to describe the
* mutex macro, one setting respond to one bit.
* Use a String... array named
* overrideItem to describe the mutex Settings key-value.
* Attention, overrideItem length must equal the macro sum * 2, no less, no more.
* Attention, override value comes from mPreferences, and the current hardware value is the default one.
*/
@Override
public void updateSettingsMutex() {
// define the mutex macro
int len = 0;
int WHITE_BALANCE = 1 << (len++);
int FLASH_MODE = 1 << (len++);
int FOCUS_MODE = 1 << (len++);
int EXPOSURE = 1 << (len++);
int SCENE_MODE = 1 << (len++);
int PICTURE_SIZE = 1 << (len++);
int CAMERA_VIDEO_ZSL = 1 << (len++);
int CAMERA_CONTINUOUS_CAPTURE = 1 << (len++);
String overrideItem[] = new String[len * 2];
// define overrideIndex
int overrideIndex = 0;
if (!Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) {
overrideIndex |= WHITE_BALANCE;
overrideIndex |= FLASH_MODE;
overrideIndex |= FOCUS_MODE;
}
if (Parameters.SCENE_MODE_HDR.equals(mSceneMode)) {
overrideIndex |= WHITE_BALANCE;
overrideIndex |= EXPOSURE;
overrideIndex |= SCENE_MODE;
overrideIndex |= PICTURE_SIZE;
overrideIndex |= CAMERA_VIDEO_ZSL;
overrideIndex |= CAMERA_CONTINUOUS_CAPTURE;
}
Log.d(TAG, "overrideIndex = " + overrideIndex);
// define overrideItem
int index = 0;
overrideItem[index++] = CameraSettings.KEY_WHITE_BALANCE;
if ((WHITE_BALANCE & overrideIndex) == WHITE_BALANCE) {
overrideItem[index++] = mPreferences.getString(
CameraSettings.KEY_WHITE_BALANCE, Parameters.WHITE_BALANCE_AUTO);
boolean supported = isSupported(Parameters.WHITE_BALANCE_AUTO,
mParameters.getSupportedWhiteBalance());
if (supported) {
mParameters.setWhiteBalance(Parameters.WHITE_BALANCE_AUTO);
}
} else {
overrideItem[index++] = null;
}
overrideItem[index++] = CameraSettings.KEY_FLASH_MODE;
if ((FLASH_MODE & overrideIndex) == FLASH_MODE) {
overrideItem[index++] = mPreferences.getString(
CameraSettings.KEY_FLASH_MODE, Parameters.FLASH_MODE_OFF);
boolean supported = CameraSettings.VALUE_TRUE.equals(
mParameters.get(CameraSettings.KEY_HAL_FLASH_SUPPORTED));
if (supported) {
mParameters.setFlashMode(Parameters.FLASH_MODE_OFF);
}
} else {
overrideItem[index++] = null;
}
overrideItem[index++] = CameraSettings.KEY_FOCUS_MODE;
if ((FOCUS_MODE & overrideIndex) == FOCUS_MODE) {
overrideItem[index++] = mPreferences.getString(
CameraSettings.KEY_FOCUS_MODE, Parameters.FOCUS_MODE_AUTO);
boolean supported = isSupported(Parameters.FOCUS_MODE_AUTO,
mParameters.getSupportedFocusModes());
if (supported) {
mParameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
}
} else {
overrideItem[index++] = null;
}
overrideItem[index++] = CameraSettings.KEY_EXPOSURE;
if ((EXPOSURE & overrideIndex) == EXPOSURE) {
overrideItem[index++] = mPreferences.getString(
CameraSettings.KEY_EXPOSURE, "0");
mParameters.setExposureCompensation(0);
} else {
overrideItem[index++] = null;
}
overrideItem[index++] = CameraSettings.KEY_SCENE_MODE;
if ((SCENE_MODE & overrideIndex) == SCENE_MODE) {
overrideItem[index++] = mPreferences.getString(
CameraSettings.KEY_SCENE_MODE, Parameters.SCENE_MODE_AUTO);
mParameters.setSceneMode(Parameters.SCENE_MODE_HDR);
} else {
overrideItem[index++] = null;
}
overrideItem[index++] = CameraSettings.KEY_PICTURE_SIZE;
if ((PICTURE_SIZE & overrideIndex) == PICTURE_SIZE) {
overrideItem[index++] = mPreferences.getString(
CameraSettings.KEY_PICTURE_SIZE, null);
} else {
overrideItem[index++] = null;
}
overrideItem[index++] = CameraSettings.KEY_CAMERA_VIDEO_ZSL;
if ((CAMERA_VIDEO_ZSL & overrideIndex) == CAMERA_VIDEO_ZSL) {
overrideItem[index++] = mPreferences.getString(
CameraSettings.KEY_CAMERA_VIDEO_ZSL, CameraSettings.VALUE_OFF);
} else {
overrideItem[index++] = null;
}
overrideItem[index++] = CameraSettings.KEY_CAMERA_CONTINUOUS_CAPTURE;
if ((CAMERA_CONTINUOUS_CAPTURE & overrideIndex) == CAMERA_CONTINUOUS_CAPTURE) {
overrideItem[index++] = mPreferences.getString(
CameraSettings.KEY_CAMERA_CONTINUOUS_CAPTURE, "1");
// mParameters.set(CameraSettings.KEY_CAPTURE_MODE, "1");
} else {
overrideItem[index++] = null;
}
mUI.overrideSettings(overrideItem);
/* Bug 267440 ANR @{ */
if (overrideIndex != 0 && mCameraDevice != null) {
mCameraDevice.setParameters(mParameters);
}
/* @{ */
}
/* @} */
private void loadCameraPreferences() {
CameraSettings settings = new CameraSettings(mActivity, mInitialParams,
mCameraId, CameraHolder.instance().getCameraInfo());
mPreferenceGroup = settings.getPreferenceGroup(R.xml.camera_preferences);
}
@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;
mOrientation = CameraUtil.roundOrientation(orientation, mOrientation);
/* @{ SPRD: fix bug 255774 start */
// When the screen is unlocked, display rotation may change. Always
// calculate the up-to-date orientationCompensation.
int orientationCompensation = mOrientation
+ CameraUtil.getDisplayRotation(mActivity) % 360;
if (mOrientationCompensation != orientationCompensation) {
mOrientationCompensation = orientationCompensation;
}
/* fix bug 255774 end @}*/
// 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();
}
}
@Override
public void onStop() {
if (mMediaProviderClient != null) {
mMediaProviderClient.release();
mMediaProviderClient = null;
}
}
@Override
public void onCaptureCancelled() {
mActivity.setResultEx(Activity.RESULT_CANCELED, new Intent());
mActivity.finish();
}
@Override
public void onCaptureRetake() {
if (mPaused)
return;
/* @{ SPRD: bug 251198 start */
mJpegImageData = null;
/* bug 251198 end @} */
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);
if (outputStream != null) {
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);
}
/* @{ SPRD: bug 251198 start */
mJpegImageData = null;
/* bug 251198 end @} */
// 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 (mPaused || mUI.collapseCameraControls()
|| (mCameraState == SNAPSHOT_IN_PROGRESS)
|| (mCameraState == PREVIEW_STOPPED)) return;
// 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 void onShutterButtonClick() {
if (mPaused || mUI.collapseCameraControls()
|| (mCameraState == SWITCHING_CAMERA)
|| (mCameraState == PREVIEW_STOPPED)
|| isFreezeFrameDisplay()
|| mActivity.getMediaSaveService() == null
|| mActivity.getMediaSaveService().isQueueFull()) {
Log.d(TAG, "onShutterButtonClick is return !");
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);
/* SPRD: fixbug262369 set invisible of thumbnailview in freezeFrame @{ */
if (sFreezeFrameControl != null && sFreezeFrameControl.isFreezeFrame()) {
mUI.setPreviewThumbVisibility(View.INVISIBLE);
}
if (mContinuousCaptureCount <= 0) {
mContinuousCaptureCount = getContinuousCount();
} else if (mIsTakingPicture) {
Log.v(TAG, "Taking picture mContinueTakePictureCount =" + mContinueTakePictureCount);
return;
}
Log.v(TAG, " onShutterButtonClick mContinueTakePictureCount =" + mContinueTakePictureCount);
mUI.hideControlTopButton();
/* @} */
// @{ SPRD: bug 261395 hide module switcher view be not expect hdr begin
hideSwitcher();
// SPRD: bug 260858
mEnableCameraSet = false;
mUI.hideControlsUI();
mUI.setSwipingEnabled(false);
/* if (mSceneMode == CameraUtil.SCENE_MODE_HDR) {
mUI.hideSwitcher();
mUI.setSwipingEnabled(false);
} SPRD: hide module switcher view be not expect hdr @}*/
// 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.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();
}
Log.d(TAG, " mIsTakingPicture = " + mIsTakingPicture + " mContinuousCaptureCount="
+ mContinuousCaptureCount);
mUI.enableShutter(false);
if (seconds > 0) {
mUI.startCountDown(seconds, playSound);
} else {
mSnapshotOnIdle = false;
mFocusManager.doSnap();
// SPRD: HDR screen hint supported
if (mUI != null) {
mUI.enableHdrScreenHint(true, mPreferences);
}
if (mUI != null && isContinueTakePicture()) {
mUI.enableBurstScreenHint(true);
}
}
}
@Override
public void installIntentFilter() {
// Do nothing.
}
@Override
public boolean updateStorageHintOnResume() {
return mFirstTimeInitialized;
}
public void updateCameraAppView() {
//mActivity.updateCameraAppView();//SPRD:Add for freeze_display
}
@Override
public void onResumeBeforeSuper() {
mPaused = false;
}
private boolean prepareCamera() {
// We need to check whether the activity is paused before long
// operations to ensure that onPause() can be done ASAP.
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 false;
}
mParameters = mCameraDevice.getParameters();
initializeCapabilities();
if (mFocusManager == null) initializeFocusManager();
setCameraParameters(UPDATE_PARAM_ALL);
mHandler.sendEmptyMessage(CAMERA_OPEN_DONE);
mCameraPreviewParamsReady = true;
startPreview();
mOnResumeTime = SystemClock.uptimeMillis();
checkDisplayRotation();
return true;
}
@Override
public void onResumeAfterSuper() {
// 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 rmEnableTopButtonesume.");
onResumeTasks();
}
/* @{ SPRD: fix bug 272810 start */
mEnableTopButton = true;
/* end }@ */
mEnableCameraSet = true;
// SPRD: Camera HAL is restarted , continuous is reset.
mContinuousCaptureCount = 0;
}
private void onResumeTasks() {
Log.v(TAG, "Executing onResumeTasks.");
if (mOpenCameraFail || mCameraDisabled) return;
mJpegPictureCallbackTime = 0;
mZoomValue = 0;
resetExposureCompensation();
if (!prepareCamera()) {
// Camera failure.
return;
}
// 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.hidePreviewCover();
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);
}
}
@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);
}
// SPRD: HDR screen hint supported
if (mUI != null) {
mUI.enableHdrScreenHint(false, mPreferences);
mUI.enableBurstScreenHint(false);
}
/* SPRD bug294204 */
if (mCameraState == SNAPSHOT_IN_PROGRESS || mIsTakingPicture) {
mIsTakingPicture = false;
}
}
@Override
public void onPauseAfterSuper() {
Log.v(TAG, "On pause.");
// SPRD: Disable preview cover for preformance.
// mUI.showPreviewCover();
// Reset the focus first. Camera CTS does not guarantee that
// cancelAutoFocus is allowed after preview stops.
if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) {
mCameraDevice.cancelAutoFocus();
}
// 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.
/* @{ SPRD: bug 251198 start */
//mJpegImageData = null;
/* bug 251198 end @} */
// 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);
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
Log.v(TAG, "onConfigurationChanged");
mUI.setShutterButtonRes(newConfig.orientation);
if (mFocusManager != null) {
mFocusManager.resetTouchFocus();
}
setDisplayOrientation();
// SPRD: Update freezeFrame display when change screen configuration
if(sFreezeFrameControl !=null && sFreezeFrameControl.mFreezeVisible)
sFreezeFrameControl.updateFreezeUi();
}
@Override
public void updateCameraOrientation() {
if (mDisplayRotation != CameraUtil.getDisplayRotation(mActivity)) {
setDisplayOrientation();
// SPRD: Update freezeFrame display when camera orientation change
if(sFreezeFrameControl !=null && sFreezeFrameControl.mFreezeVisible)
sFreezeFrameControl.updateFreezeUi();
}
}
@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;
}
}
}
private boolean canTakePicture() {
return isCameraIdle() && (mActivity.getStorageSpaceBytes() > Storage.LOW_STORAGE_THRESHOLD_BYTES);
}
@Override
public void autoFocus() {
// SPRD :Modified this because this will cause camera focus state wrong.
setCameraState(FOCUSING);
mFocusStartTime = System.currentTimeMillis();
mCameraDevice.autoFocus(mHandler, mAutoFocusCallback);
// setCameraState(FOCUSING);
}
@Override
public void cancelAutoFocus() {
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
|| sFreezeFrameControl.mFreezeVisible) {
return;
}
// Check if metering area or focus area is supported.
if (!mFocusAreaSupported && !mMeteringAreaSupported) return;
mFocusManager.onSingleTapUp(x, y);
}
@Override
public boolean onBackPressed() {
return mUI.onBackPressed();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
/* edit by topwise houyi for bug 190
* case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
*/ case KeyEvent.KEYCODE_FOCUS:
if (/*TODO: mActivity.isInCameraApp() &&*/ mFirstTimeInitialized) {
// SPRD: Freeze display don't action the key_down event
if(sFreezeFrameControl != null &&
sFreezeFrameControl.mFreezeVisible) {
return true;
}
if (event.getRepeatCount() == 0) {
onShutterButtonFocus(true);
}
return true;
}
return false;
case KeyEvent.KEYCODE_CAMERA:
// SPRD: Freeze display don't action the key_down event
if(sFreezeFrameControl != null &&
sFreezeFrameControl.mFreezeVisible) {
return true;
}
if (mCameraState == SNAPSHOT_IN_PROGRESS || mIsTakingPicture) {
Log.e(TAG,"Press KEYCODE_CAMERA down,SNAPSHOT_IN_PROGRESS & isCountingDown, So Direct Return.");
return true;
}
if (mFirstTimeInitialized && event.getRepeatCount() == 0) {
onShutterButtonFocus(true);
}
return true;
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) {
//edit by topwise houyi for bug 190
/* case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (mActivity.isInCameraApp() && mFirstTimeInitialized) {
// SPRD: Freeze display don't action the key_up event
if(sFreezeFrameControl != null &&
sFreezeFrameControl.mFreezeVisible) {
return true;
}
if (getCameraState() == SNAPSHOT_IN_PROGRESS || mIsTakingPicture) {
Log.e(TAG,"onKeyUp SNAPSHOT_IN_PROGRESS, So Direct Return.");
return true;
}
onShutterButtonClick();
return true;
}
return false;
*/ case KeyEvent.KEYCODE_FOCUS:
if (mFirstTimeInitialized) {
// SPRD: Freeze display don't action the key_up event
if(sFreezeFrameControl != null &&
sFreezeFrameControl.mFreezeVisible) {
return true;
}
onShutterButtonFocus(false);
}
return true;
case KeyEvent.KEYCODE_CAMERA:
if (mFirstTimeInitialized) {
if (mCameraState == SNAPSHOT_IN_PROGRESS || mIsTakingPicture) {
Log.e(TAG,"Press KEYCODE_CAMERA up,SNAPSHOT_IN_PROGRESS or isCountingDown, So Direct Return.");
return true;
}
if(sFreezeFrameControl != null && sFreezeFrameControl.mFreezeVisible) {
return true;
}
onShutterButtonClick();
return true;
}
return false;
}
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() && !CameraActivity.isFirstStartAfterScreenOn()) {
// Blocks until camera is actually released.
CameraHolder.instance().strongRelease();
} else {
CameraHolder.instance().release();
}
mFaceDetectionStarted = false;
mCameraDevice = null;
setCameraState(PREVIEW_STOPPED);
mFocusManager.onCameraReleased();
}
}
private void setDisplayOrientation() {
mDisplayRotation = CameraUtil.getDisplayRotation(mActivity);
mDisplayOrientation = CameraUtil.getDisplayOrientation(mDisplayRotation, mCameraId);
mCameraDisplayOrientation = mDisplayOrientation;
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, post any view updates to MainHandler. */
private void startPreview() {
if (mPaused || mCameraDevice == null) {
return;
}
// Any decisions we make based on the surface texture state
// need to be protected.
SurfaceTexture st = mUI.getSurfaceTexture();
if (st == null) {
Log.w(TAG, "startPreview: surfaceTexture is not ready.");
return;
}
if (!mCameraPreviewParamsReady) {
Log.w(TAG, "startPreview: parameters for preview is not ready.");
return;
}
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 /*&& !isContinueTakePicture()*/) {
stopPreview();
}
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();
}
mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
}
setCameraParameters(UPDATE_PARAM_ALL);
// updateSettingsMutex(); // SPRD: Before prievew start ,paramter mutex
// must be update.
// Let UI set its expected aspect ratio
mCameraDevice.setPreviewTexture(st);
Log.v(TAG, "startPreview");
mCameraDevice.startPreview();
mFocusManager.onPreviewStarted();
onPreviewStarted();
mUI.enableSwitchCameraButton(true);//add by sprd for bug456
if (mSnapshotOnIdle || mActivity.isAutoCapture()) {
mHandler.post(mDoSnapRunnable);
}
}
@Override
public void stopPreview() {
if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) {
Log.v(TAG, "stopPreview");
mCameraDevice.stopPreview();
mFaceDetectionStarted = false;
}
setCameraState(PREVIEW_STOPPED);
if (mFocusManager != null) mFocusManager.onPreviewStopped();
}
@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()) {
mParameters.setZoom(mZoomValue);
}
}
@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());
}
}
private boolean updateCameraParametersPreference() {
CameraUtil.P(DEBUG, TAG, "updateCameraParametersPreference start");
setAutoExposureLockIfSupported();
setAutoWhiteBalanceLockIfSupported();
setFocusAreasIfSupported();
setMeteringAreasIfSupported();
// Set picture size.
String pictureSize =
mPreferences.getString(CameraSettings.KEY_PICTURE_SIZE, null);
if (pictureSize == null) {
CameraSettings.initialCameraPictureSize(mActivity, mParameters);
} else {
List<Size> supported = mParameters.getSupportedPictureSizes();
CameraSettings.setCameraPictureSize(pictureSize, supported, mParameters);
}
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);
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();
}
if(optimalSize.width != 0 && optimalSize.height != 0) {
mUI.updatePreviewAspectRatio(
(float) optimalSize.width / (float) optimalSize.height);
}
Log.v(TAG, "Preview 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 {
mSceneMode = (hdrOn ?
CameraUtil.SCENE_MODE_HDR :
mPreferences.getString(
CameraSettings.KEY_SCENE_MODE,
mActivity.getString(R.string.pref_camera_scenemode_default)));
if(hdrOn){
mParameters.setExposureCompensation(0);
}
}
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();
}
} else {
mSceneMode = mParameters.getSceneMode();
if (mSceneMode == null) {
mSceneMode = Parameters.SCENE_MODE_AUTO;
}
}
boolean hdrSupported = CameraUtil.isSupported(Parameters.SCENE_MODE_HDR,
mParameters.getSupportedSceneModes());
mUI.setHdrSupported(hdrSupported);
boolean flashSupported = CameraSettings.VALUE_TRUE.equals(
mParameters.get(CameraSettings.KEY_HAL_FLASH_SUPPORTED));
mUI.setFlashSupported(flashSupported);
/** SPRD: set HDR property after reset ZSL property @{ */
if (mZSLController != null) {
boolean debug_reset_zsl =
mZSLController.proxyResetSwitcherValue(mPreferences, mParameters, hdrOn);
if(debug_reset_zsl && mZSLController.switchOn()) {
mUI.setZSLEnable(true);
} else {
mUI.setZSLEnable(false);
}
Log.d(TAG, "we need reset ZSL value to device? " + debug_reset_zsl);
}
/** @} */
// 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.
if(mZSLController.switchOff()) {
String flashMode = mPreferences.getString(
CameraSettings.KEY_FLASH_MODE,
mActivity.getString(R.string.pref_camera_flashmode_default));
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);
}
}
} else { // SPRD: set flash off when ZSL is on
mParameters.setFlashMode(Parameters.FLASH_MODE_OFF);
}
// Set white balance parameter.
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.
mFocusManager.overrideFocusMode(null);
mParameters.setFocusMode(mFocusManager.getFocusMode());
} else {
mFocusManager.overrideFocusMode(mParameters.getFocusMode());
}
if (mContinuousFocusSupported && ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK) {
updateAutoFocusMoveCallback();
}
/* SPRD: Set Antibanding Value To FW.*/
String antibanding = mPreferences.getString(
CameraSettings.KEY_CAMERA_ANTIBANDING,
mActivity.getString(R.string.pref_camera_antibanding_entryvalue_50));
if (CameraUtil.isSupported(antibanding, mParameters.getSupportedAntibanding())) {
mParameters.setAntibanding(antibanding);
}
/* SPRD: Set ISO Value To FW.*/
// String camera_iso = mPreferences.getString(
// CameraSettings.KEY_CAMERA_ISO,
// mActivity.getString(R.string.pref_entry_value_auto));
// if (CameraUtil.isSupported(camera_iso, mParameters.getSupportedISO())) {
// mParameters.setISO(camera_iso);
// }
/* SPRD: Set Color Effect Value To FW.*/
String color_effect = mPreferences.getString(
CameraSettings.KEY_CAMERA_COLOR_EFFECT,
mActivity.getString(R.string.pref_entry_value_none));
if (CameraUtil.isSupported(color_effect, mParameters.getSupportedColorEffects())) {
mParameters.setColorEffect(color_effect);
}
/* SPRD: Set CONTRAST Value To FW.*/
// String contrast = mPreferences.getString(
// CameraSettings.KEY_CAMERA_VIDEO_CONTRAST,
// mActivity.getString(R.string.pref_entry_value_three));
// if (CameraUtil.isSupported(contrast, mParameters.getSupportedContrast())) {
// mParameters.setContrast(contrast);
// }
// Set JPEG quality.
// fixed bug 128513 start
// Sometime "CameraStartUpThread" initialize speed to fast more than main thread,
// But "update hardware parameters" will be call back twice, so don't be worry can
// not re-set "JpegQuality" property on the hardware.
if (mJpegQualityController != null) {
String quality = mPreferences.getString(
CameraSettings.KEY_CAMERA_JPEG_QUALITY,
mActivity.getString(R.string.pref_camera_jpegh_quality_entry_value_super_hight));
int jpegQuality = mJpegQualityController.findJpegQuality(quality);
mParameters.setJpegQuality(jpegQuality);
}
// fixed bug 128513 end
/* SPRD: Set Camera Metering Value To FW.*/
// String metering = mPreferences.getString(
// CameraSettings.KEY_CAMERA_METERING,
// mActivity.getString(R.string.pref_camera_metering_entry_value_frame_average));
// if (CameraUtil.isSupported(metering, mParameters.getSupportedAutoExposureModes())) {
// mParameters.setAutoExposureMode(metering);
// } else {
// metering = mParameters.getAutoExposureMode();
// }
// Set brightness
// String brightness = mPreferences.getString(
// CameraSettings.KEY_CAMERA_BRIGHTNESS,
// mActivity.getString(R.string.pref_entry_value_three));
// if (isSupported(brightness, mParameters.getSupportedBrightness())) {
// mParameters.setBrightness(brightness);
// }
String sharpness = mPreferences.getString(
CameraSettings.KEY_CAMERA_SHARPNESS,
mActivity.getString(R.string.pref_entry_value_three));
// if (isSupported(sharpness, mParameters.getSupportedSharpness())) {
// mParameters.setSharpness(sharpness);
// } else {
// sharpness = mParameters.getSharpness();
// }
String saturation = mPreferences.getString(
CameraSettings.KEY_CAMERA_SATURATION,
mActivity.getString(R.string.pref_entry_value_three));
// if (isSupported(saturation, mParameters.getSupportedSaturation())) {
// mParameters.setSaturation(saturation);
// } else {
// saturation = mParameters.getSaturation();
// }
String burst = mPreferences.getString(
CameraSettings.KEY_CAMERA_CONTINUOUS_CAPTURE, CameraSettings.DETAULT_PICTURE_NUMBER);
if (mIsImageCaptureIntent) {
burst = CameraSettings.DETAULT_PICTURE_NUMBER;
}
if (burst != null ) {
mParameters.set(CameraSettings.KEY_CAPTURE_MODE, burst);
}
/* @{ SPRD: fix bug 273860 start */
String val = mPreferences.getString(
CameraSettings.KEY_TIMER,
mActivity.getString(R.string.pref_camera_timer_default));
int seconds = Integer.parseInt(val);
if (seconds > 0) mUI.instantiateCountDown();
/* end }@ */
CameraUtil.P(DEBUG, TAG, "updateCameraParametersPreference end");
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) {
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();
}
if (DEBUG) {
String message = mParameters.flatten();
CameraUtil.P(DEBUG, TAG, message);
}
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);
//orig
//updateSceneMode();
updateSettingsMutex();
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() {
Intent intent = mActivity.getIntent();
String action = intent.getAction();
mActivity.checkIntent(intent);
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");
}
}
@Override
public void onSharedPreferenceChanged() {
// ignore the events after "onPause()"
if (mPaused) return;
boolean recordLocation = RecordLocationPreference.get(
mPreferences, mContentResolver);
mLocationManager.recordLocation(recordLocation);
setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE);
sFreezeFrameControl.proxySharedPreferenceChanged(); //SPRD:Add for freeze_display
mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup, mPreferences);
mUI.updateControlsTop(mPreferenceGroup, mParameters);
ListPreference prefStorage =
mPreferenceGroup.findPreference(CameraSettings.KEY_CAMERA_STORAGE_PATH);
StorageUtil utilStorage = StorageUtil.newInstance();
String patch = utilStorage.getStoragePath(mActivity, CameraUtil.MODE_CAMERA);
if(patch != null){
prefStorage.setStorageValue(patch);
}
}
@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() {
mInitialParams = mCameraDevice.getParameters();
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;
if (mUI != null && isContinueTakePicture()) {
mUI.enableBurstScreenHint(true);
}
mFocusManager.doSnap();
mFocusManager.onShutterUp();
// SPRD: HDR screen hint supported
if (mUI != null) {
mUI.enableHdrScreenHint(true, mPreferences);
}
}
@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
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);
if (full && sFreezeFrameControl != null
&& sFreezeFrameControl.isFreezeFrame()) {
Uri uri = null;
sFreezeFrameControl.proxyRunLoadProxy(uri);
}
if (mIsTakingPicture &&
mActivity.getStorageSpaceBytes() <= Storage.LOW_STORAGE_THRESHOLD_BYTES) {
Log.i(TAG, "Not enough space or storage not ready. remaining="
+ mActivity.getStorageSpaceBytes());
updateCameraControls();
mIsTakingPicture = false;
}
}
@Override
public void onQueueEmpty() {
if (mContinuousCaptureCount > 0) {
return;
}
if (isContinueTakePicture()) {
updateCameraControls();
mIsTakingPicture = false;
}
}
@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);
}
@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);
}
}
}
/* Below is no longer needed, except to get rid of compile error
* TODO: Remove these
*/
// TODO: Delete this function after old camera code is removed
/* SPRD:Add for restore @{ */
@Override
public void onRestorePreferencesClicked(AlertDialogPopup popup) {
if (mPaused) return;
Runnable runnableOk = new Runnable() {
@Override
public void run() {
restorePreferences();
}
};
Runnable runnableCancel = new Runnable() {
@Override
public void run() {
mUI.dismissPopup(true);
}
};
popup.setAlertDialog(
mActivity.getString(R.string.pref_restore_detail),
mActivity.getString(R.string.confirm_restore_message),
mActivity.getString(R.string.dialog_ok), runnableOk,
mActivity.getString(R.string.dialog_cancel), runnableCancel);
mUI.showPopup(popup);
}
/* @} */
/* SPRD:Add for restore @{ */
private void restorePreferences() {
// Reset the zoom. Zoom value is not stored in preference.
mZoomValue = 0;
setCameraParametersWhenIdle(UPDATE_PARAM_ZOOM);
mUI.initializeZoom(mParameters);
if (mUI != null) {
mUI.dismissPopup(false);
Context context = mActivity;
StoragePathPreference pathPreference = StoragePathPreference.getInstance(mActivity);
pathPreference.clear();
CameraSettings.restorePreferences(context, mPreferences, mParameters);
mUI.reloadPreferences();
onSharedPreferenceChanged();
}
StorageUtil utilStorage = StorageUtil.newInstance();
utilStorage.syncThumbnailPath();
mActivity.updateStorageSpaceAndHint();
}
/* @} */
/**
* SPRD:initialize CustomController, HDR,ZSL etc. @{
*/
private void initializeCustomController() {
mZSLController = new ZSLController(mPreferences);
}
/** @} */
/* SPRD: porting new feature JPEG quality start @{ */
private JpegQualityController mJpegQualityController;
private class JpegQualityController {
private static final String TAG = "CAM_CameraJpegQualityController";
private static final String VAL_NORMAL = "normal";
private static final String VAL_HIGHT = "hight";
private static final String VAL_SUPER = "super";
private static final int VAL_DEFAULT_QUALITY = 85;
// default construct
/*package*/ JpegQualityController() { }
public int findJpegQuality(String quality) {
int convertQuality = getConvertJpegQuality(quality);
int result = VAL_DEFAULT_QUALITY;
if (VAL_DEFAULT_QUALITY != convertQuality) {
result = CameraProfile.getJpegEncodingQualityParameter(convertQuality);
}
Log.d(TAG, "findJpegQuality result = " + result);
return result;
}
private int getConvertJpegQuality(String quality) {
int result = VAL_DEFAULT_QUALITY;
if (quality != null) {
if (VAL_NORMAL.equals(quality))
result = CameraProfile.QUALITY_LOW;
else if (VAL_HIGHT.equals(quality))
result = CameraProfile.QUALITY_MEDIUM;
else if (VAL_SUPER.equals(VAL_SUPER))
result = CameraProfile.QUALITY_HIGH;
}
Log.d(TAG, "getConvertJpegQuality result = " + result);
return result;
}
}
/* }@ dev new feature jpeg quality end */
// onClick handler for R.id.btn_switch
public void onSwitchButtonClicked() {
// need to do
// SPRD: bug 260858 Disable camera PickerButton when take picture
if (!mEnableCameraSet || !mEnableTopButton || !isCameraIdle() || mUI.isCountingDown())
return;
if (mPreferenceGroup == null)
return;
ListPreference pref =
mPreferenceGroup.findPreference(CameraSettings.KEY_CAMERA_ID);
if (pref != null) {
mUI.enableSwitchCameraButton(false);//add by sprd for bug456
int index = pref.findIndexOfValue(pref.getValue());
CharSequence[] values = pref.getEntryValues();
// SPRD: check "values" is null for monkey
CameraUtil.P(DEBUG, TAG, "onSwitchButtonClicked values=" + Arrays.toString(values) + ", index=" + index);
int valuesLength = 0;
if (values != null && (valuesLength = values.length) > 0) {
index = (index + 1) % valuesLength;
int newCameraId = Integer.parseInt((String) values[index]);
pref.setValue("" + newCameraId);
onCameraPickerClicked(newCameraId);
}
}
}
// onClick handler for R.id.btn_hdr
public void onHdrButtonClicked() {
// SPRD: bug 260858 disable HdrButton when take picture
if(!mEnableCameraSet || !isCameraIdle() || mUI.isCountingDown()) return;
String valueOn = mActivity.getString(R.string.setting_on_value);
String valueOff = mActivity.getString(R.string.setting_off_value);
String hdrValue = mPreferences.getString(CameraSettings.KEY_CAMERA_HDR, valueOff);
// change current HDR state in the preferences
boolean switcherOn = !(valueOn.equals(hdrValue));
String changedValue = (switcherOn ? valueOn : valueOff);
// reset HDR state to preferences
Editor edit = mPreferences.edit();
edit.putString(CameraSettings.KEY_CAMERA_HDR, changedValue);
// if (changedValue.equals(valueOn) && isContinueTakePicture()) {
// edit.putString(CameraSettings.KEY_CAMERA_CONTINUOUS_CAPTURE, "1");
// }
edit.apply();
if (DEBUG) {
String message =
String.format("onHdrButtonClicked before=%s, after=%s",
new Object[] { hdrValue, changedValue });
CameraUtil.P(DEBUG, TAG, message);
}
setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE);
mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup, mPreferences);
mUI.updateControlsTop(mPreferenceGroup, mParameters);
}
// onClick handler for R.id.btn_flash
public void onFlashButtonClicked() {
// SPRD: bug 260858 Disable FlashButton when take picture
if(!mEnableTopButton || isHdrOn() || !isCameraIdle() ||
mUI.isCountingDown() || mZSLController.switchOn()) return;
setFlashMode();
if (mParameters != null && mPreferenceGroup != null && mPreferences != null) {
mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup, mPreferences);
mUI.updateControlsTop(mPreferenceGroup, mParameters);
}
}
private void setFlashMode() {
if (mPreferenceGroup == null) return;
if (mCameraDevice == null) {
Log.e(TAG, "The Camera is not initialized :" + mCameraId + ", aborting.");
return;
}
ListPreference pref = mPreferenceGroup.findPreference(
CameraSettings.KEY_FLASH_MODE);
if (pref != null) {
int index = pref.findIndexOfValue(pref.getValue());
CharSequence[] values = pref.getEntryValues();
index = (index + 1) % values.length;
pref.setValue("" + values[index]);
}
if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) {
// Set flash mode.
String flashMode =
mPreferences.getString(
CameraSettings.KEY_FLASH_MODE,
mActivity.getString(R.string.pref_camera_flashmode_default));
// if HDR switch is on, so we must reset flash to off
// because camera device is unsupported HDR and flash both on
// if (mHDRController != null && mHDRController.switchOn()) {
// flashMode =
// mActivity.getString(R.string.pref_camera_flashmode_default);
// // if scene mode is burst and flash is on, so we must override
// flash setting
// } else if(mBurstController != null &&
// mBurstController.switchOn()) {
// flashMode =
// mActivity.getString(R.string.pref_camera_flashmode_default);
// }
List<String> supportedFlash = mParameters.getSupportedFlashModes();
if (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.
String whiteBalance =
mPreferences.getString(
CameraSettings.KEY_WHITE_BALANCE,
mActivity.getString(R.string.pref_camera_whitebalance_default));
if (isSupported(whiteBalance, mParameters.getSupportedWhiteBalance())) {
mParameters.setWhiteBalance(whiteBalance);
} else {
whiteBalance = mParameters.getWhiteBalance();
if (whiteBalance == null) {
whiteBalance = Parameters.WHITE_BALANCE_AUTO;
}
}
} else {
mParameters.setFlashMode(Parameters.FLASH_MODE_OFF);
mParameters.setWhiteBalance(Parameters.WHITE_BALANCE_AUTO);
}
mCameraDevice.setParameters(mParameters);
}
private static boolean isSupported(String value, List<String> supported) {
return supported == null ? false : supported.indexOf(value) >= 0;
}
public void updateThumbnail(Bitmap bitmap){
if(mIsImageCaptureIntent)
bitmap = null;
mUI.updateThumbnail(bitmap,mEnableCameraSet);
}
public void onCameraSettingClicked() {
if(!mEnableCameraSet) return;
mUI.onCameraSettingClicked();
}
public void onVideoCaptureShutterButtonClick() {
}
/* SPRD: dev multi-focus feature start @{ */
public void onMultiTapUp(View view, List<Tuple<Integer, Integer>> pointers) {
if (mPaused || mCameraDevice == null || !mFirstTimeInitialized
|| mCameraState == SNAPSHOT_IN_PROGRESS
|| mCameraState == SWITCHING_CAMERA
|| mCameraState == PREVIEW_STOPPED
|| sFreezeFrameControl.mFreezeVisible) {
return;
}
// Check if metering area or focus area is supported.
if (!mFocusAreaSupported && !mMeteringAreaSupported) return;
mFocusManager.onMultiTapUp(pointers);
}
/* dev multi-focus feature end @} */
/* SPRD: click 1st level popup title to dismiss start @{ */
public void onSettingTitleClicked(View v) {
mUI.onSettingTitleClicked(v);
}
/* click 1st level popup title to dismiss end @} */
public void onPauseClicked() {
// nothing to do
}
public void onStopClicked() {
// nothing to do
}
/* SPRD:Add for freeze_display @{ */
public FreezeFrameDisplayControl sFreezeFrameControl;
private class FreezeFrameDisplayControl implements FreezeFrameDisplayView.ProxyFreezeFrameClick,Rotatable {
private static final String TAG = "CAM_CameraFreezeFrameDisplayControl";
private boolean sBurstSwitch;
private boolean sFreezSwitch;
private boolean mFreezeVisible;
// SPRD: Save uri for Frezzeframe display
private Uri mUri;
// freeze-frame display view
private FreezeFrameDisplayView sView;
// default construct, initialize properties
private FreezeFrameDisplayControl() {
sBurstSwitch = isContinueTakePicture();
sFreezSwitch = getBooleanByPreferenceKey(CameraSettings.KEY_FREEZE_FRAME_DISPLAY);
}
private void initialize() {
FrameLayout layoutRoot =
(FrameLayout)mActivity.findViewById(R.id.camera_layout_root);
if (sView != null) {
layoutRoot.removeView(sView);
}
LayoutInflater inflater = mActivity.getLayoutInflater();
sView = (FreezeFrameDisplayView)
inflater.inflate(R.layout.preview_camera_freeze_frame_display, null);
layoutRoot.addView(sView);
sView.setListener(this);
sView.proxySetRotateDialogController(mRotateDialog);
}
// Runs in main thread
/*package*/ boolean proxyDoNotTake() {
/*
* validate condition following:
* 1、default by sView visibility state, if current state is visible, so anyway(camera key or soft key) can't take picture
* 2、rejection soft key double click event and camera key quick click event
*/
return (proxyDisplay()/* || (sFreezSwitch && (mCameraState != IDLE))*/);
}
/*package*/ boolean isFreezeFrame() {
// SPRD: FixBug 269986,To obtain the values "FreezeDisplay".
sFreezSwitch = getBooleanByPreferenceKey(CameraSettings.KEY_FREEZE_FRAME_DISPLAY);
return (sFreezSwitch && !sBurstSwitch);
}
// Runs in main thread
/*package*/ void proxyAnimation(boolean show) {
initialize();
if (show) {
sView.proxyFadeIn(mIsImageCaptureIntent, mFreezeVisible);
// we need reset FreezeFrameDisplayView orientation
/* @{ SPRD: fix bug 255774 start */
//sView.setOrientation(mOrientation, true);
//sView.setOrientation(mOrientationCompensation, true);
updateRotation(mDisplayOrientation);
/* fix bug 255774 end @}*/
// mCameraAppView.setVisibility(View.GONE);
mFreezeVisible = true;
mUI.hideUI();
mUI.hideControlTopButton();
// SPRD: bug 262968 Hide module switch view when FreezeFrame Display
} else {
mUI.showUI();
mUI.showControlTopButton();
mUI.updateControlsTop(mPreferenceGroup, mParameters);
sView.proxyFadeOut();
// mCameraAppView.setVisibility(View.VISIBLE);
mFreezeVisible = false;
updateCameraAppView();
// SPRD: bug 262968 show module switch view when FreezeFrame unDisplay
}
}
/*package*/ boolean proxyDisplay() {
if (sView != null) {
return sView.displayed();
}
return false;
}
/*package*/ void proxyRunLoadProxy(Uri uri) {
mUri = uri;
mActivity.setSwipingEnabled(false);
if (sView == null) {
initialize();
}
sView.runLoadResource(uri);
}
/* @{ SPRD: bug 251198 start */
/*package*/ void proxyRunLoadProxy(byte [] jpagByte) {
initialize();
mActivity.setSwipingEnabled(false);
sView.runLoadResource(jpagByte,mActivity.isAutoCapture());
}
/* bug 251198 end @} */
/*package*/ void proxySharedPreferenceChanged() {
/* Bug 268614 Burst and Freez Mutex @{ */
if(isHdrOn()){
return;
}
boolean bBurst = isContinueTakePicture();
boolean bFreez = getBooleanByPreferenceKey(CameraSettings.KEY_FREEZE_FRAME_DISPLAY);
Log.d(TAG, "proxySharedPreferenceChanged() before changed: Burst old = " + sBurstSwitch + ", new = "+
bBurst+",Freeze old = "+sFreezSwitch+", new = "+bFreez);
boolean changed = false;
if (bFreez == bBurst && !bFreez) {
// if "val_freez" value is "false" and "val_freez" & "val_burst" value is
// similar, we need validation previous burst and freeze value, if changed
// we must call "mIndicatorControlContainer.reloadPreference()" method
if (sBurstSwitch != bBurst || sFreezSwitch != bFreez) {
sBurstSwitch = changed;
sFreezSwitch = changed;
changed = true;
}
} else if (sBurstSwitch != bBurst) {
sBurstSwitch = bBurst;
sFreezSwitch = !bBurst;
changed = true;
} else if (sFreezSwitch != bFreez) {
sFreezSwitch = bFreez;
sBurstSwitch = !bFreez;
changed = true;
}
Log.d(TAG, "proxySharedPreferenceChanged() is changed? "+changed);
if (changed) {
Log.d(TAG, "proxySharedPreferenceChanged() after changed: Burst old = " + sBurstSwitch + ", new = "+
bBurst+",Freeze old = "+sFreezSwitch+", new = "+bFreez);
Editor editor = mPreferences.edit();
String valueBurst;
if (!sBurstSwitch) {
valueBurst = String.valueOf(VAL_DEFAULT_CAPTURE_COUNT);
editor.putString( CameraSettings.KEY_CAMERA_CONTINUOUS_CAPTURE, valueBurst);
} else {
valueBurst = String.valueOf(getContinuousCount());
editor.putString( CameraSettings.KEY_CAMERA_CONTINUOUS_CAPTURE, valueBurst);
}
mParameters.set(CameraSettings.KEY_CAPTURE_MODE, valueBurst);
String valueFreez = getStringBySwitchValue(sFreezSwitch);
editor.putString(CameraSettings.KEY_FREEZE_FRAME_DISPLAY, valueFreez);
editor.apply();
Log.d(TAG, "proxySharedPreferenceChanged() after editor valueBurst = " + valueBurst + ",valueFreez = " + valueFreez);
mCameraDevice.setParameters(mParameters);
mUI.overrideSettings( CameraSettings.KEY_CAMERA_CONTINUOUS_CAPTURE, valueBurst);
mUI.overrideSettings( CameraSettings.KEY_CAMERA_CONTINUOUS_CAPTURE, null);
mUI.overrideSettings(CameraSettings.KEY_FREEZE_FRAME_DISPLAY, valueFreez);
mUI.overrideSettings(CameraSettings.KEY_FREEZE_FRAME_DISPLAY, null);
}
/* @{ */
}
private boolean getBooleanByPreferenceKey(String key) {
String val = mPreferences.getString(key, CameraSettings.VALUE_OFF);
return (CameraSettings.VALUE_ON.equals(val));
}
private String getStringBySwitchValue(boolean value) {
return (value ? CameraSettings.VALUE_ON : CameraSettings.VALUE_OFF);
}
private void proxyRestartCamera() {
if (!mIsImageCaptureIntent /*&& (mCameraStartUpThread == null)*/) {
startPreview();
setCameraState(IDLE);
startFaceDetection();
}
}
@Override
public void proxyRestartViews() {
/* @{ SPRD: bug 251198 start */
if (mIsImageCaptureIntent) {
onCaptureCancelled();
return;
}
/* bug 251198 end @} */
mActivity.setSwipingEnabled(true);
proxyRestartCamera();
proxyAnimation(false);
}
@Override
public void proxyDoneClicked() {
/* @{ SPRD: bug 251198 start */
if(mIsImageCaptureIntent) {
onCaptureDone();
return;
}
// SPRD: NotifyNewMedia when select save the freeze display picture
Log.d(TAG,"proxyDoneClicked, mUri = "+mUri);
if(mUri != null)
mActivity.notifyNewMedia(mUri);
/* bug 251198 end @} */
proxyRestartViews();
}
@Override
public void proxyFinishDeleted(boolean deleted) {
Log.d(TAG, "main thread delete picture result = " + deleted);
// update thumbnail
if (deleted && !mIsImageCaptureIntent) {
mActivity.updateThumbail();
mUI.setPreviewThumbVisibility(View.VISIBLE);
}
}
/* @{ SPRD: bug 251198 start */
@Override
public void proxyRetakeClicked() {
// TODO Auto-generated method stub
if(mIsImageCaptureIntent) {
mJpegImageData = null;
proxyRestartCamera();
proxyAnimation(false);
if (mPaused) return;
mUI.hidePostCaptureAlert();
startPreview();
setCameraState(IDLE);
startFaceDetection();
return;
}
else return;
}
/* bug 251198 end @} */
public void setOrientation(int orientation, boolean animation) {
if (sView != null && proxyDisplay()) {
}
}
// @{ SPRD: Update the view for freezeframe display begin
public void updateFreezeUi() {
if(mFreezeVisible) {
// initialize();
proxyAnimation(true);
if(mUri != null) {
proxyRunLoadProxy(mUri);
}
}
} // SPRD: Update the view for freezeframe display end @}
// @{ SPRD: Change the rotation of views for freezeframe begin
public void updateRotation(int rotation) {
if(sView == null) return;
switch (rotation) {
case 180:
sView.setRotationY(180);
break;
case 270:
sView.setRotationX(180);
break;
default:
;
}
sView.updateFreezeChildUi(rotation);
} // SPRD: Change the rotation of views for freezeframe end @}
}
/* @} */
public void showSwitcher() {
if(!mIsImageCaptureIntent)
mUI.showSwitcher();
}
public void hideSwitcher() {
mUI.hideSwitcher();
}
/** SPRD: get hdr state methods @{ */
public boolean isHdrOn() {
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));
return onValue.equals(hdr);
}
public boolean isHdrPlusOn() {
String onValue = mActivity.getString(R.string.setting_on_value);
String hdrPlus = mPreferences.getString(CameraSettings.KEY_CAMERA_HDR_PLUS,
mActivity.getString(R.string.pref_camera_hdr_plus_default));
return onValue.equals(hdrPlus);
}
/** @} */
/** SPRD: Get the numbers when capture. */
private int getContinuousCount() {
String valueOff = mActivity.getString(R.string.setting_off_value);
String hdrValue = mPreferences.getString(CameraSettings.KEY_CAMERA_HDR, valueOff);
if (!valueOff.equals(hdrValue)) {
mContinueTakePictureCount = 1;
} else {
String sValue = mPreferences.getString(CameraSettings.KEY_CAMERA_CONTINUOUS_CAPTURE,
String.valueOf(VAL_DEFAULT_CAPTURE_COUNT));
mContinueTakePictureCount = (mIsImageCaptureIntent ? VAL_DEFAULT_CAPTURE_COUNT
: Integer.valueOf(sValue));
}
Log.d(TAG, "getContinuousCount=" + mContinueTakePictureCount);
return mContinueTakePictureCount;
}
private boolean isContinueTakePicture() {
if (getContinuousCount() > 1) {
return true;
}
return false;
}
@Override
public void hideControls() {
mUI.hideControlsUI();
}
@Override
public void showControls() {
mUI.showControlsUI();
}
@Override
public boolean isFreezeFrameDisplay() {
if (sFreezeFrameControl != null) {
return sFreezeFrameControl.proxyDisplay();
}
return false ;
}
private void updateCameraControls(){
if (mUI == null) {
return;
}
// SPRD: bug 260858
mEnableTopButton = true;
mEnableCameraSet = true;
mUI.enableShutter(true);
mUI.enableBurstScreenHint(false);
showControls();
if (!isFreezeFrameDisplay()) {
// SPRD: bug 273960
showSwitcher();
mUI.showControlTopButton();
mUI.updateControlsTop(mPreferenceGroup, mParameters);
}
}
}