Merge "Fix effects orientation handling." into ics-mr0
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 589a5c8..70f70c8 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -124,7 +124,6 @@
private boolean mMeteringAreaSupported;
private boolean mAeLockSupported;
private boolean mAwbLockSupported;
- private boolean mAeAwbLock;
private MyOrientationEventListener mOrientationListener;
// The degrees of the device rotated clockwise from its natural orientation.
@@ -385,6 +384,7 @@
Util.initializeScreenBrightness(getWindow(), getContentResolver());
installIntentFilter();
initializeZoom();
+ startFaceDetection();
// Show the tap to focus toast if this is the first start.
if (mFocusAreaSupported &&
mPreferences.getBoolean(CameraSettings.KEY_TAP_TO_FOCUS_PROMPT_SHOWN, true)) {
@@ -700,6 +700,7 @@
enableCameraControls(true);
startPreview();
+ startFaceDetection();
}
if (!mIsImageCaptureIntent) {
@@ -1258,6 +1259,7 @@
public void onReviewRetakeClicked(View v) {
hidePostCaptureAlert();
startPreview();
+ startFaceDetection();
}
@OnClickAttr
@@ -1358,18 +1360,10 @@
// Do not do focus if there is not enough storage.
if (pressed && !canTakePicture()) return;
- // Lock AE and AWB so users can half-press shutter and recompose.
- mAeAwbLock = pressed;
- if (mAeAwbLock && (mAeLockSupported || mAwbLockSupported)) {
- setCameraParameters(UPDATE_PARAM_PREFERENCE);
- }
-
- mFocusManager.doFocus(pressed);
-
- // Unlock AE and AWB after cancelAutoFocus. Camera API does not
- // guarantee setParameters can be called during autofocus.
- if (!mAeAwbLock && (mAeLockSupported || mAwbLockSupported)) {
- setCameraParameters(UPDATE_PARAM_PREFERENCE);
+ if (pressed) {
+ mFocusManager.onShutterDown();
+ } else {
+ mFocusManager.onShutterUp();
}
}
@@ -1462,6 +1456,7 @@
initializeCapabilities();
resetExposureCompensation();
startPreview();
+ startFaceDetection();
} catch (CameraHardwareException e) {
Util.showErrorAndFinish(this, R.string.cannot_connect_camera);
return;
@@ -1503,8 +1498,10 @@
if (mFirstTimeInitialized) {
mOrientationListener.disable();
- mImageSaver.finish();
- mImageSaver = null;
+ if (mImageSaver != null) {
+ mImageSaver.finish();
+ mImageSaver = null;
+ }
if (!mIsImageCaptureIntent && mThumbnail != null && !mThumbnail.fromFile()) {
mThumbnail.saveTo(new File(getFilesDir(), Thumbnail.LAST_THUMB_FILENAME));
}
@@ -1683,6 +1680,7 @@
// display rotation in onCreate may not be what we want.
if (mCameraState == PREVIEW_STOPPED) {
startPreview();
+ startFaceDetection();
} else {
if (Util.getDisplayRotation(this) != mDisplayRotation) {
setDisplayOrientation();
@@ -1756,7 +1754,8 @@
setPreviewDisplay(mSurfaceHolder);
setDisplayOrientation();
- mAeAwbLock = false; // Unlock AE and AWB.
+
+ mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
setCameraParameters(UPDATE_PARAM_ALL);
// If the focus mode is continuous autofocus, call cancelAutoFocus to
// resume it because it may have been paused by autoFocus call.
@@ -1779,7 +1778,6 @@
throw new RuntimeException("startPreview failed", ex);
}
- startFaceDetection();
mZoomState = ZOOM_STOPPED;
mCameraState = IDLE;
mFocusManager.onPreviewStarted();
@@ -1831,11 +1829,11 @@
private void updateCameraParametersPreference() {
if (mAeLockSupported) {
- mParameters.setAutoExposureLock(mAeAwbLock);
+ mParameters.setAutoExposureLock(mFocusManager.getAeAwbLock());
}
if (mAwbLockSupported) {
- mParameters.setAutoWhiteBalanceLock(mAeAwbLock);
+ mParameters.setAutoWhiteBalanceLock(mFocusManager.getAeAwbLock());
}
if (mFocusAreaSupported) {
diff --git a/src/com/android/camera/EffectsRecorder.java b/src/com/android/camera/EffectsRecorder.java
index ed44a79..7c81bf0 100644
--- a/src/com/android/camera/EffectsRecorder.java
+++ b/src/com/android/camera/EffectsRecorder.java
@@ -91,6 +91,7 @@
private FileDescriptor mFd;
private int mOrientationHint = 0;
private long mMaxFileSize = 0;
+ private int mMaxDurationMs = 0;
private int mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
private int mEffect = EFFECT_NONE;
@@ -234,6 +235,23 @@
mMaxFileSize = maxFileSize;
}
+ /**
+ * Sets the maximum recording duration (in ms) for the next recording session
+ * Setting it to zero (the default) disables the limit.
+ */
+ public synchronized void setMaxDuration(int maxDurationMs) {
+ switch (mState) {
+ case STATE_RECORD:
+ throw new RuntimeException("setMaxDuration cannot be called while recording!");
+ case STATE_RELEASED:
+ throw new RuntimeException("setMaxDuration called on an already released recorder!");
+ default:
+ break;
+ }
+ mMaxDurationMs = maxDurationMs;
+ }
+
+
public void setCaptureRate(double fps) {
switch (mState) {
case STATE_RECORD:
@@ -638,6 +656,7 @@
recorder.setInputValue("errorListener", mErrorListener);
}
recorder.setInputValue("maxFileSize", mMaxFileSize);
+ recorder.setInputValue("maxDurationMs", mMaxDurationMs);
recorder.setInputValue("recording", true);
if (mRecordSound != null) mRecordSound.play();
mState = STATE_RECORD;
diff --git a/src/com/android/camera/FocusManager.java b/src/com/android/camera/FocusManager.java
index 6b9dbd6..228e2d1 100644
--- a/src/com/android/camera/FocusManager.java
+++ b/src/com/android/camera/FocusManager.java
@@ -55,6 +55,8 @@
private boolean mInitialized;
private boolean mFocusAreaSupported;
private boolean mInLongPress;
+ private boolean mLockAeAwbNeeded;
+ private boolean mAeAwbLock;
private SoundPlayer mSoundPlayer;
private View mFocusIndicatorRotateLayout;
private FocusIndicatorView mFocusIndicator;
@@ -104,6 +106,8 @@
mFocusAreaSupported = (mParameters.getMaxNumFocusAreas() > 0
&& isSupported(Parameters.FOCUS_MODE_AUTO,
mParameters.getSupportedFocusModes()));
+ mLockAeAwbNeeded = (mParameters.isAutoExposureLockSupported() ||
+ mParameters.isAutoWhiteBalanceLockSupported());
}
public void initialize(View focusIndicatorRotate, View previewFrame,
@@ -121,27 +125,42 @@
}
}
- public void doFocus(boolean pressed) {
+ public void onShutterDown() {
if (!mInitialized) return;
- if (!(getFocusMode().equals(Parameters.FOCUS_MODE_INFINITY)
- || getFocusMode().equals(Parameters.FOCUS_MODE_FIXED)
- || getFocusMode().equals(Parameters.FOCUS_MODE_EDOF))) {
- if (pressed) { // Focus key down.
- // Do not focus if touch focus has been triggered.
- if (mState != STATE_SUCCESS && mState != STATE_FAIL) {
- autoFocus();
- }
- } else { // Focus key up.
- // User releases half-pressed focus key.
- if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
- || mState == STATE_FAIL) {
- cancelAutoFocus();
- }
+ // Lock AE and AWB so users can half-press shutter and recompose.
+ if (mLockAeAwbNeeded && !mAeAwbLock) {
+ mAeAwbLock = true;
+ mListener.setFocusParameters();
+ }
+
+ if (needAutoFocusCall()) {
+ // Do not focus if touch focus has been triggered.
+ if (mState != STATE_SUCCESS && mState != STATE_FAIL) {
+ autoFocus();
}
}
}
+ public void onShutterUp() {
+ if (!mInitialized) return;
+
+ if (needAutoFocusCall()) {
+ // User releases half-pressed focus key.
+ if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
+ || mState == STATE_FAIL) {
+ cancelAutoFocus();
+ }
+ }
+
+ // Unlock AE and AWB after cancelAutoFocus. Camera API does not
+ // guarantee setParameters can be called during autofocus.
+ if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
+ mAeAwbLock = false;
+ mListener.setFocusParameters();
+ }
+ }
+
public void shutterLongPressed() {
if (Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)
&& isSupported(Parameters.FOCUS_MODE_AUTO, mParameters.getSupportedFocusModes())) {
@@ -151,9 +170,9 @@
mInLongPress = true;
// Cancel any outstanding Auto focus requests. The auto focus mode
// will be changed from CAF to auto in cancelAutoFocus.
- doFocus(false);
+ onShutterUp();
// Call Autofocus
- doFocus(true);
+ onShutterDown();
mInLongPress = false;
}
}
@@ -164,11 +183,7 @@
// If the user has half-pressed the shutter and focus is completed, we
// can take the photo right away. If the focus mode is infinity, we can
// also take the photo.
- if (getFocusMode().equals(Parameters.FOCUS_MODE_INFINITY)
- || getFocusMode().equals(Parameters.FOCUS_MODE_FIXED)
- || getFocusMode().equals(Parameters.FOCUS_MODE_EDOF)
- || (mState == STATE_SUCCESS
- || mState == STATE_FAIL)) {
+ if (!needAutoFocusCall() || (mState == STATE_SUCCESS || mState == STATE_FAIL)) {
capture();
} else if (mState == STATE_FOCUSING) {
// Half pressing the shutter (i.e. the focus button event) will
@@ -467,7 +482,22 @@
mOverrideFocusMode = focusMode;
}
+ public void setAeAwbLock(boolean lock) {
+ mAeAwbLock = lock;
+ }
+
+ public boolean getAeAwbLock() {
+ return mAeAwbLock;
+ }
+
private static boolean isSupported(String value, List<String> supported) {
return supported == null ? false : supported.indexOf(value) >= 0;
}
+
+ private boolean needAutoFocusCall() {
+ String focusMode = getFocusMode();
+ return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY)
+ || focusMode.equals(Parameters.FOCUS_MODE_FIXED)
+ || focusMode.equals(Parameters.FOCUS_MODE_EDOF));
+ }
}
diff --git a/src/com/android/camera/MenuHelper.java b/src/com/android/camera/MenuHelper.java
index 2e1ec28..07caeb2 100644
--- a/src/com/android/camera/MenuHelper.java
+++ b/src/com/android/camera/MenuHelper.java
@@ -138,8 +138,9 @@
startCameraActivity(activity, new Intent(action), className);
}
- public static void gotoVideoMode(Activity activity) {
+ public static void gotoVideoMode(Activity activity, boolean resetEffect) {
Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
+ intent.putExtra(VideoCamera.RESET_EFFECT_EXTRA, resetEffect);
startCameraActivity(activity, intent, VIDEO_CAMERA_CLASS);
}
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index 8ac25e6..4694c90 100755
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -183,6 +183,9 @@
private int mEffectType = EffectsRecorder.EFFECT_NONE;
private Object mEffectParameter = null;
private String mEffectUriFromGallery = null;
+ private String mPrefVideoEffectDefault;
+ private boolean mResetEffect = true;
+ public static final String RESET_EFFECT_EXTRA = "reset_effect";
private boolean mMediaRecorderRecording = false;
private long mRecordingStartTime;
@@ -353,6 +356,11 @@
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
mNumberOfCameras = CameraHolder.instance().getNumberOfCameras();
+ mPrefVideoEffectDefault = getString(R.string.pref_video_effect_default);
+ // Do not reset the effect if users are switching between back and front
+ // cameras.
+ mResetEffect = getIntent().getBooleanExtra(RESET_EFFECT_EXTRA, true);
+ resetEffect();
/*
* To reduce startup time, we start the preview in another thread.
@@ -556,7 +564,8 @@
}
private void startPlayVideoActivity() {
- Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri);
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(mCurrentVideoUri, convertOutputFormatToMimeType(mProfile.fileFormat));
try {
startActivity(intent);
} catch (ActivityNotFoundException ex) {
@@ -704,33 +713,17 @@
mEffectType = CameraSettings.readEffectType(mPreferences);
if (mEffectType != EffectsRecorder.EFFECT_NONE) {
mEffectParameter = CameraSettings.readEffectParameter(mPreferences);
- // When picking from gallery, mEffectParameter should have been
- // initialized in onActivityResult. If not, fall back to no effect
- if (mEffectType == EffectsRecorder.EFFECT_BACKDROPPER
- && ((String) mEffectParameter).equals(EFFECT_BG_FROM_GALLERY)
- && mEffectUriFromGallery == null) {
- Log.w(TAG, "No URI from gallery, resetting to no effect");
- mEffectType = EffectsRecorder.EFFECT_NONE;
- mEffectParameter = null;
- writeDefaultEffectToPrefs();
- if (mIndicatorControlContainer != null) {
- mIndicatorControlContainer.overrideSettings(
+ // Set quality to 480p for effects, unless intent is overriding it
+ if (!intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) {
+ quality = CamcorderProfile.QUALITY_480P;
+ }
+ // On initial startup, can get here before indicator control is
+ // enabled. In that case, UI quality override handled in
+ // initializeIndicatorControl.
+ if (mIndicatorControlContainer != null) {
+ mIndicatorControlContainer.overrideSettings(
CameraSettings.KEY_VIDEO_QUALITY,
- null);
- }
- } else {
- // Set quality to 480p for effects, unless intent is overriding it
- if (!intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) {
- quality = CamcorderProfile.QUALITY_480P;
- }
- // On initial startup, can get here before indicator control is
- // enabled. In that case, UI quality override handled in
- // initializeIndicatorControl.
- if (mIndicatorControlContainer != null) {
- mIndicatorControlContainer.overrideSettings(
- CameraSettings.KEY_VIDEO_QUALITY,
- Integer.toString(CamcorderProfile.QUALITY_480P));
- }
+ Integer.toString(CamcorderProfile.QUALITY_480P));
}
} else {
mEffectParameter = null;
@@ -804,6 +797,10 @@
// some time to get first orientation.
mOrientationListener.enable();
if (!mPreviewing) {
+ if (resetEffect()) {
+ mBgLearningMessageFrame.setVisibility(View.GONE);
+ mIndicatorControlContainer.reloadPreferences();
+ }
try {
mCameraDevice = Util.openCamera(this, mCameraId);
readVideoPreferences();
@@ -1319,6 +1316,7 @@
maxFileSize = requestedSizeLimit;
}
mEffectsRecorder.setMaxFileSize(maxFileSize);
+ mEffectsRecorder.setMaxDuration(mMaxVideoDurationInMs);
}
@@ -1354,12 +1352,9 @@
private void generateVideoFilename(int outputFileFormat) {
long dateTaken = System.currentTimeMillis();
String title = createName(dateTaken);
- String filename = title + ".3gp"; // Used when emailing.
- String mime = "video/3gpp";
- if (outputFileFormat == MediaRecorder.OutputFormat.MPEG_4) {
- filename = title + ".mp4";
- mime = "video/mp4";
- }
+ // Used when emailing.
+ String filename = title + convertOutputFormatToFileExt(outputFileFormat);
+ String mime = convertOutputFormatToMimeType(outputFileFormat);
mVideoFilename = Storage.DIRECTORY + '/' + filename;
mCurrentVideoValues = new ContentValues(7);
mCurrentVideoValues.put(Video.Media.TITLE, title);
@@ -1933,6 +1928,11 @@
// seen by startPreview from onResume()
mEffectUriFromGallery = ((Uri) data.getData()).toString();
Log.v(TAG, "Received URI from gallery: " + mEffectUriFromGallery);
+ mResetEffect = false;
+ } else {
+ mEffectUriFromGallery = null;
+ Log.w(TAG, "No URI from gallery");
+ mResetEffect = true;
}
break;
default:
@@ -2053,9 +2053,11 @@
// animation.
if (mIsVideoCaptureIntent) {
// If the intent is video capture, stay in video capture mode.
- MenuHelper.gotoVideoMode(this, getIntent());
+ Intent intent = getIntent();
+ intent.putExtra(RESET_EFFECT_EXTRA, false);
+ MenuHelper.gotoVideoMode(this, intent);
} else {
- MenuHelper.gotoVideoMode(this);
+ MenuHelper.gotoVideoMode(this, false);
}
finish();
} else {
@@ -2346,4 +2348,31 @@
Util.broadcastNewPicture(this, uri);
}
}
+
+ private boolean resetEffect() {
+ if (mResetEffect) {
+ String value = mPreferences.getString(CameraSettings.KEY_VIDEO_EFFECT,
+ mPrefVideoEffectDefault);
+ if (!mPrefVideoEffectDefault.equals(value)) {
+ writeDefaultEffectToPrefs();
+ return true;
+ }
+ }
+ mResetEffect = true;
+ return false;
+ }
+
+ private String convertOutputFormatToMimeType(int outputFileFormat) {
+ if (outputFileFormat == MediaRecorder.OutputFormat.MPEG_4) {
+ return "video/mp4";
+ }
+ return "video/3gpp";
+ }
+
+ private String convertOutputFormatToFileExt(int outputFileFormat) {
+ if (outputFileFormat == MediaRecorder.OutputFormat.MPEG_4) {
+ return ".mp4";
+ }
+ return ".3gp";
+ }
}