summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/camera/Camera.java6
-rw-r--r--src/com/android/camera/CropImage.java5
-rw-r--r--src/com/android/camera/ImageManager.java104
-rw-r--r--src/com/android/camera/gallery/BaseCancelable.java164
-rw-r--r--src/com/android/camera/gallery/BaseImage.java67
-rw-r--r--src/com/android/camera/gallery/Cancelable.java52
-rw-r--r--src/com/android/camera/gallery/Image.java27
-rw-r--r--src/com/android/camera/gallery/ThreadSafeOutputStream.java67
-rw-r--r--tests/src/com/android/camera/gallery/BaseCancelableUnitTests.java232
9 files changed, 62 insertions, 662 deletions
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 0d56d5a..2755f34 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -64,7 +64,6 @@ import android.view.MenuItem.OnMenuItemClickListener;
import android.widget.ImageView;
import android.widget.ZoomButtonsController;
-import com.android.camera.gallery.Cancelable;
import com.android.camera.gallery.IImage;
import com.android.camera.gallery.IImageList;
@@ -687,7 +686,6 @@ public class Camera extends Activity implements View.OnClickListener,
private boolean mCancel = false;
private Uri mLastContentUri;
- private Cancelable<Void> mAddImageCancelable;
Bitmap mCaptureOnlyBitmap;
@@ -709,11 +707,9 @@ public class Camera extends Activity implements View.OnClickListener,
mCancel = true;
}
if (!mCancel) {
- mAddImageCancelable = ImageManager.storeImage(
+ ImageManager.storeImage(
mLastContentUri, mContentResolver,
0, null, data);
- mAddImageCancelable.get();
- mAddImageCancelable = null;
ImageManager.setImageSize(mContentResolver, mLastContentUri,
new File(ImageManager.CAMERA_IMAGE_BUCKET_NAME,
name).length());
diff --git a/src/com/android/camera/CropImage.java b/src/com/android/camera/CropImage.java
index aa4ec67..91608d2 100644
--- a/src/com/android/camera/CropImage.java
+++ b/src/com/android/camera/CropImage.java
@@ -16,7 +16,6 @@
package com.android.camera;
-import com.android.camera.gallery.Cancelable;
import com.android.camera.gallery.IImage;
import com.android.camera.gallery.IImageList;
@@ -378,15 +377,13 @@ public class CropImage extends MonitoredActivity {
directory.toString(),
fileName + "-" + x + ".jpg");
- Cancelable<Void> cancelable =
- ImageManager.storeImage(
+ ImageManager.storeImage(
newUri,
mContentResolver,
0, // TODO fix this orientation
croppedImage,
null);
- cancelable.get();
setResult(RESULT_OK, new Intent()
.setAction(newUri.toString())
.putExtras(extras));
diff --git a/src/com/android/camera/ImageManager.java b/src/com/android/camera/ImageManager.java
index 2148e73..0b46da5 100644
--- a/src/com/android/camera/ImageManager.java
+++ b/src/com/android/camera/ImageManager.java
@@ -16,9 +16,7 @@
package com.android.camera;
-import com.android.camera.gallery.BaseCancelable;
import com.android.camera.gallery.BaseImageList;
-import com.android.camera.gallery.Cancelable;
import com.android.camera.gallery.DrmImageList;
import com.android.camera.gallery.IImage;
import com.android.camera.gallery.IImageList;
@@ -50,7 +48,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.concurrent.ExecutionException;
/**
* ImageManager is used to retrieve and store images
@@ -245,77 +242,54 @@ public class ImageManager {
return cr.insert(STORAGE_URI, values);
}
- private static class AddImageCancelable extends BaseCancelable<Void> {
- private final Uri mUri;
- private final ContentResolver mCr;
- private final int mOrientation;
- private final Bitmap mSource;
- private final byte [] mJpegData;
-
- public AddImageCancelable(Uri uri, ContentResolver cr,
- int orientation, Bitmap source, byte[] jpegData) {
- if (source == null && jpegData == null || uri == null) {
- throw new IllegalArgumentException("source cannot be null");
- }
- mUri = uri;
- mCr = cr;
- mOrientation = orientation;
- mSource = source;
- mJpegData = jpegData;
+ public static void storeImage(
+ Uri uri, ContentResolver cr, int orientation,
+ Bitmap source, byte [] jpegData) {
+
+ if (source == null && jpegData == null || uri == null) {
+ throw new IllegalArgumentException("source cannot be null");
}
- @Override
- protected Void execute() throws InterruptedException,
- ExecutionException {
- boolean complete = false;
+ boolean complete = false;
+ try {
+ long id = ContentUris.parseId(uri);
+ BaseImageList il = new ImageList(
+ cr, STORAGE_URI, THUMB_URI, SORT_ASCENDING, null);
+
+ // TODO: Redesign the process of adding new images. We should
+ // create an <code>IImage</code> in "ImageManager.addImage"
+ // and pass the image object to here.
+ Image image = new Image(il, cr, id, 0, il.contentUri(id), null,
+ 0, null, 0, null, null, 0);
+ String[] projection = new String[] {
+ ImageColumns._ID,
+ ImageColumns.MINI_THUMB_MAGIC, ImageColumns.DATA};
+ Cursor c = cr.query(uri, projection, null, null, null);
+ String filepath;
try {
- long id = ContentUris.parseId(mUri);
- BaseImageList il = new ImageList(
- mCr, STORAGE_URI, THUMB_URI, SORT_ASCENDING, null);
-
- // TODO: Redesign the process of adding new images. We should
- // create an <code>IImage</code> in "ImageManager.addImage"
- // and pass the image object to here.
- Image image = new Image(il, mCr, id, 0, il.contentUri(id), null,
- 0, null, 0, null, null, 0);
- String[] projection = new String[] {
- ImageColumns._ID,
- ImageColumns.MINI_THUMB_MAGIC, ImageColumns.DATA};
- Cursor c = mCr.query(mUri, projection, null, null, null);
- String filepath;
- try {
- c.moveToPosition(0);
- filepath = c.getString(2);
- } finally {
- c.close();
- }
- runSubTask(image.saveImageContents(
- mSource, mJpegData, mOrientation, true, filepath));
-
- ContentValues values = new ContentValues();
- values.put(ImageColumns.MINI_THUMB_MAGIC, 0);
- mCr.update(mUri, values, null, null);
- complete = true;
- return null;
+ c.moveToPosition(0);
+ filepath = c.getString(2);
} finally {
- if (!complete) {
- try {
- mCr.delete(mUri, null, null);
- } catch (Throwable t) {
- // ignore it while clean up.
- }
+ c.close();
+ }
+ image.saveImageContents(
+ source, jpegData, orientation, true, filepath);
+
+ ContentValues values = new ContentValues();
+ values.put(ImageColumns.MINI_THUMB_MAGIC, 0);
+ cr.update(uri, values, null, null);
+ complete = true;
+ } finally {
+ if (!complete) {
+ try {
+ cr.delete(uri, null, null);
+ } catch (Throwable t) {
+ // ignore it while clean up.
}
}
}
}
- public static Cancelable<Void> storeImage(
- Uri uri, ContentResolver cr, int orientation,
- Bitmap source, byte [] jpegData) {
- return new AddImageCancelable(
- uri, cr, orientation, source, jpegData);
- }
-
// This is the factory function to create an image list.
public static IImageList makeImageList(ContentResolver cr,
ImageListParam param) {
diff --git a/src/com/android/camera/gallery/BaseCancelable.java b/src/com/android/camera/gallery/BaseCancelable.java
deleted file mode 100644
index d5566a8..0000000
--- a/src/com/android/camera/gallery/BaseCancelable.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera.gallery;
-
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-
-/**
- * An abstract class for the interface <code>Cancelable</code>. Subclass can
- * simply override the <code>execute()</code> function to provide an
- * implementation of <code>Cancelable</code>.
- */
-public abstract class BaseCancelable<T> implements Cancelable<T> {
-
- /**
- * The state of the task, possible transitions are:
- * <pre>
- * INITIAL -> CANCELED
- * EXECUTING -> COMPLETE, CANCELING, ERROR, CANCELED
- * CANCELING -> CANCELED
- * </pre>
- * When the task stop, it must be end with one of the following states:
- * COMPLETE, CANCELED, or ERROR;
- */
- private static final int STATE_INITIAL = (1 << 0);
- private static final int STATE_EXECUTING = (1 << 1);
- private static final int STATE_CANCELING = (1 << 2);
- private static final int STATE_CANCELED = (1 << 3);
- private static final int STATE_ERROR = (1 << 4);
- private static final int STATE_COMPLETE = (1 << 5);
-
- private int mState = STATE_INITIAL;
-
- private Throwable mError;
- private T mResult;
- private Cancelable<?> mCurrentTask;
-
- protected abstract T execute() throws Exception;
-
- /**
- * Frees the result (which is not null) when the task has been canceled.
- */
- protected void freeCanceledResult(T result) {
- // Do nothing by default;
- }
-
- private boolean isInStates(int states) {
- return (states & mState) != 0;
- }
-
- private T handleTerminalStates() throws ExecutionException {
- if (mState == STATE_CANCELED) {
- throw new CancellationException();
- }
- if (mState == STATE_ERROR) {
- throw new ExecutionException(mError);
- }
- if (mState == STATE_COMPLETE) return mResult;
- throw new IllegalStateException();
- }
-
- public synchronized void await() throws InterruptedException {
- while (!isInStates(STATE_COMPLETE | STATE_CANCELED | STATE_ERROR)) {
- wait();
- }
- }
-
- public final T get() throws InterruptedException, ExecutionException {
- synchronized (this) {
- if (mState != STATE_INITIAL) {
- await();
- return handleTerminalStates();
- }
- mState = STATE_EXECUTING;
- }
- try {
- mResult = execute();
- } catch (CancellationException e) {
- mState = STATE_CANCELED;
- } catch (InterruptedException e) {
- mState = STATE_CANCELED;
- } catch (Throwable error) {
- synchronized (this) {
- if (mState != STATE_CANCELING) {
- mError = error;
- mState = STATE_ERROR;
- }
- }
- }
- synchronized (this) {
- if (mState == STATE_CANCELING) mState = STATE_CANCELED;
- if (mState == STATE_EXECUTING) mState = STATE_COMPLETE;
- notifyAll();
- if (mState == STATE_CANCELED && mResult != null) {
- freeCanceledResult(mResult);
- }
- return handleTerminalStates();
- }
- }
-
- /**
- * Requests the task to be canceled.
- *
- * @return true if the task is running and has not been canceled; false
- * otherwise
- */
-
- public synchronized boolean requestCancel() {
- if (mState == STATE_INITIAL) {
- mState = STATE_CANCELED;
- notifyAll();
- return false;
- }
- if (mState == STATE_EXECUTING) {
- if (mCurrentTask != null) mCurrentTask.requestCancel();
- mState = STATE_CANCELING;
- return true;
- }
- return false;
- }
-
- /**
- * Runs a <code>Cancelable</code> subtask. This method is helpful, if the
- * task can be composed of several cancelable tasks. By using this function,
- * it will pass <code>requestCancel</code> message to those subtasks.
- *
- * @param <T> the return type of the sub task
- * @param cancelable the sub task
- * @return the result of the subtask
- */
- protected <T> T runSubTask(Cancelable<T> cancelable)
- throws InterruptedException, ExecutionException {
- synchronized (this) {
- if (mCurrentTask != null) {
- throw new IllegalStateException(
- "cannot two subtasks at the same time");
- }
- if (mState == STATE_CANCELING) throw new CancellationException();
- mCurrentTask = cancelable;
- }
- try {
- return cancelable.get();
- } finally {
- synchronized (this) {
- mCurrentTask = null;
- }
- }
- }
-
-}
diff --git a/src/com/android/camera/gallery/BaseImage.java b/src/com/android/camera/gallery/BaseImage.java
index c80cd6c..d3e6769 100644
--- a/src/com/android/camera/gallery/BaseImage.java
+++ b/src/com/android/camera/gallery/BaseImage.java
@@ -82,54 +82,6 @@ public abstract class BaseImage implements IImage {
protected abstract Bitmap.CompressFormat compressionType();
- private class CompressImageToFile extends BaseCancelable<Boolean> {
- private ThreadSafeOutputStream mOutputStream = null;
-
- private final Bitmap mBitmap;
- private final Uri mDestinationUri;
- private final byte[] mJpegData;
-
- public CompressImageToFile(Bitmap bitmap, byte[] jpegData, Uri uri) {
- mBitmap = bitmap;
- mDestinationUri = uri;
- mJpegData = jpegData;
- }
-
- @Override
- public boolean requestCancel() {
- if (super.requestCancel()) {
- if (mOutputStream != null) {
- mOutputStream.close();
- }
- return true;
- }
- return false;
- }
-
- @Override
- public Boolean execute() {
- try {
- OutputStream delegate =
- mContentResolver.openOutputStream(mDestinationUri);
- synchronized (this) {
- mOutputStream = new ThreadSafeOutputStream(delegate);
- }
- if (mBitmap != null) {
- mBitmap.compress(compressionType(), 75, mOutputStream);
- } else {
- mOutputStream.write(mJpegData);
- }
- return true;
- } catch (FileNotFoundException ex) {
- return false;
- } catch (IOException ex) {
- return false;
- } finally {
- Util.closeSilently(mOutputStream);
- }
- }
- }
-
/**
* Take a given bitmap and compress it to a file as described
* by the Uri parameter.
@@ -138,9 +90,24 @@ public abstract class BaseImage implements IImage {
* @param uri where to store the bitmap
* @return true if we succeeded
*/
- protected Cancelable<Boolean> compressImageToFile(
+ protected boolean compressImageToFile(
Bitmap bitmap, byte [] jpegData, Uri uri) {
- return new CompressImageToFile(bitmap, jpegData, uri);
+ OutputStream outputStream = null;
+ try {
+ outputStream = mContentResolver.openOutputStream(uri);
+ if (bitmap != null) {
+ bitmap.compress(compressionType(), 75, outputStream);
+ } else {
+ outputStream.write(jpegData);
+ }
+ return true;
+ } catch (FileNotFoundException ex) {
+ return false;
+ } catch (IOException ex) {
+ return false;
+ } finally {
+ Util.closeSilently(outputStream);
+ }
}
public String getDataPath() {
diff --git a/src/com/android/camera/gallery/Cancelable.java b/src/com/android/camera/gallery/Cancelable.java
deleted file mode 100644
index 1fd1672..0000000
--- a/src/com/android/camera/gallery/Cancelable.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera.gallery;
-
-import java.util.concurrent.ExecutionException;
-
-/**
- * The interface for all the tasks that could be canceled.
- */
-public interface Cancelable<T> {
- /*
- * Requests this <code>Cancelable</code> to be canceled. This function will
- * return <code>true</code> if and only if the task is originally running
- * and now begin requested for cancel.
- *
- * If subclass need to do more things to cancel the task. It can override
- * the code like this:
- * <pre>
- * @Override
- * public boolean requestCancel() {
- * if (super.requestCancel()) {
- * // do necessary work to cancel the task
- * return true;
- * }
- * return false;
- * }
- * </pre>
- */
- public boolean requestCancel();
-
- /**
- * Gets the results of this <code>Cancelable</code> task.
- *
- * @throws ExecutionException if exception is thrown during the execution of
- * the task
- */
- public T get() throws InterruptedException, ExecutionException;
-} \ No newline at end of file
diff --git a/src/com/android/camera/gallery/Image.java b/src/com/android/camera/gallery/Image.java
index 3102a7b..0313274 100644
--- a/src/com/android/camera/gallery/Image.java
+++ b/src/com/android/camera/gallery/Image.java
@@ -36,7 +36,6 @@ import android.util.Log;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
-import java.util.concurrent.ExecutionException;
/**
* The class for normal images in gallery.
@@ -105,29 +104,11 @@ public class Image extends BaseImage implements IImage {
mExifData.put(tag, value);
}
- private class SaveImageContentsCancelable extends BaseCancelable<Void> {
- private final Bitmap mImage;
- private final byte [] mJpegData;
-
- SaveImageContentsCancelable(Bitmap image, byte[] jpegData,
- int orientation, String filePath) {
- mImage = image;
- mJpegData = jpegData;
- }
-
- @Override
- public Void execute() throws InterruptedException, ExecutionException {
- Bitmap thumbnail = null;
- Uri uri = mContainer.contentUri(mId);
- runSubTask(compressImageToFile(mImage, mJpegData, uri));
- return null;
- }
- }
-
- public Cancelable<Void> saveImageContents(Bitmap image, byte [] jpegData,
+ public void saveImageContents(Bitmap image, byte [] jpegData,
int orientation, boolean newFile, String filePath) {
- return new SaveImageContentsCancelable(
- image, jpegData, orientation, filePath);
+ Bitmap thumbnail = null;
+ Uri uri = mContainer.contentUri(mId);
+ compressImageToFile(image, jpegData, uri);
}
private void loadExifData() {
diff --git a/src/com/android/camera/gallery/ThreadSafeOutputStream.java b/src/com/android/camera/gallery/ThreadSafeOutputStream.java
deleted file mode 100644
index 2bd1f96..0000000
--- a/src/com/android/camera/gallery/ThreadSafeOutputStream.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera.gallery;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A wrapper of an <code>OutputStream</code>, so that all the IO operations are
- * thread safe.
- */
-class ThreadSafeOutputStream extends OutputStream {
- private OutputStream mDelegateStream;
- boolean mClosed;
-
- public ThreadSafeOutputStream(OutputStream delegate) {
- mDelegateStream = delegate;
- }
-
- @Override
- public synchronized void close() {
- try {
- mClosed = true;
- mDelegateStream.close();
- } catch (IOException ex) {
- //TODO: this should be thrown out.
- }
- }
-
- @Override
- public synchronized void flush() throws IOException {
- super.flush();
- }
-
- @Override
- public void write(byte[] b, int offset, int length) throws IOException {
- while (length > 0) {
- synchronized (this) {
- if (mClosed) return;
- int writeLength = Math.min(8192, length);
- mDelegateStream.write(b, offset, writeLength);
- offset += writeLength;
- length -= writeLength;
- }
- }
- }
-
- @Override
- public synchronized void write(int oneByte) throws IOException {
- if (mClosed) return;
- mDelegateStream.write(oneByte);
- }
-} \ No newline at end of file
diff --git a/tests/src/com/android/camera/gallery/BaseCancelableUnitTests.java b/tests/src/com/android/camera/gallery/BaseCancelableUnitTests.java
deleted file mode 100644
index 36c0597..0000000
--- a/tests/src/com/android/camera/gallery/BaseCancelableUnitTests.java
+++ /dev/null
@@ -1,232 +0,0 @@
-package com.android.camera.gallery;
-
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-
-public class BaseCancelableUnitTests extends AndroidTestCase {
- private static final String TAG = "BaseCancelableTest";
-
- private static class TestTask extends BaseCancelable<Integer> {
-
- private boolean mDone = false;
- private boolean mCancel = false;
- private boolean mRunning = false;
- private boolean mFireError = false;
-
- @Override
- public synchronized boolean requestCancel() {
- if (super.requestCancel()) {
- mCancel = true;
- notifyAll();
- return true;
- }
- return false;
- }
-
- public synchronized void waitUntilRunning()
- throws InterruptedException {
- while (!mRunning) {
- wait();
- }
- }
-
- @Override
- protected synchronized Integer execute() throws Exception {
- mRunning = true;
- notifyAll();
-
- while (!mDone && !mCancel) {
- wait();
- }
- if (mFireError) throw new IllegalStateException();
- return 0;
- }
-
- public synchronized void completeTask() {
- mDone = true;
- notifyAll();
- }
-
- public synchronized void completeTaskWithException() {
- mDone = true;
- mFireError = true;
- notifyAll();
- }
- }
-
- public void testSimpleFlow() throws Exception {
- TestTask task = new TestTask();
- task.completeTask();
- assertEquals(0, task.get().intValue());
- }
-
- private void assertCancellationException(BaseCancelable<?> task)
- throws Exception {
- try {
- task.get();
- fail("expect a " + CancellationException.class);
- } catch (CancellationException e) {
- // expected
- }
- }
-
- private void assertExecutionException(BaseCancelable<?> task)
- throws Exception {
- try {
- task.get();
- fail("expect a " + ExecutionException.class);
- } catch (ExecutionException e) {
- // expected
- }
- }
-
- public void testCancelInInitialState() throws Exception {
- TestTask task = new TestTask();
- task.requestCancel();
- assertCancellationException(task);
- }
-
- public void testCancelInRunningState() throws Exception {
- final TestTask task = new TestTask();
- new Thread() {
- @Override
- public void run() {
- try {
- task.waitUntilRunning();
- assertTrue(task.requestCancel());
- } catch (InterruptedException e) {
- Log.e(TAG, "interrupt", e);
- }
- }
- }.start();
- assertCancellationException(task);
- }
-
- public void testConcurrentGet() throws Exception {
- final TestTask task = new TestTask();
- new Thread() {
- @Override
- public void run() {
- try {
- assertEquals(0, task.get().intValue());
- } catch (InterruptedException e) {
- Log.e(TAG, "interrupt", e);
- } catch (ExecutionException e) {
- Log.e(TAG, "execution fail: ", e);
- }
- }
- }.start();
- task.waitUntilRunning();
- task.completeTask();
- assertEquals(0, task.get().intValue());
- }
-
- public void testConcurrentGetOnCancled() throws Exception {
- final TestTask task = new TestTask();
- new Thread() {
- @Override
- public void run() {
- try {
- assertCancellationException(task);
- } catch (Exception e) {
- Log.e(TAG, "Exception", e);
- }
- }
- }.start();
- task.waitUntilRunning();
- task.requestCancel();
- assertCancellationException(task);
- }
-
- private static class AddTask extends BaseCancelable<Integer> {
- private final Cancelable<Integer> mTasks[];
-
- public AddTask(Cancelable<Integer> ... tasks) {
- mTasks = tasks.clone();
- }
-
- @Override
- protected Integer execute() throws Exception {
- int sum = 0;
- for (int i = 0, n = mTasks.length; i < n; ++i) {
- sum += runSubTask(mTasks[i]);
- }
- return sum;
- }
- }
-
- public void testExecuteSubtask() throws Exception {
- TestTask subtask = new TestTask();
- @SuppressWarnings("unchecked")
- AddTask addTask = new AddTask(subtask);
- subtask.completeTask();
- assertEquals(0, addTask.get().intValue());
- }
-
- public void testExecuteSubtaskWithError() throws Exception {
- TestTask subtask = new TestTask();
- @SuppressWarnings("unchecked")
- AddTask addTask = new AddTask(subtask);
- subtask.completeTaskWithException();
- assertExecutionException(addTask);
- }
-
- public void testCancelWithSubtask() throws Exception {
- final TestTask subtask = new TestTask();
- @SuppressWarnings("unchecked")
- final AddTask addTask = new AddTask(subtask);
- new Thread() {
- @Override
- public void run() {
- try {
- subtask.waitUntilRunning();
- } catch (InterruptedException e) {
- Log.e(TAG, "interrupted", e);
- }
- addTask.requestCancel();
- }
- }.start();
- assertCancellationException(addTask);
- }
-
- private static class TaskSet extends BaseCancelable<Integer> {
- private final TestTask mTasks[];
- private int mExecutedTaskCount = 0;
-
- public TaskSet(TestTask ... tasks) {
- mTasks = tasks.clone();
- }
-
- @Override
- protected Integer execute() throws Exception {
- int exceptionCount = 0;
- for (TestTask task : mTasks) {
- try {
- ++ mExecutedTaskCount;
- runSubTask(task);
- } catch (ExecutionException e) {
- ++ exceptionCount;
- }
- }
- return exceptionCount;
- }
-
- }
-
- public void testHandleExceptionInSubTasks() throws Exception {
- TestTask task0 = new TestTask();
- TestTask task1 = new TestTask();
- TestTask task2 = new TestTask();
-
- task0.completeTask();
- task1.completeTaskWithException();
- task2.completeTask();
- TaskSet taskSet = new TaskSet(task0, task1, task2);
-
- assertEquals(1, taskSet.get().intValue());
- assertEquals(3, taskSet.mExecutedTaskCount);
- }
-}