summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/session
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/camera/session')
-rw-r--r--src/com/android/camera/session/CaptureSession.java61
-rw-r--r--src/com/android/camera/session/CaptureSessionImpl.java67
2 files changed, 117 insertions, 11 deletions
diff --git a/src/com/android/camera/session/CaptureSession.java b/src/com/android/camera/session/CaptureSession.java
index 7b2808904..0dff1a1b3 100644
--- a/src/com/android/camera/session/CaptureSession.java
+++ b/src/com/android/camera/session/CaptureSession.java
@@ -23,9 +23,13 @@ import android.net.Uri;
import com.android.camera.exif.ExifInterface;
import com.android.camera.stats.CaptureSessionStatsCollector;
import com.android.camera.util.Size;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
/**
* A session is an item that is in progress of being created and saved, such as
* a photo sphere or HDR+ photo.
@@ -58,6 +62,45 @@ public interface CaptureSession {
public void onStatusMessageChanged(int messageId);
}
+ /**
+ * Classes implementing this interface can listen to progress updates of
+ * this session.
+ */
+ public static interface ImageLifecycleListener {
+ /**
+ * Occurs when, for a particular image type, an image capture has
+ * started. This method is always executed, and will always be called
+ * first.
+ */
+ public void onCaptureStarted();
+
+ /**
+ * Occurs when the tiny thumbnail bytes are received.
+ */
+ public void onTinyThumb();
+
+ /**
+ * Occurs when the medium thumbnail bytes are received.
+ */
+ public void onMediumThumb();
+
+ /**
+ * Occurs when rendering/processing/encoding starts for the full size image.
+ */
+ public void onProcessingStarted();
+
+ /**
+ * Occurs when the rendering/processing/encoding for the full size image
+ * is completed.
+ */
+ public void onProcessingComplete();
+
+ /**
+ * This occurs after all the bytes are physically on disk.
+ */
+ public void onCapturePersisted();
+ }
+
/** Returns the title/name of this session. */
public String getTitle();
@@ -109,42 +152,50 @@ public interface CaptureSession {
/**
* Starts an empty session with the given placeholder size.
*
- * @param mPictureSize the size, in pixels of the empty placeholder.
+ * @param listener receives events as the session progresses.
+ * @param pictureSize the size, in pixels of the empty placeholder.
*/
- public void startEmpty(Size mPictureSize);
+ public void startEmpty(@Nullable ImageLifecycleListener listener, @Nonnull Size pictureSize);
/**
* Starts the session by adding a placeholder to the filmstrip and adding
* notifications.
*
+ * @param listener receives events as the session progresses.
* @param placeholder a valid encoded bitmap to be used as the placeholder.
* @param progressMessageId the message to be used to the progress
* notification initially. This can later be changed using
* {@link #setProgressMessage(int)}.
*/
- public void startSession(byte[] placeholder, int progressMessageId);
+ public void startSession(@Nullable ImageLifecycleListener listener, @Nonnull byte[] placeholder,
+ int progressMessageId);
/**
* Starts the session by adding a placeholder to the filmstrip and adding
* notifications.
*
+ * @param listener receives events as the session progresses.
* @param placeholder a valid bitmap to be used as the placeholder.
* @param progressMessageId the message to be used to the progress
* notification initially. This can later be changed using
* {@link #setProgressMessage(int)}.
*/
- public void startSession(Bitmap placeholder, int progressMessageId);
+ @VisibleForTesting
+ public void startSession(@Nullable ImageLifecycleListener listener, @Nonnull Bitmap placeholder,
+ int progressMessageId);
/**
* Starts the session by marking the item as in-progress and adding
* notifications.
*
+ * @param listener receives events as the session progresses.
* @param uri the URI of the item to be re-processed.
* @param progressMessageId the message to be used to the progress
* notification initially. This can later be changed using
* {@link #setProgressMessage(int)}.
*/
- public void startSession(Uri uri, int progressMessageId);
+ public void startSession(@Nullable ImageLifecycleListener listener, @Nonnull Uri uri,
+ int progressMessageId);
/**
* Cancel the session without a final result. The session will be removed
diff --git a/src/com/android/camera/session/CaptureSessionImpl.java b/src/com/android/camera/session/CaptureSessionImpl.java
index 0cb5257c9..042c24bed 100644
--- a/src/com/android/camera/session/CaptureSessionImpl.java
+++ b/src/com/android/camera/session/CaptureSessionImpl.java
@@ -37,6 +37,9 @@ import java.io.File;
import java.io.IOException;
import java.util.HashSet;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
/**
* The default implementation of the CaptureSession interface. This is the
* implementation we use for normal Camera use.
@@ -80,6 +83,10 @@ public class CaptureSessionImpl implements CaptureSession {
/** Object that collects logging information through the capture session lifecycle */
private final CaptureSessionStatsCollector mCaptureSessionStatsCollector = new CaptureSessionStatsCollector();
+ @Nullable
+ private ImageLifecycleListener mImageLifecycleListener;
+ private boolean mHasPreviouslySetProgress = false;
+
/**
* Creates a new {@link CaptureSession}.
*
@@ -140,6 +147,10 @@ public class CaptureSessionImpl implements CaptureSession {
@Override
public synchronized void setProgress(int percent) {
+ if (!mHasPreviouslySetProgress && percent == 0 && mImageLifecycleListener != null) {
+ mImageLifecycleListener.onProcessingStarted();
+ }
+
mProgressPercent = percent;
mSessionNotifier.notifyTaskProgress(mUri, mProgressPercent);
for (ProgressListener listener : mProgressListeners) {
@@ -163,21 +174,34 @@ public class CaptureSessionImpl implements CaptureSession {
@Override
public void updateThumbnail(Bitmap bitmap) {
+ if (mImageLifecycleListener != null) {
+ mImageLifecycleListener.onMediumThumb();
+ }
mPlaceholderManager.replacePlaceholder(mPlaceHolder, bitmap);
mSessionNotifier.notifySessionUpdated(mUri);
}
@Override
public void updateCaptureIndicatorThumbnail(Bitmap indicator, int rotationDegrees) {
+ if (mImageLifecycleListener != null) {
+ mImageLifecycleListener.onTinyThumb();
+ }
onCaptureIndicatorUpdate(indicator, rotationDegrees);
+
}
@Override
- public synchronized void startEmpty(Size pictureSize) {
+ public synchronized void startEmpty(@Nullable ImageLifecycleListener listener,
+ @Nonnull Size pictureSize) {
if (mIsFinished) {
return;
}
+ if (listener != null) {
+ mImageLifecycleListener = listener;
+ mImageLifecycleListener.onCaptureStarted();
+ }
+
mProgressMessageId = -1;
mPlaceHolder = mPlaceholderManager.insertEmptyPlaceholder(mTitle, pictureSize,
mSessionStartMillis);
@@ -187,11 +211,17 @@ public class CaptureSessionImpl implements CaptureSession {
}
@Override
- public synchronized void startSession(Bitmap placeholder, int progressMessageId) {
+ public synchronized void startSession(@Nullable ImageLifecycleListener listener,
+ @Nonnull Bitmap placeholder, int progressMessageId) {
if (mIsFinished) {
return;
}
+ if (listener != null) {
+ mImageLifecycleListener = listener;
+ mImageLifecycleListener.onCaptureStarted();
+ }
+
mProgressMessageId = progressMessageId;
mPlaceHolder = mPlaceholderManager.insertPlaceholder(mTitle, placeholder,
mSessionStartMillis);
@@ -202,11 +232,17 @@ public class CaptureSessionImpl implements CaptureSession {
}
@Override
- public synchronized void startSession(byte[] placeholder, int progressMessageId) {
+ public synchronized void startSession(@Nullable ImageLifecycleListener listener,
+ @Nonnull byte[] placeholder, int progressMessageId) {
if (mIsFinished) {
return;
}
+ if (listener != null) {
+ mImageLifecycleListener = listener;
+ mImageLifecycleListener.onCaptureStarted();
+ }
+
mProgressMessageId = progressMessageId;
mPlaceHolder = mPlaceholderManager.insertPlaceholder(mTitle, placeholder,
mSessionStartMillis);
@@ -221,7 +257,13 @@ public class CaptureSessionImpl implements CaptureSession {
}
@Override
- public synchronized void startSession(Uri uri, int progressMessageId) {
+ public synchronized void startSession(@Nullable ImageLifecycleListener listener,
+ @Nonnull Uri uri, int progressMessageId) {
+ if (listener != null) {
+ mImageLifecycleListener = listener;
+ mImageLifecycleListener.onCaptureStarted();
+ }
+
mUri = uri;
mProgressMessageId = progressMessageId;
mPlaceHolder = mPlaceholderManager.convertToPlaceholder(uri);
@@ -244,18 +286,27 @@ public class CaptureSessionImpl implements CaptureSession {
}
@Override
- public synchronized ListenableFuture<Optional<Uri>> saveAndFinish(byte[] data, int width, int height,
- int orientation, ExifInterface exif) {
+ public synchronized ListenableFuture<Optional<Uri>> saveAndFinish(byte[] data, int width,
+ int height, int orientation, ExifInterface exif) {
final SettableFuture<Optional<Uri>> futureResult = SettableFuture.create();
+ if (mImageLifecycleListener != null) {
+ mImageLifecycleListener.onProcessingComplete();
+ }
+
mIsFinished = true;
if (mPlaceHolder == null) {
+
mMediaSaver.addImage(
data, mTitle, mSessionStartMillis, mLocation, width, height,
orientation, exif, new MediaSaver.OnMediaSavedListener() {
@Override
public void onMediaSaved(Uri uri) {
futureResult.set(Optional.fromNullable(uri));
+
+ if (mImageLifecycleListener != null) {
+ mImageLifecycleListener.onCapturePersisted();
+ }
}
});
} else {
@@ -264,6 +315,10 @@ public class CaptureSessionImpl implements CaptureSession {
orientation, exif, data, width, height, FilmstripItemData.MIME_TYPE_JPEG);
mSessionNotifier.notifyTaskDone(mUri);
futureResult.set(Optional.fromNullable(mUri));
+
+ if (mImageLifecycleListener != null) {
+ mImageLifecycleListener.onCapturePersisted();
+ }
} catch (IOException e) {
Log.e(TAG, "Could not write file", e);
finishWithFailure(-1, true);