Merge "bugfix 5370554 camcorder preview background is inconsistent"
diff --git a/res/raw/backdropper.graph b/res/raw/backdropper.graph
index e3fe877..25c86e6 100644
--- a/res/raw/backdropper.graph
+++ b/res/raw/backdropper.graph
@@ -35,6 +35,8 @@
@external previewWidth;
@external previewHeight;
+@external orientation;
+
@external learningDoneListener;
// Filters ---------------------------------------------------
@@ -52,6 +54,7 @@
sourceUrl = "no_file_specified";
waitForNewFrame = false;
sourceIsUrl = true;
+ orientation = $orientation;
}
// Background replacer
diff --git a/res/raw/goofy_face.graph b/res/raw/goofy_face.graph
index e346322..430c811 100644
--- a/res/raw/goofy_face.graph
+++ b/res/raw/goofy_face.graph
@@ -37,6 +37,10 @@
@external previewWidth;
@external previewHeight;
+// Not used by this graph, but simplifies higher-level
+// graph initialization code.
+@external orientation;
+
// Filters ---------------------------------------------------
// Camera input
diff --git a/res/xml/video_preferences.xml b/res/xml/video_preferences.xml
index 700c843..e158139 100644
--- a/res/xml/video_preferences.xml
+++ b/res/xml/video_preferences.xml
@@ -62,4 +62,12 @@
camera:largeIcons="@array/video_effect_icons"
camera:entries="@array/pref_video_effect_entries"
camera:entryValues="@array/pref_video_effect_entryvalues" />
+ <RecordLocationPreference
+ camera:key="pref_camera_recordlocation_key"
+ camera:defaultValue="@string/pref_camera_recordlocation_default"
+ camera:title="@string/pref_camera_recordlocation_title"
+ camera:icons="@array/camera_recordlocation_icons"
+ camera:largeIcons="@array/camera_recordlocation_largeicons"
+ camera:entries="@array/pref_camera_recordlocation_entries"
+ camera:entryValues="@array/pref_camera_recordlocation_entryvalues" />
</PreferenceGroup>
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 10f0b80..74a1b37 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -941,12 +941,12 @@
final String[] SETTING_KEYS = {
CameraSettings.KEY_FLASH_MODE,
CameraSettings.KEY_WHITE_BALANCE,
+ CameraSettings.KEY_EXPOSURE,
CameraSettings.KEY_SCENE_MODE};
final String[] OTHER_SETTING_KEYS = {
CameraSettings.KEY_RECORD_LOCATION,
- CameraSettings.KEY_FOCUS_MODE,
- CameraSettings.KEY_EXPOSURE,
- CameraSettings.KEY_PICTURE_SIZE};
+ CameraSettings.KEY_PICTURE_SIZE,
+ CameraSettings.KEY_FOCUS_MODE};
CameraPicker.setImageResourceId(R.drawable.ic_switch_photo_facing_holo_light);
mIndicatorControlContainer.initialize(this, mPreferenceGroup,
diff --git a/src/com/android/camera/EffectsRecorder.java b/src/com/android/camera/EffectsRecorder.java
index 301f2a2..f177387 100644
--- a/src/com/android/camera/EffectsRecorder.java
+++ b/src/com/android/camera/EffectsRecorder.java
@@ -300,7 +300,8 @@
mGraphEnv.addReferences(
"previewSurface", mPreviewSurfaceHolder.getSurface(),
"previewWidth", mPreviewWidth,
- "previewHeight", mPreviewHeight);
+ "previewHeight", mPreviewHeight,
+ "orientation", mOrientationHint);
if (mState == STATE_PREVIEW) {
// Switching effects while running. Inform video camera.
sendMessage(mCurrentEffect, EFFECT_MSG_SWITCHING_EFFECT);
diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java
index c5bc79d..61a55dd 100644
--- a/src/com/android/camera/Util.java
+++ b/src/com/android/camera/Util.java
@@ -115,8 +115,8 @@
public static Bitmap rotateAndMirror(Bitmap b, int degrees, boolean mirror) {
if ((degrees != 0 || mirror) && b != null) {
Matrix m = new Matrix();
- m.setRotate(degrees,
- (float) b.getWidth() / 2, (float) b.getHeight() / 2);
+ // Mirror first.
+ // horizontal flip + rotation = -rotation + horizontal flip
if (mirror) {
m.postScale(-1, 1);
degrees = (degrees + 360) % 360;
@@ -128,6 +128,11 @@
throw new IllegalArgumentException("Invalid degrees=" + degrees);
}
}
+ if (degrees != 0) {
+ // clockwise
+ m.postRotate(degrees,
+ (float) b.getWidth() / 2, (float) b.getHeight() / 2);
+ }
try {
Bitmap b2 = Bitmap.createBitmap(
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index 81ce3a9..b75fbed 100644
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -235,7 +235,8 @@
// 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;
- private int mOrientationHint; // the orientation hint for video playback
+ // The orientation compenstaion when we start recording.
+ private int mOrientationCompensationAtRecordStart;
private static final int ZOOM_STOPPED = 0;
private static final int ZOOM_START = 1;
@@ -465,11 +466,12 @@
final String[] SETTING_KEYS = {
CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE,
- CameraSettings.KEY_VIDEO_EFFECT,
CameraSettings.KEY_WHITE_BALANCE,
+ CameraSettings.KEY_VIDEO_EFFECT,
+ CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL,
CameraSettings.KEY_VIDEO_QUALITY};
final String[] OTHER_SETTING_KEYS = {
- CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL};
+ CameraSettings.KEY_RECORD_LOCATION};
CameraPicker.setImageResourceId(R.drawable.ic_switch_video_facing_holo_light);
mIndicatorControlContainer.initialize(this, mPreferenceGroup,
@@ -511,7 +513,7 @@
mOrientationCompensation = orientationCompensation;
if (effectsActive()) {
CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
- int rotation = (info.orientation + mOrientation) % 360;;
+ int rotation = (info.orientation + mOrientation) % 360;
mEffectsRecorder.setOrientationHint(rotation);
}
// Do not rotate the icons during recording because the video
@@ -1137,6 +1139,13 @@
mMediaRecorder.setCaptureRate((1000 / (double) mTimeBetweenTimeLapseFrameCaptureMs));
}
+ Location loc = mLocationManager.getCurrentLocation();
+ if (loc != null) {
+ mMediaRecorder.setLocation((float) loc.getLatitude(),
+ (float) loc.getLongitude());
+ }
+
+
// Set output file.
// Try Uri in the intent first. If it doesn't exist, use our own
// instead.
@@ -1169,6 +1178,9 @@
// See android.hardware.Camera.Parameters.setRotation for
// documentation.
+ // Note that mOrientation here is the device orientation, which is the opposite of
+ // what activity.getWindowManager().getDefaultDisplay().getRotation() would return,
+ // which is the orientation the graphics need to rotate in order to render correctly.
int rotation = 0;
if (mOrientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
@@ -1179,7 +1191,7 @@
}
}
mMediaRecorder.setOrientationHint(rotation);
- mOrientationHint = rotation;
+ mOrientationCompensationAtRecordStart = mOrientationCompensation;
try {
mMediaRecorder.prepare();
@@ -1214,7 +1226,7 @@
rotation = (info.orientation + mOrientation) % 360;
}
mEffectsRecorder.setOrientationHint(rotation);
- mOrientationHint = rotation;
+ mOrientationCompensationAtRecordStart = mOrientationCompensation;
mEffectsRecorder.setPreviewDisplay(
mSurfaceHolder,
@@ -1546,13 +1558,11 @@
mPreviewFrameLayout.getWidth());
if (bitmap != null) {
// MetadataRetriever already rotates the thumbnail. We should rotate
- // it back (and mirror if it is front-facing camera).
+ // it to match the UI orientation (and mirror if it is front-facing camera).
CameraInfo[] info = CameraHolder.instance().getCameraInfo();
- if (info[mCameraId].facing == CameraInfo.CAMERA_FACING_BACK) {
- bitmap = Util.rotateAndMirror(bitmap, -mOrientationHint, false);
- } else {
- bitmap = Util.rotateAndMirror(bitmap, -mOrientationHint, true);
- }
+ boolean mirror = (info[mCameraId].facing == CameraInfo.CAMERA_FACING_FRONT);
+ bitmap = Util.rotateAndMirror(bitmap, -mOrientationCompensationAtRecordStart,
+ mirror);
mReviewImage.setImageBitmap(bitmap);
mReviewImage.setVisibility(View.VISIBLE);
}
diff --git a/src/com/android/camera/panorama/PanoramaActivity.java b/src/com/android/camera/panorama/PanoramaActivity.java
index a1605de..09df1e0 100755
--- a/src/com/android/camera/panorama/PanoramaActivity.java
+++ b/src/com/android/camera/panorama/PanoramaActivity.java
@@ -38,6 +38,7 @@
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
@@ -71,6 +72,7 @@
import android.widget.TextView;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.util.List;
/**
@@ -147,9 +149,6 @@
private Thumbnail mThumbnail;
private SharePopup mSharePopup;
- private AnimatorSet mThumbnailViewAndModePickerOut;
- private AnimatorSet mThumbnailViewAndModePickerIn;
-
private int mPreviewWidth;
private int mPreviewHeight;
private Camera mCameraDevice;
@@ -271,9 +270,8 @@
onBackgroundThreadFinished();
// Set the thumbnail bitmap here because mThumbnailView must be accessed
// from the UI thread.
- if (mThumbnail != null) {
- mThumbnailView.setBitmap(mThumbnail.getBitmap());
- }
+ updateThumbnailButton();
+
// Share popup may still have the reference to the old thumbnail. Clear it.
mSharePopup = null;
resetToPreview();
@@ -309,6 +307,12 @@
});
}
+ @Override
+ public void onStart() {
+ super.onStart();
+ updateThumbnailButton();
+ }
+
private void setupCamera() {
openCamera();
Parameters parameters = mCameraDevice.getParameters();
@@ -526,30 +530,6 @@
mCaptureIndicator.setVisibility(View.VISIBLE);
showDirectionIndicators(PanoProgressBar.DIRECTION_NONE);
- // XML-style animations can not be used here. The Y position has to be calculated runtime.
- float ystart = mThumbnailView.getY();
- ValueAnimator va1 = ObjectAnimator.ofFloat(
- mThumbnailView, "y", ystart, -mThumbnailView.getHeight());
- ValueAnimator va1Reverse = ObjectAnimator.ofFloat(
- mThumbnailView, "y", -mThumbnailView.getHeight(), ystart);
- ystart = mModePicker.getY();
- float height = mCaptureLayout.getHeight();
- ValueAnimator va2 = ObjectAnimator.ofFloat(
- mModePicker, "y", ystart, height + 1);
- ValueAnimator va2Reverse = ObjectAnimator.ofFloat(
- mModePicker, "y", height + 1, ystart);
- LinearInterpolator li = new LinearInterpolator();
- mThumbnailViewAndModePickerOut = new AnimatorSet();
- mThumbnailViewAndModePickerOut.play(va1).with(va2);
- mThumbnailViewAndModePickerOut.setDuration(500);
- mThumbnailViewAndModePickerOut.setInterpolator(li);
- mThumbnailViewAndModePickerIn = new AnimatorSet();
- mThumbnailViewAndModePickerIn.play(va1Reverse).with(va2Reverse);
- mThumbnailViewAndModePickerIn.setDuration(500);
- mThumbnailViewAndModePickerIn.setInterpolator(li);
-
- mThumbnailViewAndModePickerOut.start();
-
mCompassValueXStart = mCompassValueXStartBuffer;
mCompassValueYStart = mCompassValueYStartBuffer;
mMinAngleX = 0;
@@ -571,6 +551,8 @@
}
});
+ if (mModePicker != null) mModePicker.setEnabled(false);
+
mPanoProgressBar.reset();
// TODO: calculate the indicator width according to different devices to reflect the actual
// angle of view of the camera device.
@@ -609,7 +591,8 @@
}
});
}
- mThumbnailViewAndModePickerIn.start();
+ // do we have to wait for the thread to complete before enabling this?
+ if (mModePicker != null) mModePicker.setEnabled(true);
}
private void showTooFastIndication() {
@@ -749,6 +732,19 @@
t.start();
}
+ private void updateThumbnailButton() {
+ // Update last image if URI is invalid and the storage is ready.
+ ContentResolver contentResolver = getContentResolver();
+ if ((mThumbnail == null || !Util.isUriValid(mThumbnail.getUri(), contentResolver))) {
+ mThumbnail = Thumbnail.getLastThumbnail(contentResolver);
+ }
+ if (mThumbnail != null) {
+ mThumbnailView.setBitmap(mThumbnail.getBitmap());
+ } else {
+ mThumbnailView.setBitmap(null);
+ }
+ }
+
public void saveHighResMosaic() {
runBackgroundThread(new Thread() {
@Override
@@ -884,6 +880,7 @@
stopCapture(true);
reset();
}
+ if (mSharePopup != null) mSharePopup.dismiss();
releaseCamera();
mMosaicView.onPause();
clearMosaicFrameProcessorIfNeeded();
diff --git a/src/com/android/camera/ui/SecondLevelIndicatorControlBar.java b/src/com/android/camera/ui/SecondLevelIndicatorControlBar.java
index f3e5247..8fce8a7 100644
--- a/src/com/android/camera/ui/SecondLevelIndicatorControlBar.java
+++ b/src/com/android/camera/ui/SecondLevelIndicatorControlBar.java
@@ -34,7 +34,7 @@
public class SecondLevelIndicatorControlBar extends IndicatorControl implements
View.OnClickListener, AbstractIndicatorButton.IndicatorChangeListener {
private static final String TAG = "SecondLevelIndicatorControlBar";
- private static int ICON_SPACING = Util.dpToPixel(24);
+ private static int ICON_SPACING = Util.dpToPixel(16);
private ImageView mCloseIcon;
private View mDivider; // the divider line
private View mIndicatorHighlight; // the side highlight bar