import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
import com.android.camera.util.QuickActivity;
import com.android.camera.util.ReleaseHelper;
-import com.android.camera.util.Size;
import com.android.camera.widget.FilmstripView;
import com.android.camera.widget.Preloader;
import com.android.camera2.R;
import com.bumptech.glide.MemoryCategory;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor;
-import com.bumptech.glide.load.engine.prefill.PreFillType;
import com.google.common.base.Optional;
import com.google.common.logging.eventprotos;
import com.google.common.logging.eventprotos.ForegroundEvent.ForegroundSource;
if (!Storage.isSessionUri(uri)) {
return;
}
- SessionItem newData = new SessionItem(getApplicationContext(), uri);
- mDataAdapter.addOrUpdate(newData);
+ Optional<SessionItem> newData = SessionItem.create(getApplicationContext(), uri);
+ if (newData.isPresent()) {
+ mDataAdapter.addOrUpdate(newData.get());
+ }
}
@Override
}
@Override
+ public void onSessionCanceled(Uri uri) {
+ Log.v(TAG, "onSessionCanceled:" + uri);
+ int failedIndex = mDataAdapter.findByContentUri(uri);
+ mDataAdapter.removeAt(failedIndex);
+ }
+
+ @Override
public void onSessionThumbnailUpdate(Bitmap bitmap) {
}
import android.provider.MediaStore.Images.ImageColumns;
import android.provider.MediaStore.MediaColumns;
import android.util.LruCache;
+
import com.android.camera.data.FilmstripItemData;
import com.android.camera.debug.Log;
import com.android.camera.exif.ExifInterface;
import com.android.camera.util.Size;
import com.google.common.base.Optional;
-import javax.annotation.Nonnull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
+
public class Storage {
public static final String DCIM =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString();
public static final File DIRECTORY_FILE = new File(DIRECTORY);
public static final String JPEG_POSTFIX = ".jpg";
public static final String GIF_POSTFIX = ".gif";
- // Match the code in MediaProvider.computeBucketValues().
- public static final String BUCKET_ID =
- String.valueOf(DIRECTORY.toLowerCase().hashCode());
public static final long UNAVAILABLE = -1L;
public static final long PREPARING = -2L;
public static final long UNKNOWN_SIZE = -3L;
}
/**
- * Returns the current version of a placeholder for a session. The version will increment
- * with each call to replacePlaceholder.
- *
- * @param uri the session uri to look up.
- * @return the current version int.
+ * @return Whether a placeholder size for the session with the given URI
+ * exists.
*/
- public static int getPlaceholderVersionForSession(Uri uri) {
- return sSessionsToPlaceholderVersions.get(uri);
+ public static boolean containsPlaceholderSize(Uri uri) {
+ return sSessionsToSizes.containsKey(uri);
}
/**
}
@Override
+ public void onSessionCanceled(Uri mediaUri) {
+ }
+
+ @Override
public void onSessionProgress(Uri sessionUri, int progress) {
}
package com.android.camera.captureintent.state;
-import com.google.common.base.Optional;
+import android.graphics.Bitmap;
+import android.net.Uri;
import com.android.camera.async.RefCountBase;
import com.android.camera.captureintent.CaptureIntentConfig;
import com.android.camera.captureintent.PictureDecoder;
-import com.android.camera.captureintent.resource.ResourceCaptureTools;
-import com.android.camera.captureintent.resource.ResourceConstructed;
-import com.android.camera.captureintent.stateful.EventHandler;
import com.android.camera.captureintent.event.EventOnTextureViewLayoutChanged;
import com.android.camera.captureintent.event.EventPause;
import com.android.camera.captureintent.event.EventPictureCompressed;
import com.android.camera.captureintent.event.EventTapOnCancelIntentButton;
import com.android.camera.captureintent.event.EventTapOnConfirmPhotoButton;
import com.android.camera.captureintent.event.EventTapOnRetakePhotoButton;
+import com.android.camera.captureintent.resource.ResourceCaptureTools;
+import com.android.camera.captureintent.resource.ResourceConstructed;
+import com.android.camera.captureintent.stateful.EventHandler;
import com.android.camera.captureintent.stateful.State;
import com.android.camera.captureintent.stateful.StateImpl;
import com.android.camera.debug.Log;
import com.android.camera.session.CaptureSessionManager;
-
-import android.graphics.Bitmap;
-import android.net.Uri;
+import com.google.common.base.Optional;
/**
* A state that shows the taken picture for review. The Cancel, Done or
}
@Override
+ public void onSessionCanceled(Uri mediaUri) {
+ }
+
+ @Override
public void onSessionProgress(Uri sessionUri, int progress) {
}
import android.widget.ImageView;
import com.android.camera.Storage;
+import com.android.camera.debug.Log;
import com.android.camera.util.Size;
import com.android.camera2.R;
import com.bumptech.glide.Glide;
private final Context mContext;
private final Uri mUri;
- public SessionItem(Context context, Uri uri) {
+ /**
+ * Creates a new session from the given URI.
+ * @param context valid android application context.
+ * @param uri the URI of the session.
+ * @return If the session was found, a new SessionItem is returned.
+ */
+ public static Optional<SessionItem> create(Context context, Uri uri) {
+ if (!Storage.containsPlaceholderSize(uri)) {
+ return Optional.absent();
+ }
+ Size dimension = getSessionSize(uri);
+ if (dimension == null) {
+ return Optional.absent();
+ }
+ return Optional.of(new SessionItem(context, uri, dimension));
+ }
+
+ protected SessionItem(Context context, Uri uri, Size dimension) {
mContext = context;
mUri = uri;
mMetaData.setLoaded(true);
Date creationDate = new Date();
- Size dimension = getSessionSize(uri);
-
mData = new FilmstripItemData.Builder(uri)
.withCreationDate(creationDate)
.withLastModifiedDate(creationDate)
mAttributes = new FilmstripItemAttributes.Builder()
.with(FilmstripItemAttributes.Attributes.IS_RENDERING)
.build();
-
}
- private Size getSessionSize(Uri uri) {
+ private static Size getSessionSize(Uri uri) {
Point size = Storage.getSizeForSession(uri);
- return new Size(size.x, size.y);
+ if (size == null) {
+ return null;
+ }
+ return new Size(size);
}
@Override
@Override
public FilmstripItem refresh() {
Size dimension = getSessionSize(mData.getUri());
+ if (dimension == null) {
+ Log.w(TAG, "Cannot refresh item, session does not exist.");
+ return this;
+ }
mData = FilmstripItemData.Builder.from(mData)
.withDimensions(dimension)
private final SessionNotifier mSessionNotifier;
/** Used for adding/removing/updating placeholders for in-progress sessions. */
private final PlaceholderManager mPlaceholderManager;
+ /** A place holder for this capture session. */
+ private PlaceholderManager.Placeholder mPlaceHolder;
/** Used to store images on disk and to add them to the media store. */
private final MediaSaver mMediaSaver;
/** The title of the item being processed. */
private int mProgressPercent = 0;
/** A message ID for the current progress state. */
private int mProgressMessageId;
- /** A place holder for this capture session. */
- private PlaceholderManager.Session mPlaceHolderSession;
private Uri mContentUri;
/** Whether this image was finished. */
private volatile boolean mIsFinished;
@Override
public void updateThumbnail(Bitmap bitmap) {
- mPlaceholderManager.replacePlaceholder(mPlaceHolderSession, bitmap);
+ mPlaceholderManager.replacePlaceholder(mPlaceHolder, bitmap);
mSessionNotifier.notifySessionUpdated(mUri);
}
}
mProgressMessageId = -1;
- mPlaceHolderSession = mPlaceholderManager.insertEmptyPlaceholder(mTitle, pictureSize,
+ mPlaceHolder = mPlaceholderManager.insertEmptyPlaceholder(mTitle, pictureSize,
mSessionStartMillis);
- mUri = mPlaceHolderSession.outputUri;
+ mUri = mPlaceHolder.outputUri;
mSessionManager.putSession(mUri, this);
mSessionNotifier.notifyTaskQueued(mUri);
}
}
mProgressMessageId = progressMessageId;
- mPlaceHolderSession = mPlaceholderManager.insertPlaceholder(mTitle, placeholder,
+ mPlaceHolder = mPlaceholderManager.insertPlaceholder(mTitle, placeholder,
mSessionStartMillis);
- mUri = mPlaceHolderSession.outputUri;
+ mUri = mPlaceHolder.outputUri;
mSessionManager.putSession(mUri, this);
mSessionNotifier.notifyTaskQueued(mUri);
onCaptureIndicatorUpdate(placeholder, 0);
}
mProgressMessageId = progressMessageId;
- mPlaceHolderSession = mPlaceholderManager.insertPlaceholder(mTitle, placeholder,
+ mPlaceHolder = mPlaceholderManager.insertPlaceholder(mTitle, placeholder,
mSessionStartMillis);
- mUri = mPlaceHolderSession.outputUri;
+ mUri = mPlaceHolder.outputUri;
mSessionManager.putSession(mUri, this);
mSessionNotifier.notifyTaskQueued(mUri);
Optional<Bitmap> placeholderBitmap =
- mPlaceholderManager.getPlaceholder(mPlaceHolderSession);
+ mPlaceholderManager.getPlaceholder(mPlaceHolder);
if (placeholderBitmap.isPresent()) {
onCaptureIndicatorUpdate(placeholderBitmap.get(), 0);
}
public synchronized void startSession(Uri uri, int progressMessageId) {
mUri = uri;
mProgressMessageId = progressMessageId;
- mPlaceHolderSession = mPlaceholderManager.convertToPlaceholder(uri);
+ mPlaceHolder = mPlaceholderManager.convertToPlaceholder(uri);
mSessionManager.putSession(mUri, this);
mSessionNotifier.notifyTaskQueued(mUri);
public synchronized void cancel() {
if (isStarted()) {
mSessionManager.removeSession(mUri);
+ mSessionNotifier.notifyTaskCanceled(mUri);
+ }
+
+ if (mPlaceHolder != null) {
+ mPlaceholderManager.removePlaceholder(mPlaceHolder);
+ mPlaceHolder = null;
}
}
final SettableFuture<Optional<Uri>> futureResult = SettableFuture.create();
mIsFinished = true;
- if (mPlaceHolderSession == null) {
+ if (mPlaceHolder == null) {
mMediaSaver.addImage(
data, mTitle, mSessionStartMillis, mLocation, width, height,
orientation, exif, new MediaSaver.OnMediaSavedListener() {
});
} else {
try {
- mContentUri = mPlaceholderManager.finishPlaceholder(mPlaceHolderSession, mLocation,
+ mContentUri = mPlaceholderManager.finishPlaceholder(mPlaceHolder, mLocation,
orientation, exif, data, width, height, FilmstripItemData.MIME_TYPE_JPEG);
mSessionNotifier.notifyTaskDone(mUri);
futureResult.set(Optional.fromNullable(mUri));
@Override
public void finish() {
- if (mPlaceHolderSession == null) {
+ if (mPlaceHolder == null) {
throw new IllegalStateException(
"Cannot call finish without calling startSession first.");
}
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap placeholder = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length,
options);
- mPlaceholderManager.replacePlaceholder(mPlaceHolderSession, placeholder);
+ mPlaceholderManager.replacePlaceholder(mPlaceHolder, placeholder);
mSessionNotifier.notifySessionUpdated(mUri);
}
});
@Override
public void finishWithFailure(int failureMessageId, boolean removeFromFilmstrip) {
- if (mPlaceHolderSession == null) {
+ if (mPlaceHolder == null) {
throw new IllegalStateException(
"Cannot call finish without calling startSession first.");
}
@Override
public void finalizeSession() {
- mPlaceholderManager.removePlaceholder(mPlaceHolderSession);
+ mPlaceholderManager.removePlaceholder(mPlaceHolder);
}
private void onCaptureIndicatorUpdate(Bitmap indicator, int rotationDegrees) {
/** Called when the session with the given Uri failed processing. */
public void onSessionFailed(Uri mediaUri, int failureMessageId, boolean removeFromFilmstrip);
+ /** Called when the session with the given Uri was canceled. */
+ public void onSessionCanceled(Uri mediaUri);
+
/** Called when the session with the given Uri has progressed. */
public void onSessionProgress(Uri mediaUri, int progress);
});
}
+ @Override
+ public void notifyTaskCanceled(final Uri uri) {
+ mMainHandler.execute(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mTaskListeners) {
+ for (SessionListener listener : mTaskListeners) {
+ listener.onSessionCanceled(uri);
+ }
+ }
+ finalizeSession(uri);
+ }
+ });
+ }
+
/**
* Notifies all task listeners that the task with the given URI has
* progressed to the given state.
private final Context mContext;
- public static class Session {
+ public static class Placeholder {
final String outputTitle;
final Uri outputUri;
final long time;
- Session(String title, Uri uri, long timestamp) {
+ Placeholder(String title, Uri uri, long timestamp) {
outputTitle = title;
outputUri = uri;
time = timestamp;
* within the filmstrip). Millis since epoch.
* @return A session instance representing the new placeholder.
*/
- public Session insertEmptyPlaceholder(String title, Size size, long timestamp) {
+ public Placeholder insertEmptyPlaceholder(String title, Size size, long timestamp) {
Uri uri = Storage.addEmptyPlaceholder(size);
- return new Session(title, uri, timestamp);
+ return new Placeholder(title, uri, timestamp);
}
/**
* within the filmstrip). Millis since epoch.
* @return A session instance representing the new placeholder.
*/
- public Session insertPlaceholder(String title, Bitmap placeholder, long timestamp) {
+ public Placeholder insertPlaceholder(String title, Bitmap placeholder, long timestamp) {
if (title == null || placeholder == null) {
throw new IllegalArgumentException("Null argument passed to insertPlaceholder");
}
if (uri == null) {
return null;
}
- return new Session(title, uri, timestamp);
+ return new Placeholder(title, uri, timestamp);
}
- public Session insertPlaceholder(String title, byte[] placeholder, long timestamp) {
+ public Placeholder insertPlaceholder(String title, byte[] placeholder, long timestamp) {
if (title == null || placeholder == null) {
throw new IllegalArgumentException("Null argument passed to insertPlaceholder");
}
* @return A session that can be used to update the progress of the new
* session.
*/
- public Session convertToPlaceholder(Uri uri) {
+ public Placeholder convertToPlaceholder(Uri uri) {
return createSessionFromUri(uri);
}
/**
* This converts the placeholder in to a real media item
*
- * @param session the session that is being finished.
+ * @param placeholder the session that is being finished.
* @param location the location of the image
* @param orientation the orientation of the image
* @param exif the exif of the image
* @param mimeType the mime type of the image
* @return The content URI of the new media item.
*/
- public Uri finishPlaceholder(Session session, Location location, int orientation,
+ public Uri finishPlaceholder(Placeholder placeholder, Location location, int orientation,
ExifInterface exif, byte[] jpeg, int width, int height, String mimeType) throws IOException {
- Uri resultUri = Storage.updateImage(session.outputUri, mContext.getContentResolver(),
- session.outputTitle, session.time, location, orientation, exif, jpeg, width,
+ Uri resultUri = Storage.updateImage(placeholder.outputUri, mContext.getContentResolver(),
+ placeholder.outputTitle, placeholder.time, location, orientation, exif, jpeg, width,
height, mimeType);
CameraUtil.broadcastNewPicture(mContext, resultUri);
return resultUri;
* @param session the session to update
* @param placeholder the placeholder bitmap
*/
- public void replacePlaceholder(Session session, Bitmap placeholder) {
+ public void replacePlaceholder(Placeholder session, Bitmap placeholder) {
Storage.replacePlaceholder(session.outputUri, placeholder);
CameraUtil.broadcastNewPicture(mContext, session.outputUri);
}
/**
* Retrieve the placeholder for a given session.
*
- * @param session the session for which to retrieve bitmap placeholder
+ * @param placeholder the session for which to retrieve bitmap placeholder
*/
- public Optional<Bitmap> getPlaceholder(Session session) {
- return Storage.getPlaceholderForSession(session.outputUri);
+ public Optional<Bitmap> getPlaceholder(Placeholder placeholder) {
+ return Storage.getPlaceholderForSession(placeholder.outputUri);
}
/**
* Remove the placeholder for a given session.
*
- * @param session the session for which to remove the bitmap placeholder.
+ * @param placeholder the session for which to remove the bitmap placeholder.
*/
- public void removePlaceholder(Session session) {
- Storage.removePlaceholder(session.outputUri);
+ public void removePlaceholder(Placeholder placeholder) {
+ Storage.removePlaceholder(placeholder.outputUri);
}
/**
* <p>
* TODO: Make sure this works with types other than images when needed.
*/
- private Session createSessionFromUri(Uri uri) {
+ private Placeholder createSessionFromUri(Uri uri) {
ContentResolver resolver = mContext.getContentResolver();
Cursor cursor = resolver.query(uri,
name = name.substring(0, name.length() - Storage.JPEG_POSTFIX.length());
}
- return new Session(name, uri, date);
+ return new Placeholder(name, uri, date);
}
}
/** A task has failed to process. */
public void notifyTaskFailed(final Uri uri, final int failureMessageId,
- boolean removeFromFilmstrip);
+ boolean removeFromFilmstrip);
+
+ /** A task has been canceled. */
+ public void notifyTaskCanceled(final Uri uri);
/** A task has progressed. */
public void notifyTaskProgress(final Uri uri, final int progressPercent);