summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/camera/CaptureModule.java5
-rw-r--r--src/com/android/camera/captureintent/CaptureIntentSession.java13
-rw-r--r--src/com/android/camera/captureintent/resource/ResourceCaptureToolsImpl.java2
-rw-r--r--src/com/android/camera/session/CaptureSession.java61
-rw-r--r--src/com/android/camera/session/CaptureSessionImpl.java67
-rw-r--r--src_pd/com/android/camera/stats/CaptureStats.java36
6 files changed, 167 insertions, 17 deletions
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 90495471d..1a0d33d9d 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -71,6 +71,7 @@ import com.android.camera.remote.RemoteCameraModule;
import com.android.camera.session.CaptureSession;
import com.android.camera.settings.Keys;
import com.android.camera.settings.SettingsManager;
+import com.android.camera.stats.CaptureStats;
import com.android.camera.stats.UsageStatistics;
import com.android.camera.stats.profiler.Profile;
import com.android.camera.stats.profiler.Profiler;
@@ -555,7 +556,9 @@ public class CaptureModule extends CameraModule implements
String title = CameraUtil.instance().createJpegName(sessionTime);
CaptureSession session = getServices().getCaptureSessionManager()
.createNewSession(title, sessionTime, location);
- session.startEmpty(new Size((int) mPreviewArea.width(), (int) mPreviewArea.height()));
+
+ session.startEmpty(new CaptureStats(mHdrPlusEnabled),
+ new Size((int) mPreviewArea.width(), (int) mPreviewArea.height()));
return session;
}
diff --git a/src/com/android/camera/captureintent/CaptureIntentSession.java b/src/com/android/camera/captureintent/CaptureIntentSession.java
index bd78dceb3..6fb22c620 100644
--- a/src/com/android/camera/captureintent/CaptureIntentSession.java
+++ b/src/com/android/camera/captureintent/CaptureIntentSession.java
@@ -33,6 +33,8 @@ import com.google.common.base.Optional;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import javax.annotation.Nonnull;
+
/**
* An implementation of {@link CaptureSession} which is used by
* {@link CaptureIntentModule}.
@@ -118,22 +120,25 @@ public class CaptureIntentSession implements CaptureSession {
}
@Override
- public synchronized void startEmpty(Size pictureSize) {
+ public synchronized void startEmpty(ImageLifecycleListener listener, @Nonnull Size pictureSize) {
isStarted = true;
}
@Override
- public synchronized void startSession(Bitmap placeholder, int progressMessageId) {
+ public synchronized void startSession(ImageLifecycleListener listener, @Nonnull Bitmap placeholder,
+ int progressMessageId) {
throw new RuntimeException("Not supported.");
}
@Override
- public synchronized void startSession(byte[] placeholder, int progressMessageId) {
+ public synchronized void startSession(ImageLifecycleListener listener, @Nonnull byte[] placeholder,
+ int progressMessageId) {
throw new RuntimeException("Not supported.");
}
@Override
- public synchronized void startSession(Uri uri, int progressMessageId) {
+ public synchronized void startSession(ImageLifecycleListener listener, @Nonnull Uri uri,
+ @Nonnull int progressMessageId) {
throw new RuntimeException("Not supported.");
}
diff --git a/src/com/android/camera/captureintent/resource/ResourceCaptureToolsImpl.java b/src/com/android/camera/captureintent/resource/ResourceCaptureToolsImpl.java
index 35ddc702b..adce211de 100644
--- a/src/com/android/camera/captureintent/resource/ResourceCaptureToolsImpl.java
+++ b/src/com/android/camera/captureintent/resource/ResourceCaptureToolsImpl.java
@@ -171,7 +171,7 @@ public final class ResourceCaptureToolsImpl implements ResourceCaptureTools {
resource.getLocationManager().getCurrentLocation();
final CaptureSession session =
mCaptureSessionManager.createNewSession(fileName, timestamp, location);
- session.startEmpty(openedCamera.getPictureSize());
+ session.startEmpty(null, openedCamera.getPictureSize());
/** Logging */
final SettingsManager settingsManager = resource.getSettingsManager();
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);
diff --git a/src_pd/com/android/camera/stats/CaptureStats.java b/src_pd/com/android/camera/stats/CaptureStats.java
new file mode 100644
index 000000000..72ff1824d
--- /dev/null
+++ b/src_pd/com/android/camera/stats/CaptureStats.java
@@ -0,0 +1,36 @@
+package com.android.camera.stats;
+
+import com.android.camera.session.CaptureSession.ImageLifecycleListener;
+
+/**
+ * Simple statistics of internal app behavior during capture.
+ */
+public class CaptureStats implements ImageLifecycleListener {
+
+ public CaptureStats(boolean isHdrPlus) {
+ }
+
+ @Override
+ public void onCaptureStarted() {
+ }
+
+ @Override
+ public void onTinyThumb() {
+ }
+
+ @Override
+ public void onMediumThumb() {
+ }
+
+ @Override
+ public void onProcessingStarted() {
+ }
+
+ @Override
+ public void onProcessingComplete() {
+ }
+
+ @Override
+ public void onCapturePersisted() {
+ }
+}