Commit 597c1a09 authored by Sascha Haeberling's avatar Sascha Haeberling
Browse files

Support for capture session errors.

  Bug: 13026663

Change-Id: I3713440483aa4732f94aff9eaff2fc34a04c0427
parent 69cb8407
res/drawable-hdpi/ic_error_normal.png

1.12 KB

res/drawable-mdpi/ic_error_normal.png

846 Bytes

res/drawable-xhdpi/ic_error_normal.png

1.46 KB

res/drawable-xxhdpi/ic_error_normal.png

2.03 KB

......@@ -99,6 +99,31 @@
android:contentDescription="@string/delete_button_description" />
</LinearLayout>
<!-- The progress error panel -->
<LinearLayout
android:id="@+id/bottom_progress_error_panel"
android:layout_width="@dimen/filmstrip_bottom_control_layout_size"
android:layout_height="@dimen/filmstrip_bottom_control_button_size"
android:layout_gravity="bottom|center_horizontal"
android:gravity="center"
android:visibility="gone"
android:orientation="horizontal">
<ImageView
android:src="@drawable/ic_error_normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="10dp"
android:scaleType="centerInside"/>
<TextView
android:id="@+id/bottom_progress_error_text"
style="@style/FilmstripBottomProgressText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<!-- The progress bar -->
<LinearLayout
android:id="@+id/bottom_progress_panel"
......
......@@ -384,6 +384,14 @@ public class CameraActivity extends Activity
}
return intent;
}
@Override
public void onProgressErrorClicked() {
LocalData data = getCurrentLocalData();
getServices().getCaptureSessionManager().removeErrorMessage(
data.getContentUri());
updateBottomControlsByData(data);
}
};
private ComboPreferences mPreferences;
......@@ -682,9 +690,14 @@ public class CameraActivity extends Activity
CameraAppUI.BottomPanel controls = mCameraAppUI.getFilmstripBottomControls();
controls.setProgressText(message);
controls.hideControls();
controls.hideProgressError();
controls.showProgress();
}
private void showProcessError(CharSequence message) {
mCameraAppUI.getFilmstripBottomControls().showProgressError(message);
}
private void updateSessionProgress(int progress) {
mCameraAppUI.getFilmstripBottomControls().setProgress(progress);
}
......@@ -737,23 +750,23 @@ public class CameraActivity extends Activity
@Override
public void onSessionQueued(final Uri uri) {
notifyNewMedia(uri);
int dataID = mDataAdapter.findDataByContentUri(uri);
if (dataID != -1) {
int dataId = mDataAdapter.findDataByContentUri(uri);
if (dataId != -1) {
// Don't allow special UI actions (swipe to
// delete, for example) on in-progress data.
LocalData d = mDataAdapter.getLocalData(dataID);
LocalData d = mDataAdapter.getLocalData(dataId);
InProgressDataWrapper newData = new InProgressDataWrapper(d);
mDataAdapter.updateData(dataID, newData);
mDataAdapter.updateData(dataId, newData);
}
}
@Override
public void onSessionDone(final Uri uri) {
Log.v(TAG, "onSessionDone:" + uri);
int doneID = mDataAdapter.findDataByContentUri(uri);
int doneId = mDataAdapter.findDataByContentUri(uri);
int currentDataId = mFilmstripController.getCurrentId();
if (currentDataId == doneID) {
if (currentDataId == doneId) {
hideSessionProgress();
updateSessionProgress(0);
}
......@@ -780,6 +793,20 @@ public class CameraActivity extends Activity
public void onSessionUpdated(Uri uri) {
mDataAdapter.refresh(uri, /* isInProgress */true);
}
@Override
public void onSessionFailed(Uri uri, CharSequence reason) {
Log.v(TAG, "onSessionFailed:" + uri);
int failedDataId = mDataAdapter.findDataByContentUri(uri);
int currentDataId = mFilmstripController.getCurrentId();
if (currentDataId == failedDataId) {
updateSessionProgress(0);
showProcessError(reason);
}
mDataAdapter.refresh(uri, /* isInProgress */false);
}
};
@Override
......@@ -2052,15 +2079,21 @@ public class CameraActivity extends Activity
Uri contentUri = currentData.getContentUri();
CaptureSessionManager sessionManager = getServices()
.getCaptureSessionManager();
int sessionProgress = sessionManager.getSessionProgress(contentUri);
if (sessionProgress < 0) {
hideSessionProgress();
if (sessionManager.hasErrorMessage(contentUri)) {
showProcessError(sessionManager.getErrorMesage(contentUri));
} else {
CharSequence progressMessage = sessionManager
.getSessionProgressMessage(contentUri);
showSessionProgress(progressMessage);
updateSessionProgress(sessionProgress);
filmstripBottomPanel.hideProgressError();
int sessionProgress = sessionManager.getSessionProgress(contentUri);
if (sessionProgress < 0) {
hideSessionProgress();
} else {
CharSequence progressMessage = sessionManager
.getSessionProgressMessage(contentUri);
showSessionProgress(progressMessage);
updateSessionProgress(sessionProgress);
}
}
/* View button */
......
......@@ -161,6 +161,16 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
*/
void setProgress(int progress);
/**
* Replaces the progress UI with an error message.
*/
void showProgressError(CharSequence message);
/**
* Hide the progress error message.
*/
void hideProgressError();
/**
* Shows the progress.
*/
......@@ -211,6 +221,11 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener,
* Called when the "share" button is pressed.
*/
public void onShare();
/**
* Called when the progress error message is clicked.
*/
public void onProgressErrorClicked();
}
}
......
......@@ -17,12 +17,12 @@
package com.android.camera.app;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.android.camera.util.CameraUtil;
import com.android.camera2.R;
/**
......@@ -34,7 +34,7 @@ class FilmstripBottomPanel implements CameraAppUI.BottomPanel {
private final AppController mController;
private final ViewGroup mLayout;
private Listener mListener;
private View mControlLayout;
private final View mControlLayout;
private ImageButton mEditButton;
private ImageButton mViewButton;
private ImageButton mDeleteButton;
......@@ -42,6 +42,8 @@ class FilmstripBottomPanel implements CameraAppUI.BottomPanel {
private final View mMiddleFiller;
private View mProgressLayout;
private TextView mProgressText;
private View mProgressErrorLayout;
private TextView mProgressErrorText;
private ProgressBar mProgressBar;
private boolean mTinyPlanetEnabled;
......@@ -133,9 +135,23 @@ class FilmstripBottomPanel implements CameraAppUI.BottomPanel {
mProgressBar.setProgress(progress);
}
@Override
public void showProgressError(CharSequence message) {
hideControls();
hideProgress();
mProgressErrorLayout.setVisibility(View.VISIBLE);
mProgressErrorText.setText(message);
}
@Override
public void hideProgressError() {
mProgressErrorLayout.setVisibility(View.INVISIBLE);
}
@Override
public void showProgress() {
mProgressLayout.setVisibility(View.VISIBLE);
hideProgressError();
}
@Override
......@@ -222,6 +238,16 @@ class FilmstripBottomPanel implements CameraAppUI.BottomPanel {
mProgressBar = (ProgressBar) mLayout.findViewById(R.id.bottom_session_progress_bar);
mProgressBar.setMax(100);
mProgressLayout.setVisibility(View.INVISIBLE);
mProgressErrorText = (TextView) mLayout.findViewById(R.id.bottom_progress_error_text);
mProgressErrorLayout = mLayout.findViewById(R.id.bottom_progress_error_panel);
mProgressErrorLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
mListener.onProgressErrorClicked();
}
}
});
}
/**
......
......@@ -100,6 +100,11 @@ public interface CaptureSession {
*/
public void finish();
/**
* Finish the session and indicate it failed.
*/
public void finishWithFailure(CharSequence reason);
/**
* Returns the path to the final output of this session. This is only
* available after startSession has been called.
......
......@@ -48,6 +48,9 @@ public interface CaptureSessionManager {
/** Called when the session with the given Uri finished. */
public void onSessionDone(Uri mediaUri);
/** Called when the session with the given Uri failed processing. */
public void onSessionFailed(Uri mediaUri, CharSequence reason);
/** Called when the session with the given Uri has progressed. */
public void onSessionProgress(Uri mediaUri, int progress);
}
......@@ -75,7 +78,7 @@ public interface CaptureSessionManager {
* @param loc the capture location.
* @param width the width of the captured image.
* @param height the height of the captured image.
* @param orientation the orientatio of the captured image.
* @param orientation the orientation of the captured image.
* @param exif the EXIF data of the captured image.
* @param listener called when saving is complete.
*/
......@@ -115,9 +118,25 @@ public interface CaptureSessionManager {
public CharSequence getSessionProgressMessage(Uri uri);
/**
* Gets the directory to be used for temporary data.
*
* See {@link SessionStorageManager#getSessionDirectory(String)}
* Gets the directory to be used for temporary data. See
* {@link SessionStorageManager#getSessionDirectory(String)}
*/
public File getSessionDirectory(String subDirectory) throws IOException;
/**
* @return Whether the session with the given URI exists and has an error
* message.
*/
public boolean hasErrorMessage(Uri uri);
/**
* @return If existant, returns the error message for the session with the
* given URI.
*/
public CharSequence getErrorMesage(Uri uri);
/**
* Removes any existing error messages for the session with the given URI.
*/
public void removeErrorMessage(Uri uri);
}
......@@ -198,6 +198,23 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
PlaceholderManager.PLACEHOLDER_MIME_TYPE, /* finalImage */ false);
notifySessionUpdate(mPlaceHolderSession.outputUri);
}
@Override
public void finishWithFailure(CharSequence reason) {
if (mPlaceHolderSession == null) {
throw new IllegalStateException(
"Cannot call finish without calling startSession first.");
}
mProgressMessage = reason;
// Change mime type of session so it's not marked as in progress anymore.
mPlaceholderManager.replacePlaceHolder(mPlaceHolderSession, mLocation,
LocalData.MIME_TYPE_JPEG, /* finalImage */false);
mNotificationManager.notifyCompletion(mNotificationId);
removeSession(mUri.toString());
mFailedSessionMessages.put(mPlaceHolderSession.outputUri, reason);
notifyTaskFailed(mPlaceHolderSession.outputUri, reason);
}
}
private final MediaSaver mMediaSaver;
......@@ -206,6 +223,10 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
private final SessionStorageManager mSessionStorageManager;
private final ContentResolver mContentResolver;
/** Failed session messages. Uri -> message. */
private final HashMap<Uri, CharSequence> mFailedSessionMessages =
new HashMap<Uri, CharSequence>();
/**
* We use this to fire events to the session listeners from the main thread.
*/
......@@ -335,6 +356,23 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
});
}
/**
* Notifies all task listeners that the task with the given URI has been
* failed to process.
*/
private void notifyTaskFailed(final Uri uri, final CharSequence reason) {
mMainHandler.post(new Runnable() {
@Override
public void run() {
synchronized (mTaskListeners) {
for (SessionListener listener : mTaskListeners) {
listener.onSessionFailed(uri, reason);
}
}
}
});
}
/**
* Notifies all task listeners that the task with the given URI has
* progressed to the given state.
......@@ -368,4 +406,19 @@ public class CaptureSessionManagerImpl implements CaptureSessionManager {
}
});
}
@Override
public boolean hasErrorMessage(Uri uri) {
return mFailedSessionMessages.containsKey(uri);
}
@Override
public CharSequence getErrorMesage(Uri uri) {
return mFailedSessionMessages.get(uri);
}
@Override
public void removeErrorMessage(Uri uri) {
mFailedSessionMessages.remove(uri);
}
}
......@@ -21,8 +21,8 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
......@@ -329,8 +329,8 @@ public class BottomBar extends FrameLayout
mRect.set(
0.0f,
0.0f,
(float) width,
(float) height);
width,
height);
mRectPath.reset();
mRectPath.addRect(mRect, Path.Direction.CW);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment