Add ability to add a ready-state changed listener to the camera.
Bug: 16945820
Bug: 16948752
This enables us to hook up memory intense cameras and make sure we don't
activate the shutter button if the camera is not ready.
Change-Id: I70a31c76e063d775c844404ee9e20e583fa233e3
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 30b24cf..f3cb1df 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -17,7 +17,6 @@
package com.android.camera;
import android.app.Activity;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
@@ -94,6 +93,7 @@
ModuleController,
OneCamera.PictureCallback,
OneCamera.FocusStateListener,
+ OneCamera.ReadyStateChangedListener,
PreviewStatusListener.PreviewAreaChangedListener,
RemoteCameraModule,
SensorEventListener,
@@ -200,8 +200,6 @@
/** Application context. */
private final Context mContext;
private CaptureModuleUI mUI;
- /** Your standard content resolver. */
- private ContentResolver mContentResolver;
/** The camera manager used to open cameras. */
private OneCameraManager mCameraManager;
/** The currently opened camera device. */
@@ -311,7 +309,6 @@
mIsResumeFromLockScreen = isResumeFromLockscreen(activity);
mMainHandler = new Handler(activity.getMainLooper());
mCameraManager = mAppController.getCameraManager();
- mContentResolver = activity.getContentResolver();
mDisplayRotation = CameraUtil.getDisplayRotation(mContext);
mCameraFacing = getFacingFromCameraId(mSettingsManager.getInteger(
mAppController.getModuleScope(),
@@ -341,7 +338,6 @@
if (mCamera == null) {
return;
}
- mAppController.setShutterEnabled(false);
// Set up the capture session.
long sessionTime = System.currentTimeMillis();
@@ -464,6 +460,7 @@
Log.d(TAG, "Ready for capture.");
onPreviewStarted();
mCamera.setFocusStateListener(CaptureModule.this);
+ mCamera.setReadyStateChangedListener(CaptureModule.this);
}
});
}
@@ -520,6 +517,8 @@
mAppController.addPreviewAreaSizeChangedListener(this);
resetDefaultBufferSize();
getServices().getRemoteShutterListener().onModuleReady(this);
+ // TODO: Check if we can really take a photo right now (memory, camera
+ // state, ... ).
mAppController.setShutterEnabled(true);
}
@@ -716,6 +715,11 @@
}
@Override
+ public void onReadyStateChanged(boolean readyForCapture) {
+ mAppController.setShutterEnabled(readyForCapture);
+ }
+
+ @Override
public String getPeekAccessibilityString() {
return mAppController.getAndroidContext()
.getResources().getString(R.string.photo_accessibility_peek);
@@ -728,8 +732,6 @@
@Override
public void onPictureTaken(CaptureSession session) {
- // TODO, enough memory available? ProcessingService status, etc.
- mAppController.setShutterEnabled(true);
}
@Override
@@ -744,7 +746,6 @@
@Override
public void onPictureTakenFailed() {
- // TODO
}
@Override
diff --git a/src/com/android/camera/one/AbstractOneCamera.java b/src/com/android/camera/one/AbstractOneCamera.java
index d21e9f4..6bd75cf 100644
--- a/src/com/android/camera/one/AbstractOneCamera.java
+++ b/src/com/android/camera/one/AbstractOneCamera.java
@@ -27,6 +27,7 @@
public abstract class AbstractOneCamera implements OneCamera {
protected CameraErrorListener mCameraErrorListener;
protected FocusStateListener mFocusStateListener;
+ protected ReadyStateChangedListener mReadyStateChangedListener;
@Override
public final void setCameraErrorListener(CameraErrorListener listener) {
@@ -38,6 +39,11 @@
mFocusStateListener = listener;
}
+ @Override
+ public void setReadyStateChangedListener(ReadyStateChangedListener listener) {
+ mReadyStateChangedListener = listener;
+ }
+
/**
* Create a directory we can use to store debugging information during Gcam
* captures.
@@ -64,4 +70,13 @@
String destFolderPath = destFolder.getAbsolutePath();
return destFolderPath;
}
+
+ /**
+ * If set, tells the ready state changed listener the new state.
+ */
+ protected void broadcastReadyState(boolean readyForCapture) {
+ if (mReadyStateChangedListener != null) {
+ mReadyStateChangedListener.onReadyStateChanged(readyForCapture);
+ }
+ }
}
diff --git a/src/com/android/camera/one/OneCamera.java b/src/com/android/camera/one/OneCamera.java
index 555f6cb..d622210 100644
--- a/src/com/android/camera/one/OneCamera.java
+++ b/src/com/android/camera/one/OneCamera.java
@@ -53,7 +53,7 @@
SCANNING,
/** Indicates scan success (camera in focus). */
STOPPED_FOCUSED,
- /** Indicates scan or other failure. */
+ /** Indicates scan or other failure. */
STOPPED_UNFOCUSED
}
@@ -114,6 +114,18 @@
}
/**
+ * Classes implementing this interface can be informed when the state of
+ * capture changes.
+ */
+ public static interface ReadyStateChangedListener {
+ /**
+ * Called when the camera is either ready or not ready to take a picture
+ * right now.
+ */
+ public void onReadyStateChanged(boolean readyForCapture);
+ }
+
+ /**
* A class implementing this interface can be passed into the call to take a
* picture in order to receive the resulting image or updated about the
* progress.
@@ -135,7 +147,7 @@
/**
* Called when the picture has been saved to disk.
*
- * @param uri the URI of the stored data.
+ * @param uri the URI of the stored data.
*/
public void onPictureSaved(Uri uri);
@@ -165,7 +177,7 @@
/**
* Classes implementing this interface will be called when the state of the
- * focus changes. Guaranteed not to stay stuck in scanning state past some
+ * focus changes. Guaranteed not to stay stuck in scanning state past some
* reasonable timeout even if Camera API is stuck.
*/
public static interface FocusStateListener {
@@ -238,8 +250,8 @@
/**
* Meters and triggers auto focus scan with ROI around tap point.
* <p/>
- * Normalized coordinates are referenced to portrait preview window
- * with 0,0 top left and 1,1 bottom right. Rotation has no effect.
+ * Normalized coordinates are referenced to portrait preview window with 0,0
+ * top left and 1,1 bottom right. Rotation has no effect.
*
* @param nx normalized x coordinate.
* @param nx normalized y coordinate.
@@ -267,6 +279,12 @@
public void setFocusStateListener(FocusStateListener listener);
/**
+ * Sets or replaces a listener that is called whenever the state of the
+ * camera changes to be either ready or not ready to take another picture.
+ */
+ public void setReadyStateChangedListener(ReadyStateChangedListener listener);
+
+ /**
* Starts a preview stream and renders it to the given surface.
*/
public void startPreview(Surface surface, CaptureReadyCallback listener);
diff --git a/src/com/android/camera/one/v2/OneCameraImpl.java b/src/com/android/camera/one/v2/OneCameraImpl.java
index f353c5f..d212fa5 100644
--- a/src/com/android/camera/one/v2/OneCameraImpl.java
+++ b/src/com/android/camera/one/v2/OneCameraImpl.java
@@ -229,6 +229,7 @@
byte[] imageBytes = acquireJpegBytesAndClose(reader);
// TODO: The savePicture call here seems to block UI thread.
savePicture(imageBytes, capture.parameters, capture.session);
+ broadcastReadyState(true);
capture.parameters.callback.onPictureTaken(capture.session);
}
};
@@ -266,6 +267,9 @@
return;
}
+ // Wait until the picture comes back.
+ broadcastReadyState(false);
+
mTakePictureRunnable = new Runnable() {
@Override
public void run() {
@@ -336,6 +340,7 @@
mCaptureSession.capture(request, mAutoFocusStateListener, mCameraHandler);
} catch (CameraAccessException e) {
Log.e(TAG, "Could not access camera for still image capture.");
+ broadcastReadyState(true);
params.callback.onPictureTakenFailed();
return;
}