diff options
-rw-r--r-- | src/com/android/camera/Camera.java | 6 | ||||
-rw-r--r-- | src/com/android/camera/CropImage.java | 5 | ||||
-rw-r--r-- | src/com/android/camera/ImageManager.java | 104 | ||||
-rw-r--r-- | src/com/android/camera/gallery/BaseCancelable.java | 164 | ||||
-rw-r--r-- | src/com/android/camera/gallery/BaseImage.java | 67 | ||||
-rw-r--r-- | src/com/android/camera/gallery/Cancelable.java | 52 | ||||
-rw-r--r-- | src/com/android/camera/gallery/Image.java | 27 | ||||
-rw-r--r-- | src/com/android/camera/gallery/ThreadSafeOutputStream.java | 67 | ||||
-rw-r--r-- | tests/src/com/android/camera/gallery/BaseCancelableUnitTests.java | 232 |
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); - } -} |