Merge "Load Gcam OneCamera in CaptureModule when it's also doing normal shots." into ub-camera-glacier
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 11d97c0..e6eb5f9 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -333,7 +333,7 @@
<string name="setting_front_camera_photo" msgid="4131886734622868637">"Foto de càmera frontal"</string>
<string name="setting_front_camera_video" msgid="2178799452805359752">"Vídeo de càmera frontal"</string>
<string name="setting_default_camera" msgid="6954076799301004779">"Càmera predeterminada"</string>
- <string name="setting_google_help_and_feedback" msgid="2079580537079242775">"Ajuda i comentaris"</string>
+ <string name="setting_google_help_and_feedback" msgid="2079580537079242775">"Ajuda i suggeriments"</string>
<string name="processing_hdr_plus" msgid="9160093263037540304">"Processant HDR+..."</string>
<string name="open_source_licenses" msgid="2169711954264883060">"Llicències de codi obert"</string>
<string name="pref_category_general" msgid="6737748849700581019">"Configuració general"</string>
diff --git a/res/values/bool.xml b/res/values/bool.xml
index bcb30de..464842a 100644
--- a/res/values/bool.xml
+++ b/res/values/bool.xml
@@ -15,5 +15,4 @@
-->
<resources>
<bool name="show_action_bar_title">false</bool>
- <bool name="is_os_version_l">false</bool>
</resources>
\ No newline at end of file
diff --git a/src/android/util/CameraPerformanceTracker.java b/src/android/util/CameraPerformanceTracker.java
index 4e46058..60a1ab0 100644
--- a/src/android/util/CameraPerformanceTracker.java
+++ b/src/android/util/CameraPerformanceTracker.java
@@ -75,6 +75,7 @@
sInstance.mAppResumeTime = currentTime;
break;
case FIRST_PREVIEW_FRAME:
+ Log.d(TAG, "First preview frame received");
if (sInstance.mFirstPreviewFrameLatencyColdStart == UNSET) {
// Cold start.
sInstance.mFirstPreviewFrameLatencyColdStart =
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 46086a7..e6f81cd 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -1102,8 +1102,13 @@
}
@Override
+ public void startPreCaptureAnimation(boolean shortFlash) {
+ mCameraAppUI.startPreCaptureAnimation(shortFlash);
+ }
+
+ @Override
public void startPreCaptureAnimation() {
- mCameraAppUI.startPreCaptureAnimation();
+ mCameraAppUI.startPreCaptureAnimation(false);
}
@Override
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 73b16c0..16a0d69 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -390,7 +390,7 @@
}
@Override
- public void onRemainingSecondsChanged(int remainingSeconds){
+ public void onRemainingSecondsChanged(int remainingSeconds) {
if (remainingSeconds == 1) {
mCountdownSoundPlayer.play(R.raw.beep_twice, 0.6f);
} else if (remainingSeconds == 2 || remainingSeconds == 3) {
@@ -408,6 +408,17 @@
}
@Override
+ public void onQuickExpose() {
+ mMainHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ // Starts the short version of the capture animation UI.
+ mAppController.startPreCaptureAnimation(true);
+ }
+ });
+ }
+
+ @Override
public void onPreviewAreaChanged(RectF previewArea) {
mPreviewArea = previewArea;
mUI.onPreviewAreaChanged(previewArea);
diff --git a/src/com/android/camera/app/AppController.java b/src/com/android/camera/app/AppController.java
index f273914..4516bfb 100644
--- a/src/com/android/camera/app/AppController.java
+++ b/src/com/android/camera/app/AppController.java
@@ -271,7 +271,14 @@
/********************** Capture animation **********************/
/**
- * Starts the pre-capture animation.
+ * Starts the pre-capture animation with optional shorter flash.
+ *
+ * @param shortFlash true for shorter flash (faster cameras).
+ */
+ public void startPreCaptureAnimation(boolean shortFlash);
+
+ /**
+ * Starts normal pre-capture animation.
*/
public void startPreCaptureAnimation();
diff --git a/src/com/android/camera/app/CameraAppUI.java b/src/com/android/camera/app/CameraAppUI.java
index c123d52..8dc3400 100644
--- a/src/com/android/camera/app/CameraAppUI.java
+++ b/src/com/android/camera/app/CameraAppUI.java
@@ -1472,9 +1472,11 @@
/**
* Starts the pre-capture animation.
+ *
+ * @param shortFlash show shortest possible flash instead of regular long version.
*/
- public void startPreCaptureAnimation() {
- mCaptureOverlay.startFlashAnimation();
+ public void startPreCaptureAnimation(boolean shortFlash) {
+ mCaptureOverlay.startFlashAnimation(shortFlash);
}
/**
diff --git a/src/com/android/camera/one/OneCamera.java b/src/com/android/camera/one/OneCamera.java
index 1ae63fc..ab0f95e 100644
--- a/src/com/android/camera/one/OneCamera.java
+++ b/src/com/android/camera/one/OneCamera.java
@@ -143,6 +143,13 @@
*/
public static interface PictureCallback {
/**
+ * Called near the the when an image is being exposed for cameras which
+ * are exposing a single frame, so that a UI can be presented for the
+ * capture.
+ */
+ public void onQuickExpose();
+
+ /**
* Called when a thumbnail image is provided before the final image is
* finished.
*/
diff --git a/src/com/android/camera/one/v2/ImageCaptureManager.java b/src/com/android/camera/one/v2/ImageCaptureManager.java
index edfce80..464cb1e 100644
--- a/src/com/android/camera/one/v2/ImageCaptureManager.java
+++ b/src/com/android/camera/one/v2/ImageCaptureManager.java
@@ -102,7 +102,7 @@
* Callback for saving an image.
*/
public interface ImageCaptureListener {
- /**
+ /**
* Called with the {@link Image} and associated
* {@link TotalCaptureResult}. A typical implementation would save this
* to disk.
@@ -234,6 +234,23 @@
private static final long DEBUG_MAX_IMAGE_CALLBACK_DUR = 25;
/**
+ * If spacing between onCaptureCompleted() callbacks is lower than this
+ * value, camera operations at the Java level have stalled, and are now
+ * catching up. In milliseconds.
+ */
+ private static final long DEBUG_INTERFRAME_STALL_WARNING = 5;
+
+ /**
+ * Last called to onCaptureCompleted() in SystemClock.uptimeMillis().
+ */
+ private long mDebugLastOnCaptureCompletedMillis = 0;
+
+ /**
+ * Number of frames in a row exceeding DEBUG_INTERFRAME_STALL_WARNING.
+ */
+ private long mDebugStalledFrameCount = 0;
+
+ /**
* Stores the ring-buffer of captured images.<br>
* Note that this takes care of thread-safe reference counting of images to
* ensure that they are never leaked by the app.
@@ -403,6 +420,16 @@
final TotalCaptureResult result) {
final long timestamp = result.get(TotalCaptureResult.SENSOR_TIMESTAMP);
+ // Detect camera thread stall.
+ long now = SystemClock.uptimeMillis();
+ if (now - mDebugLastOnCaptureCompletedMillis < DEBUG_INTERFRAME_STALL_WARNING) {
+ Log.e(TAG, "Camera thread has stalled for " + ++mDebugStalledFrameCount +
+ " frames at # " + result.getFrameNumber() + ".");
+ } else {
+ mDebugStalledFrameCount = 0;
+ }
+ mDebugLastOnCaptureCompletedMillis = now;
+
// Find the CapturedImage in the ring-buffer and attach the
// TotalCaptureResult to it.
// See documentation for swapLeast() for details.
diff --git a/src/com/android/camera/one/v2/OneCameraImpl.java b/src/com/android/camera/one/v2/OneCameraImpl.java
index 1abdadb..3f7e461 100644
--- a/src/com/android/camera/one/v2/OneCameraImpl.java
+++ b/src/com/android/camera/one/v2/OneCameraImpl.java
@@ -125,6 +125,8 @@
private boolean mTakePictureWhenLensIsStopped = false;
/** Takes a (delayed) picture with appropriate parameters. */
private Runnable mTakePictureRunnable;
+ /** Keep PictureCallback for last requested capture. */
+ private PictureCallback mLastPictureCallback = null;
/** Last time takePicture() was called in uptimeMillis. */
private long mTakePictureStartMillis;
/** Runnable that returns to CONTROL_AF_MODE = AF_CONTINUOUS_PICTURE. */
@@ -153,6 +155,14 @@
*/
private final CameraCaptureSession.CaptureListener mAutoFocusStateListener = new
CameraCaptureSession.CaptureListener() {
+ @Override
+ public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
+ long timestamp) {
+ if (request.getTag() == RequestTag.CAPTURE && mLastPictureCallback != null) {
+ mLastPictureCallback.onQuickExpose();
+ }
+ }
+
// AF state information is sometimes available 1 frame before
// onCaptureCompleted(), so we take advantage of that.
@Override
@@ -269,6 +279,7 @@
takePictureNow(params, session);
}
};
+ mLastPictureCallback = params.callback;
mTakePictureStartMillis = SystemClock.uptimeMillis();
// This class implements a very simple version of AF, which
diff --git a/src/com/android/camera/one/v2/OneCameraZslImpl.java b/src/com/android/camera/one/v2/OneCameraZslImpl.java
index 4d5fdef..874ace4 100644
--- a/src/com/android/camera/one/v2/OneCameraZslImpl.java
+++ b/src/com/android/camera/one/v2/OneCameraZslImpl.java
@@ -34,6 +34,7 @@
import android.media.CameraProfile;
import android.media.Image;
import android.media.ImageReader;
+import android.media.MediaActionSound;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
@@ -182,6 +183,8 @@
private MeteringRectangle[] mAFRegions = ZERO_WEIGHT_3A_REGION;
private MeteringRectangle[] mAERegions = ZERO_WEIGHT_3A_REGION;
+ private MediaActionSound mMediaActionSound = new MediaActionSound();
+
/**
* Ready state (typically displayed by the UI shutter-button) depends on two
* things:<br>
@@ -246,7 +249,6 @@
mReadyStateManager.setInput(
ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS, true);
- // TODO Add callback to CaptureModule here to flash the screen.
mSession.startEmpty();
savePicture(image, mParams, mSession);
mParams.callback.onPictureTaken(mSession);
@@ -319,6 +321,7 @@
sCaptureImageFormat, MAX_CAPTURE_IMAGES);
mCaptureImageReader.setOnImageAvailableListener(mCaptureManager, mCameraHandler);
+ mMediaActionSound.load(MediaActionSound.SHUTTER_CLICK);
}
/**
@@ -345,6 +348,14 @@
largestSupportedSize.getHeight());
}
+
+ private void onShutterInvokeUI(final PhotoCaptureParameters params) {
+ // Tell CaptureModule shutter has occurred so it can flash the screen.
+ params.callback.onQuickExpose();
+ // Play shutter click sound.
+ mMediaActionSound.play(MediaActionSound.SHUTTER_CLICK);
+ }
+
/**
* Take a picture.
*/
@@ -439,6 +450,7 @@
new ImageCaptureTask(params, session), zslConstraints);
if (capturedPreviousFrame) {
Log.v(TAG, "Saving previous frame");
+ onShutterInvokeUI(params);
} else {
Log.v(TAG, "No good image Available. Capturing next available good image.");
// If there was no good frame available in the ring buffer
@@ -473,6 +485,8 @@
CaptureResult.CONTROL_AE_STATE_PRECAPTURE))) {
mCaptureManager.removeMetadataChangeListener(key, this);
sendSingleRequest(params);
+ // TODO: Delay this until onCaptureStarted().
+ onShutterInvokeUI(params);
}
}
});
diff --git a/src/com/android/camera/ui/BottomBar.java b/src/com/android/camera/ui/BottomBar.java
index cfc6a14..551cc09 100644
--- a/src/com/android/camera/ui/BottomBar.java
+++ b/src/com/android/camera/ui/BottomBar.java
@@ -32,6 +32,7 @@
import com.android.camera.CaptureLayoutHelper;
import com.android.camera.ShutterButton;
import com.android.camera.debug.Log;
+import com.android.camera.util.ApiHelper;
import com.android.camera.util.CameraUtil;
import com.android.camera2.R;
@@ -74,7 +75,6 @@
private final float mCircleRadius;
private CaptureLayoutHelper mCaptureLayoutHelper = null;
- private final boolean mIsOsVersionL;
// for Android L, these backgrounds are RippleDrawables (ISA LayerDrawable)
// pre-L, they're plain old LayerDrawables
private final LayerDrawable[] mShutterButtonBackgrounds;
@@ -96,8 +96,6 @@
mBackgroundAlphaDefault = getResources()
.getInteger(R.integer.bottom_bar_background_alpha);
- mIsOsVersionL = context.getResources().getBoolean(R.bool.is_os_version_l);
-
// preload all the drawable BGs
TypedArray ar = context.getResources()
.obtainTypedArray(R.array.shutter_button_backgrounds);
@@ -129,13 +127,9 @@
if (mAnimatedCircleDrawable != null) {
mAnimatedCircleDrawable.setColor(color);
mAnimatedCircleDrawable.setAlpha(alpha);
- invalidateDrawable(mAnimatedCircleDrawable);
- invalidate();
} else if (mColorDrawable != null) {
mColorDrawable.setColor(color);
mColorDrawable.setAlpha(alpha);
- invalidateDrawable(mColorDrawable);
- invalidate();
}
if (mIntentReviewLayout != null) {
@@ -153,7 +147,7 @@
private void setCancelBackgroundColor(int alpha, int color) {
LayerDrawable layerDrawable = (LayerDrawable) mCancelButton.getBackground();
ColorDrawable colorDrawable = (ColorDrawable) layerDrawable.getDrawable(0);
- if (!mIsOsVersionL) {
+ if (!ApiHelper.isLOrHigher()) {
colorDrawable.setColor(color);
}
colorDrawable.setAlpha(alpha);
@@ -164,7 +158,7 @@
}
private void setCaptureButtonDown() {
- if (!mIsOsVersionL) {
+ if (!ApiHelper.isLOrHigher()) {
setPaintColor(mBackgroundAlpha, mBackgroundPressedColor);
}
}
@@ -346,7 +340,7 @@
}
private void setBackgroundPressedColor(int color) {
- if (mIsOsVersionL) {
+ if (ApiHelper.isLOrHigher()) {
// not supported (setting a color on a RippleDrawable is hard =[ )
} else {
mBackgroundPressedColor = color;
diff --git a/src/com/android/camera/ui/CaptureAnimationOverlay.java b/src/com/android/camera/ui/CaptureAnimationOverlay.java
index 9a7126d..19a21f1 100644
--- a/src/com/android/camera/ui/CaptureAnimationOverlay.java
+++ b/src/com/android/camera/ui/CaptureAnimationOverlay.java
@@ -44,13 +44,14 @@
implements PreviewStatusListener.PreviewAreaChangedListener {
private final static Log.Tag TAG = new Log.Tag("CaptureAnimOverlay");
- private final static int FLASH_ALPHA_BEFORE_SHRINK = 180;
- private final static int FLASH_ALPHA_AFTER_SHRINK = 50;
private final static int FLASH_COLOR = Color.WHITE;
private static final float FLASH_MAX_ALPHA = 0.85f;
private static final long FLASH_FULL_DURATION_MS = 65;
private static final long FLASH_DECREASE_DURATION_MS = 150;
+ private static final float SHORT_FLASH_MAX_ALPHA = 0.75f;
+ private static final long SHORT_FLASH_FULL_DURATION_MS = 34;
+ private static final long SHORT_FLASH_DECREASE_DURATION_MS = 100;
private RectF mPreviewArea = new RectF();
@@ -97,22 +98,37 @@
/**
* Start flash animation.
+ *
+ * @param shortFlash show shortest possible flash instead of regular long version.
*/
- public void startFlashAnimation() {
+ public void startFlashAnimation(boolean shortFlash) {
if (mFlashAnimation != null && mFlashAnimation.isRunning()) {
mFlashAnimation.cancel();
}
+ float maxAlpha;
- ValueAnimator flashAnim1 = ValueAnimator.ofFloat(FLASH_MAX_ALPHA, FLASH_MAX_ALPHA);
- ValueAnimator flashAnim2 = ValueAnimator.ofFloat(FLASH_MAX_ALPHA, .0f);
- flashAnim1.setDuration(FLASH_FULL_DURATION_MS);
- flashAnim2.setDuration(FLASH_DECREASE_DURATION_MS);
+ if (shortFlash) {
+ maxAlpha = SHORT_FLASH_MAX_ALPHA;
+ } else {
+ maxAlpha = FLASH_MAX_ALPHA;
+ }
+
+ ValueAnimator flashAnim1 = ValueAnimator.ofFloat(maxAlpha, maxAlpha);
+ ValueAnimator flashAnim2 = ValueAnimator.ofFloat(maxAlpha, .0f);
+
+ if (shortFlash) {
+ flashAnim1.setDuration(SHORT_FLASH_FULL_DURATION_MS);
+ flashAnim2.setDuration(SHORT_FLASH_DECREASE_DURATION_MS);
+ } else {
+ flashAnim1.setDuration(FLASH_FULL_DURATION_MS);
+ flashAnim2.setDuration(FLASH_DECREASE_DURATION_MS);
+ }
+
flashAnim1.addUpdateListener(mFlashAnimUpdateListener);
flashAnim2.addUpdateListener(mFlashAnimUpdateListener);
flashAnim1.setInterpolator(mFlashAnimInterpolator);
flashAnim2.setInterpolator(mFlashAnimInterpolator);
-
mFlashAnimation = new AnimatorSet();
mFlashAnimation.play(flashAnim1).before(flashAnim2);
mFlashAnimation.addListener(mFlashAnimListener);